1. Visão geral
Introdução
Neste codelab, você vai aprender a implantar um serviço do Cloud Run que usa vários contêineres. Você vai criar um app Node.js que será usado como contêiner de entrada do Cloud Run e outro app Node.js para ser usado como arquivo secundário.
Visão geral técnica
Ao usar vários contêineres em uma instância do Cloud Run, um contêiner é usado como o principal para a entrada na Web. Um ou mais contêineres adicionais são chamados de arquivos secundários.
Há duas maneiras de vários contêineres se comunicarem entre si:
- Os contêineres compartilham a interface de rede do host local para que todos possam detectar uma porta. Por exemplo: localhost:port.
- Também é possível usar volumes na memória e montá-los nos contêineres para compartilhar arquivos.
Casos de uso
Como todos os contêineres na instância do Cloud Run compartilham a interface de rede do host local, é possível usar um arquivo secundário na frente do contêiner principal para fazer solicitações de proxy. Esses proxies podem fornecer uma camada adicional de abstração para um fluxo de tráfego mais eficiente para o aplicativo entre o cliente e os servidores, interceptando solicitações e encaminhando-as para o endpoint apropriado. Por exemplo, você pode usar a imagem Nginx oficial do DockerHub (conforme mostrado aqui).
Como vários contêineres podem se comunicar pelo compartilhamento de arquivos por volumes compartilhados, você adiciona vários aplicativos de arquivo secundário ao serviço. Por exemplo, é possível instrumentar o serviço do Cloud Run para usar agentes personalizados, como o OpenTelemetry, para exportar registros, métricas e traces (exemplo do OpenTelemetry). Outro exemplo é usar uma conexão de arquivo secundário a um banco de dados PostgreSQL do Cloud Spanner (exemplo de pós-gressão do Cloud Spanner).
Exemplos neste codelab
Neste codelab, você vai implantar primeiro um serviço do Cloud Run em que o contêiner de entrada se comunica com um arquivo secundário por uma porta localhost. Em seguida, você atualizará o contêiner de entrada e o arquivo secundário para compartilhar um arquivo por meio de uma montagem de volume.
O que você vai aprender
- Como criar um contêiner que usa um arquivo secundário
- Como um contêiner de entrada pode se comunicar com um arquivo secundário usando o localhost
- Como um contêiner de entrada e um arquivo secundário podem compartilhar um arquivo por meio de um volume montado
2. Configuração e requisitos
Pré-requisitos
- Você fez login no console do Cloud.
- Você já implantou um serviço do Cloud Run. Por exemplo, siga o guia de início rápido sobre a implantação de um serviço da Web pelo código-fonte.
Ativar o Cloud Shell
- No Console do Cloud, clique em Ativar o Cloud Shell.
Se você estiver iniciando o Cloud Shell pela primeira vez, verá uma tela intermediária com a descrição dele. Se aparecer uma tela intermediária, clique em Continuar.
Leva apenas alguns instantes para provisionar e se conectar ao Cloud Shell.
Essa máquina virtual tem todas as ferramentas de desenvolvimento necessárias. Ela oferece um diretório principal persistente de 5 GB, além de ser executada no Google Cloud. Isso aprimora o desempenho e a autenticação da rede. Grande parte do trabalho neste codelab, se não todo, pode ser feito em um navegador.
Depois de se conectar ao Cloud Shell, você verá sua autenticação e o projeto estará configurado com o ID do seu projeto.
- Execute o seguinte comando no Cloud Shell para confirmar se a conta está autenticada:
gcloud auth list
Resposta ao comando
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
- Execute o seguinte comando no Cloud Shell para confirmar que o comando gcloud sabe sobre seu projeto:
gcloud config list project
Resposta ao comando
[core] project = <PROJECT_ID>
Se o projeto não estiver configurado, configure-o usando este comando:
gcloud config set project <PROJECT_ID>
Resposta ao comando
Updated property [core/project].
3. Criar o app de entrada
Definir variáveis de ambiente
Neste codelab, você vai criar algumas variáveis de ambiente para melhorar a legibilidade dos comandos gcloud
usados.
REGION=<YOUR-REGION> PROJECT_ID=<YOUR-PROJECT-ID> SERVICE_NAME=sidecar-codelab REPO_NAME=sidecar-codelab
Crie um repositório do ArtifactRegistry para armazenar suas imagens de contêiner
É possível criar um repositório no Artifact Registry para armazenar as imagens de contêiner deste codelab.
gcloud artifacts repositories create $REPO_NAME --repository-format=docker \ --location=$REGION --description="sidecar codelab"
Em seguida, crie um arquivo package.json
com o seguinte conteúdo:
{ "name": "sidecar-codelab", "version": "1.0.0", "private": true, "description": "demonstrates how to use sidecars in cloud run", "main": "index.js", "author": "Google LLC", "license": "Apache-2.0", "scripts": { "start": "node ingress.js" }, "dependencies": { "axios": "^1.6.2", "express": "^4.18.2" } }
Agora crie um arquivo chamado ingress.js
com o seguinte conteúdo:
const express = require('express'); const app = express(); const axios = require("axios"); app.get('/', async (req, res) => { let response = await axios.get("http://localhost:5000"); res.send("The sidecar says: " + response.data); }); const port = parseInt(process.env.PORT) || 8080; app.listen(port, () => { console.log(`Ingress container listening on port ${port}`); });
Crie um dockerfile para o contêiner de entrada
FROM node:20.10.0-slim WORKDIR /usr/src/app COPY package*.json ./ RUN npm install --production # Copy local code to the container image. COPY . . # Run the web service on container startup. ENV PORT=8080 CMD [ "npm", "start" ]
E crie um arquivo ".dockerignore" para o contêiner de entrada.
# Exclude locally installed dependencies node_modules/ # Exclude "build-time" ignore files. .dockerignore .gcloudignore # Exclude git history and configuration. .gitignore
Agora é possível criar a imagem para o contêiner de entrada executando o seguinte comando:
gcloud builds submit --tag $REGION-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/ingress:latest
4. Criar o app secundário
Nesta seção, você vai criar um segundo app node.js que será usado como arquivo secundário no serviço do Cloud Run.
Navegue até o diretório secundário.
cd ../sidecar
Crie um arquivo package.json
com o seguinte conteúdo:
{ "name": "sidecar-codelab", "version": "1.0.0", "private": true, "description": "demonstrates how to use sidecars in cloud run", "main": "index.js", "author": "Google LLC", "license": "Apache-2.0", "scripts": { "start": "node sidecar.js" }, "dependencies": { "axios": "^1.6.2", "express": "^4.18.2" } }
Agora crie um arquivo chamado sidecar.js
com o seguinte conteúdo:
const express = require('express'); const app = express(); app.get('/', async (req, res) => { res.send("Hello ingress container! I'm the sidecar."); }); const port = parseInt(process.env.PORT || 5000); app.listen(port, () => { console.log(`Sidecar container listening on port ${port}`); });
Criar um Dockerfile para o contêiner de arquivo secundário
FROM node:20.10.0-slim WORKDIR /usr/src/app COPY package*.json ./ RUN npm install --production # Copy local code to the container image. COPY . . # Run the web service on container startup. ENV PORT=5000 CMD [ "npm", "start" ]
E crie um arquivo ".dockerignore" para o contêiner do arquivo secundário.
# Exclude locally installed dependencies node_modules/ # Exclude "build-time" ignore files. .dockerignore .gcloudignore # Exclude git history and configuration. .gitignore
Agora é possível criar a imagem para o contêiner de entrada executando o seguinte comando:
gcloud builds submit --tag $REGION-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/sidecar:latest
Implantar o serviço do Cloud Run
Você implantará o serviço do Cloud Run usando um arquivo yaml.
Navegue até o diretório pai.
cd ..
Crie um arquivo chamado sidecar-codelab.yaml
com o conteúdo a seguir.
apiVersion: serving.knative.dev/v1 kind: Service metadata: annotations: name: sidecar-codelab labels: cloud.googleapis.com/location: "<YOUR_REGION>" spec: template: spec: containers: - image: "<YOUR_REGION>-docker.pkg.dev/<YOUR_PROJECT_ID>/sidecar-codelab/ingress:latest" ports: - containerPort: 8080 - image: "<YOUR_REGION>-docker.pkg.dev/<YOUR_PROJECT_ID>/sidecar-codelab/sidecar:latest" env: - name: PORT value: "5000"
Em seguida, implante o serviço usando o comando a seguir. Você precisa usar a gcloud beta porque as montagens de volume estão em pré-lançamento público.
gcloud beta run services replace sidecar-codelab.yaml
Após a implantação, salve o URL do serviço em uma variável de ambiente.
SERVICE_URL=$(gcloud run services describe $SERVICE_NAME --platform managed --region $REGION --format 'value(status.url)')
5. Chamar o serviço do Cloud Run
Agora você pode chamar seu serviço fornecendo o token de identidade.
curl -X GET -H "Authorization: Bearer $(gcloud auth print-identity-token)" ${SERVICE_URL}
Os resultados serão parecidos com o exemplo de saída abaixo:
The sidecar says: Hello ingress container! I'm the sidecar.
6. Compartilhar um arquivo usando uma montagem de volume
Nesta seção, você vai atualizar os contêineres para compartilhar um arquivo por meio de uma montagem de volume. Neste exemplo, o contêiner de entrada gravará em um arquivo em um volume compartilhado. O arquivo secundário vai ler o arquivo e retornar o conteúdo ao contêiner de entrada.
Primeiro, você vai atualizar o código do contêiner de entrada. Navegue até o diretório de entrada.
cd ../ingress
e substitua o conteúdo do arquivo ingress.js
pelo seguinte:
const express = require('express'); const app = express(); const fs = require('fs'); const axios = require("axios"); const filename = "test.txt" let path = "/my-volume-mount"; app.use(path, express.static(path)); try { fs.writeFileSync(`${path}/${filename}`, "The ingress container created this file."); } catch (err) { console.error(err); } app.get('/', async (req, res) => { let response = await axios.get("http://localhost:5000"); res.send("The sidecar says: " + response.data); }); const port = parseInt(process.env.PORT) || 8080; app.listen(port, () => { console.log(`Ingress container listening on port ${port}`); });
Crie a nova imagem para o contêiner de entrada executando o seguinte comando:
gcloud builds submit --tag $REGION-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/ingress:latest
Acesse o diretório do arquivo secundário:
cd ../sidecar
E atualize sidecar.js
com o seguinte conteúdo:
const express = require('express'); const app = express(); const fs = require('fs'); const filename = "test.txt" let path = "/my-volume-mount"; app.use(path, express.static(path)); async function readFile() { try { return await fs.readFileSync(`${path}/${filename}`, { encoding: 'utf8' }); } catch (err) { console.log(err); } } app.get('/', async (req, res) => { let contents = await readFile(); res.send(contents); }); const port = parseInt(process.env.PORT || 5000); app.listen(port, () => { console.log(`Sidecar container listening on port ${port}`); });
E crie a nova imagem para o contêiner de arquivo secundário executando o seguinte comando:
gcloud builds submit --tag $REGION-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/sidecar:latest
Atualize o sidecar-codelab.yaml
com o seguinte para compartilhar um volume:
apiVersion: serving.knative.dev/v1 kind: Service metadata: annotations: name: sidecar-codelab labels: cloud.googleapis.com/location: "<YOUR_REGION>" spec: template: spec: containers: - image: "<YOUR_REGION>-docker.pkg.dev/<YOUR_PROJECT_ID>/sidecar-codelab/ingress:latest" ports: - containerPort: 8080 volumeMounts: - mountPath: /my-volume-mount name: in-memory-1 - image: "<YOUR_REGION>-docker.pkg.dev/<YOUR_PROJECT_ID>/sidecar-codelab/sidecar:latest" env: - name: PORT value: "5000" volumeMounts: - mountPath: /my-volume-mount name: in-memory-1 volumes: - emptyDir: medium: Memory name: in-memory-1
Implante o arquivo sidecar-codelab.yaml
atualizado
gcloud beta run services replace sidecar-codelab.yaml
Agora você pode chamar seu serviço fornecendo o token de identidade.
curl -X GET -H "Authorization: Bearer $(gcloud auth print-identity-token)" ${SERVICE_URL}
Os resultados serão parecidos com o exemplo de saída abaixo:
The sidecar says: the ingress container created this file.
7. Parabéns!
Parabéns por concluir o codelab.
Recomendamos a leitura da documentação sobre o Cloud Run, mais especificamente sobre a implantação de vários contêineres e o uso de montagens de volume na memória.
O que vimos
- Como criar um contêiner que usa um arquivo secundário
- Como um contêiner de entrada pode se comunicar com um arquivo secundário usando o localhost
- Como um contêiner de entrada e um arquivo secundário podem compartilhar um volume montado
8. Limpar
Para evitar cobranças acidentais, por exemplo, se essa função do Cloud for invocada mais vezes do que sua alocação mensal de invocação do Cloud Run no nível sem custo financeiro, exclua o serviço do Cloud Run ou o projeto criado na etapa 2.
Para excluir a função do Cloud, acesse o Console do Cloud Functions em https://console.cloud.google.com/run/ e exclua o serviço sidecar-codelab
(ou $SERVICE_NAME, caso você tenha usado um nome diferente).
Se você optar por excluir o projeto inteiro, acesse https://console.cloud.google.com/cloud-resource-manager, selecione o projeto criado na etapa 2 e escolha "Excluir". Se você excluir o projeto, precisará alterar os projetos no SDK Cloud. Para conferir a lista de todos os projetos disponíveis, execute gcloud projects list
.