Neste tutorial, mostramos como um desenvolvedor de serviços pode resolver problemas de um serviço do Cloud Run corrompido usando as ferramentas do Google Cloud Observability para descoberta e um fluxo de trabalho de desenvolvimento local para investigação.
Neste "tutorial de estudo de caso" passo a passo do guia de solução de problemas é usado um projeto de amostra que resulta em erros de ambiente de execução quando implantados, que você soluciona para encontrar e corrigir o problema.
Objetivos
- Escrever, criar e implantar um serviço no Cloud Run
- Use o Error Reporting e o Cloud Logging para identificar um erro
- Recuperar a imagem do contêiner do Container Registry para uma análise de causa raiz
- Corrigir o serviço de "produção" e melhorá-lo para reduzir problemas futuros
Custos
Neste documento, você usará os seguintes componentes faturáveis do Google Cloud:
Para gerar uma estimativa de custo baseada na projeção de uso deste tutorial, use a calculadora de preços.
Antes de começar
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
- Ative a API Cloud Run Admin
- Instale e inicialize a CLI gcloud.
- Atualize os componentes:
gcloud components update
- Siga as instruções para instalar o Docker localmente
Funções exigidas
Para conseguir as permissões necessárias para concluir o tutorial, peça ao administrador para conceder a você os seguintes papéis do IAM no seu projeto:
-
Editor do Cloud Build (
roles/cloudbuild.builds.editor
) -
Administrador do Cloud Run (
roles/run.admin
) -
Leitor do Error Reporting (
roles/errorreporting.viewer
) -
Acessador de exibição de registros (
roles/logging.viewAccessor
) -
Administrador de projetos do IAM (
roles/resourcemanager.projectIamAdmin
) -
Usuário da conta de serviço (
roles/iam.serviceAccountUser
) -
Consumidor do Service Usage (
roles/serviceusage.serviceUsageConsumer
) -
Administrador de armazenamento (
roles/storage.admin
)
Para mais informações sobre a concessão de papéis, consulte Gerenciar o acesso a projetos, pastas e organizações.
Também é possível conseguir as permissões necessárias por meio de papéis personalizados ou de outros papéis predefinidos.
Como configurar padrões do gcloud
Para configurar a gcloud com os padrões do serviço do Cloud Run, realize as etapas a seguir:
Defina seu projeto padrão:
gcloud config set project PROJECT_ID
Substitua PROJECT_ID pelo nome do projeto que você criou para este tutorial.
Configure a gcloud para a região escolhida:
gcloud config set run/region REGION
Substitua REGION pela região compatível do Cloud Run.
Locais do Cloud Run
O Cloud Run é regional, o que significa que a infraestrutura que executa seus serviços do Cloud Run está localizada em uma região específica e é gerenciada pelo Google para estar disponível de maneira redundante em todas as zonas da região.
Atender aos seus requisitos de latência, disponibilidade ou durabilidade são os principais fatores para selecionar a região em que seus serviços do Cloud Run são executados.
Geralmente, é possível selecionar a região mais próxima de seus usuários, mas considere a localização dos outros produtos do Google Cloud usados pelo serviço do Cloud Run.
O uso de produtos do Google Cloud em vários locais pode afetar a latência e o custo do serviço.
O Cloud Run está disponível nas regiões a seguir:
Sujeitas aos preços do nível 1
asia-east1
(Taiwan)asia-northeast1
(Tóquio)asia-northeast2
(Osaka)europe-north1
(Finlândia) Baixo CO2europe-southwest1
(Madri) Baixo CO2europe-west1
(Bélgica) Baixo CO2europe-west4
(Países Baixos) Baixo CO2europe-west8
(Milão)europe-west9
(Paris) Baixo CO2me-west1
(Tel Aviv)us-central1
(Iowa) Baixo CO2us-east1
(Carolina do Sul)us-east4
(Norte da Virgínia)us-east5
(Columbus)us-south1
(Dallas) Baixo CO2us-west1
(Oregon) Baixo CO2
Sujeitas aos preços do nível 2
africa-south1
(Johannesburgo)asia-east2
(Hong Kong)asia-northeast3
(Seul, Coreia do Sul)asia-southeast1
(Singapura)asia-southeast2
(Jacarta)asia-south1
(Mumbai, Índia)asia-south2
(Déli, Índia)australia-southeast1
(Sydney)australia-southeast2
(Melbourne)europe-central2
(Varsóvia, Polônia)europe-west10
(Berlim) Baixo CO2europe-west12
(Turim)europe-west2
(Londres, Reino Unido) Baixo CO2europe-west3
(Frankfurt, Alemanha) Baixo CO2europe-west6
(Zurique, Suíça) Baixo CO2me-central1
(Doha)me-central2
(Damã)northamerica-northeast1
(Montreal) Baixo CO2northamerica-northeast2
(Toronto) Baixo CO2southamerica-east1
(São Paulo, Brasil) Baixo CO2southamerica-west1
(Santiago, Chile) Baixo CO2us-west2
(Los Angeles)us-west3
(Salt Lake City)us-west4
(Las Vegas)
Se você já criou um serviço do Cloud Run, é possível visualizar a região no painel do Cloud Run no console do Google Cloud.
Como montar o código
Crie um novo serviço completo do Cloud Run passo a passo. Lembre-se de que esse serviço cria um erro de ambiente de execução de propósito para o exercício de solução de problemas.
Crie um novo projeto:
Node.js
Crie um projeto Node.js definindo o pacote de serviços, as dependências iniciais e algumas operações comuns.Crie um novo diretório
hello-service
:mkdir hello-service cd hello-service
Crie um novo projeto Node.js gerando um arquivo
package.json
:npm init --yes npm install --save express@4
Abra o novo arquivo
package.json
no seu editor e configure um scriptstart
para executarnode index.js
. Quando terminar, o arquivo terá esta aparência:
Se você continuar a evoluir esse serviço além do tutorial imediato, preencha a descrição, o autor e avalie a licença. Para mais detalhes, leia a documentação do package.json.
Python
Crie um novo diretório
hello-service
:mkdir hello-service cd hello-service
Crie um arquivo requirements.txt e copie suas dependências para ele:
Go
Crie um novo diretório
hello-service
:mkdir hello-service cd hello-service
Crie um projeto em Go inicializando um novo módulo go:
go mod init example.com/hello-service
É possível atualizar o nome específico como você quiser: atualize o nome se o código for publicado em um repositório de código acessível pela web.
Java
Crie um novo projeto de instrução:
mvn archetype:generate \ -DgroupId=com.example.cloudrun \ -DartifactId=hello-service \ -DarchetypeArtifactId=maven-archetype-quickstart \ -DinteractiveMode=false
Copie as dependências para sua lista de dependências
pom.xml
(entre os elementos<dependencies>
):Copie a configuração de build para o
pom.xml
(nos elementos<dependencies>
):
Crie um serviço HTTP para lidar com solicitações de entrada:
Node.js
Python
Go
Java
Crie um
Dockerfile
para definir a imagem do contêiner usada para implantar o serviço:Node.js
Python
Go
Java
Esta amostra usa o Jib (em inglês) para criar imagens do Docker usando ferramentas comuns do Java. O Jib otimiza builds de contêiner sem a necessidade de um Dockerfile ou de ter o Docker (em inglês) instalado. Saiba mais sobre como criar contêineres Java com o Jib.
Como enviar o código
O código de envio consiste em três etapas: criar uma imagem de contêiner com o Cloud Build, fazer upload da imagem de contêiner no Container Registry e implantar a imagem de contêiner no Cloud Run.
Para enviar seu código, siga estas etapas:
Compile seu contêiner e publique no Container Registry.
Node.js
gcloud builds submit --tag gcr.io/PROJECT_ID/hello-service
em que PROJECT_ID é o ID do projeto no Google Cloud. Verifique o ID do projeto atual com
gcloud config get-value project
.Após a conclusão, você verá uma mensagem de "SUCESSO" contendo o ID, a hora da criação e o nome da imagem. A imagem é armazenada no Container Registry e poderá ser reutilizada, se você quiser.
Python
gcloud builds submit --tag gcr.io/PROJECT_ID/hello-service
em que PROJECT_ID é o ID do projeto no Google Cloud. Verifique o ID do projeto atual com
gcloud config get-value project
.Após a conclusão, você verá uma mensagem de "SUCESSO" contendo o ID, a hora da criação e o nome da imagem. A imagem é armazenada no Container Registry e poderá ser reutilizada, se você quiser.
Go
gcloud builds submit --tag gcr.io/PROJECT_ID/hello-service
em que PROJECT_ID é o ID do projeto no Google Cloud. Verifique o ID do projeto atual com
gcloud config get-value project
.Após a conclusão, você verá uma mensagem de "SUCESSO" contendo o ID, a hora da criação e o nome da imagem. A imagem é armazenada no Container Registry e poderá ser reutilizada, se você quiser.
Java
- Use o auxiliar de credencial do gcloud
para autorizar o Docker a enviar por push ao Container Registry.
gcloud auth configure-docker
- Use o plug-in do Maven do Jib para criar e enviar por push o contêiner ao Container Registry.
mvn compile jib:build -Dimage=gcr.io/PROJECT_ID/hello-service
em que PROJECT_ID é o ID do projeto no Google Cloud. Verifique o ID do projeto atual com
gcloud config get-value project
.Após a conclusão, você verá uma mensagem "BUILD SUCCESS". A imagem é armazenada no Container Registry e poderá ser reutilizada, se você quiser.
- Use o auxiliar de credencial do gcloud
para autorizar o Docker a enviar por push ao Container Registry.
Execute o comando a seguir para implantar o app:
gcloud run deploy hello-service --image gcr.io/PROJECT_ID/hello-service
Substitua PROJECT_ID pelo ID do projeto do Google Cloud.
hello-service
é o nome da imagem do contêiner e do serviço Cloud Run. Observe que a imagem do contêiner é implantada no serviço e na região que você configurou anteriormente em Como configurar o gcloudResponda
y
, "Sim", ao prompt allow unauthenticated. Consulte Como gerenciar o acesso para mais detalhes sobre a autenticação baseada em IAM.Aguarde até que a implantação esteja concluída. Isso pode levar cerca de 30 segundos. Em caso de sucesso, a linha de comando exibe o URL de serviço.
Testar
Teste o serviço para confirmar que o implantou. As solicitações falham com um erro HTTP 500 ou 503 (membros da classe Erros de servidor 5xx). O tutorial explica a solução de problemas dessa resposta de erro.
O serviço recebe um URL navegável automaticamente.
Navegue até este URL com seu navegador da Web:
Abra um navegador da Web.
Encontre a saída do URL de serviço pelo comando de implantação anterior.
Se o comando de implantação não fornecer um URL, algo deu errado. Analise a mensagem de erro e aja de acordo: se nenhuma orientação acionável estiver presente, consulte o guia de solução de problemas e tente novamente o comando de implantação.
Navegue até esse URL copiando-o para a barra de endereço do seu navegador e pressionando ENTER.
Veja o erro HTTP 500 ou HTTP 503.
Se você receber um erro HTTP 403, talvez tenha rejeitado
allow unauthenticated invocations
no prompt de implantação. Conceda acesso não autenticado ao serviço para corrigir isso:gcloud run services add-iam-policy-binding hello-service \ --member="allUsers" \ --role="roles/run.invoker"
Para mais informações, leia Como permitir acesso público (não-autenticado).
Como investigar o problema
Veja que o erro HTTP 5xx encontrado acima em Como testar foi encontrado como um erro de ambiente de execução de produção. Este tutorial aborda um processo formal para lidar com ele. Embora os processos de resolução de erros de produção variem muito, este tutorial apresenta uma sequência específica de etapas para mostrar a aplicação de ferramentas e técnicas úteis.
Para investigar esse problema, siga estas etapas:
- Colete mais detalhes sobre o erro relatado para ajudar na investigação e definir uma estratégia de mitigação.
- Alivie o impacto do usuário decidindo avançar em uma correção ou reversão para uma versão íntegra conhecida.
- Reproduza o erro para confirmar se os detalhes corretos foram coletados e se o erro não é uma falha única.
- Realize uma análise de causa-raiz no bug para encontrar o código, a configuração ou o processo que criou o erro.
No início da investigação, há um URL, um carimbo de data/hora e a mensagem "Erro interno do servidor".
Como coletar mais detalhes
Reúna mais informações sobre o problema para entender o que aconteceu e determinar as próximas etapas.
Use as ferramentas disponíveis do Google Cloud Observability para coletar mais detalhes:
Use o console do Error Reporting, que fornece um painel com detalhes e rastreamento de recorrência para erros com um rastreamento de pilha reconhecido.
Clique no erro para ver os detalhes do rastreamento de pilha, observando as chamadas de função feitas pouco antes do erro.
Use o Cloud Logging para analisar a sequência de operações que levam ao problema, incluindo mensagens de erro que não estão incluídas no console do Error Reporting devido à falta de um rastreamento de pilha de erros reconhecido:
Acessar o Console do Cloud Logging
Selecione Revisão do Cloud Run > hello-service na primeira caixa suspensa. Isso filtra as entradas de registro para aquelas geradas pelo serviço.
Leia mais sobre como visualizar registros no Cloud Run
Reverter para uma versão íntegra
Se esse for um serviço estabelecido, conhecido por funcionar, haverá uma revisão anterior do serviço no Cloud Run. Este tutorial usa um novo serviço sem versões anteriores. Portanto, não é possível fazer uma reversão.
No entanto, se você tiver um serviço com versões anteriores para reverter, siga Como visualizar detalhes da revisão para extrair o nome do contêiner e os detalhes de configuração necessários para criar uma nova implantação íntegra do serviço.
Como reproduzir o erro
Usando os detalhes que você recebeu anteriormente, confirme se o problema ocorre de forma consistente nas condições de teste.
Envie a mesma solicitação HTTP testando-a novamente e veja se o mesmo erro e detalhes são relatados. Pode levar algum tempo para que os detalhes do erro sejam exibidos.
Como o serviço de amostra neste tutorial é somente leitura e não aciona efeitos secundários de complicações, a reprodução de erros na produção é segura. No entanto, para muitos serviços reais, isso não acontecerá: talvez seja necessário reproduzir erros em um ambiente de teste ou limitar essa etapa à investigação local.
A reprodução do erro estabelece o contexto para trabalhos futuros. Por exemplo, se os desenvolvedores não conseguirem reproduzir o erro, investigações adicionais podem exigir instrumentação adicional do serviço.
Como realizar uma análise de causa raiz
A análise da causa raiz é uma etapa importante na solução de problemas eficaz para garantir que você corrija o problema em vez do sintoma.
Anteriormente neste tutorial, você reproduziu o problema no Cloud Run, que confirma que o problema está ativo quando o serviço está hospedado no Cloud Run. Agora, reproduza o problema localmente para determinar se ele está isolado do código ou se ele só aparece na hospedagem de produção.
Se você não tiver usado a CLI do Docker localmente com o Container Registry, faça a autenticação com o gcloud:
gcloud auth configure-docker
Para abordagens alternativas, consulte Métodos de autenticação do Container Registry.
Se o nome da imagem do contêiner usado mais recentemente não estiver disponível, a descrição do serviço terá as informações da imagem do contêiner implantada mais recentemente:
gcloud run services describe hello-service
Encontre o nome da imagem do contêiner dentro do objeto
spec
. Um comando mais segmentado pode recuperá-lo diretamente:gcloud run services describe hello-service \ --format="value(spec.template.spec.containers.image)"
Esse comando revela um nome de imagem de contêiner como
gcr.io/PROJECT_ID/hello-service
.Extraia a imagem do contêiner do Container Registry para seu ambiente. Essa etapa pode levar alguns minutos para fazer o download da imagem do contêiner:
docker pull gcr.io/PROJECT_ID/hello-service
Atualizações posteriores na imagem do contêiner que reutilizam esse nome podem ser recuperadas com o mesmo comando. Se você pular esta etapa, o comando
docker run
abaixo extrairá uma imagem de contêiner se ela não estiver presente na máquina local.Execute localmente para confirmar que o problema não é exclusivo do Cloud Run:
PORT=8080 && docker run --rm -e PORT=$PORT -p 9000:$PORT \ gcr.io/PROJECT_ID/hello-service
Analisando os elementos do comando acima:
- A variável de ambiente
PORT
é usada pelo serviço para determinar a porta a ser ouvida no contêiner. - O comando
run
inicia o contêiner, assumindo como padrão o comando entrypoint definido no Dockerfile ou em uma imagem de contêiner pai. - A sinalização
--rm
exclui a instância do contêiner na saída. - A sinalização
-e
atribui um valor a uma variável de ambiente.-e PORT=$PORT
está propagando a variávelPORT
do sistema local para o contêiner com o mesmo nome de variável. - A sinalização
-p
publica o contêiner como um serviço disponível no localhost na porta 9000. Solicitações para localhost:9000 serão roteadas para o contêiner na porta 8080. Isso significa que a saída do serviço sobre o número da porta em uso não corresponde à forma como o serviço é acessado. - O argumento final
gcr.io/PROJECT_ID/hello-service
é uma imagem de contêinertag
, um rótulo legível para o identificador de hash sha256 de uma imagem de contêiner. Se não estiver disponível localmente, o docker tentará recuperar a imagem de um registro remoto.
No navegador, abra http://localhost:9000. Verifique se há mensagens de erro na saída do terminal em {ops_name}}.
Se o problema não for reproduzível localmente, ele poderá ser exclusivo para o ambiente do Cloud Run. Consulte o guia de solução de problemas do Cloud Run para conhecer áreas específicas.
Nesse caso, o erro é reproduzido localmente.
- A variável de ambiente
Agora que o erro foi confirmado duplamente como persistente e causado pelo código de serviço em vez da plataforma de hospedagem, é hora de investigar o código mais de perto.
Para os fins deste tutorial, é seguro presumir que o código dentro do contêiner e o código no sistema local sejam idênticos.
Revise o rastreamento de pilha do relatório de erros e faça referência cruzada com o código para encontrar as linhas específicas com falha.
Node.js
Encontre a origem da mensagem de erro no arquivoindex.js
ao redor do número de linha chamado no rastreamento de pilha mostrado nos registros:
Python
Encontre a origem da mensagem de erro no arquivomain.py
ao redor do número de linha chamado no rastreamento de pilha mostrado nos registros:
Go
Encontre a origem da mensagem de erro no arquivo main.go
ao redor do número de linha chamado no rastreamento de pilha mostrado nos registros:
Java
Encontre a origem da mensagem de erro no arquivo App.java
ao redor do número de linha chamado no rastreamento de pilha mostrado nos registros:
Ao examinar esse código, as seguintes ações são realizadas quando a variável de ambiente NAME
não está definida:
- Um erro é registrado no Google Cloud Observability
- Uma resposta de erro HTTP é enviada
O problema é causado por uma variável ausente, mas a causa raiz é mais específica: a alteração de código que adiciona a dependência de uma variável de ambiente não inclui alterações relacionadas aos scripts de implantação e documentação de requisitos de ambiente de execução.
Como corrigir a causa raiz
Agora que coletamos o código e identificamos a possível causa raiz, podemos tomar medidas para corrigi-lo.
Verifique se o serviço funciona localmente com o ambiente
NAME
disponível no local:Execute o contêiner localmente com a variável de ambiente adicionada:
PORT=8080 && docker run --rm -e PORT=$PORT -p 9000:$PORT \ -e NAME="Local World!" \ gcr.io/PROJECT_ID/hello-service
Navegue para http://localhost:9000.
Consulte "Hello Local World!" que aparece na página.
Modifique o ambiente de execução do Cloud Run para incluir essa variável:
Execute o comando de atualização de serviços para adicionar uma variável de ambiente:
gcloud run services update hello-service \ --set-env-vars NAME=Override
Aguarde alguns segundos enquanto o Cloud Run cria uma nova revisão com base na revisão anterior com a nova variável de ambiente adicionada.
Confirme se o serviço foi corrigido:
- Navegue até o URL do serviço do Cloud Run.
- Consulte "Hello Override!" que aparece na página.
- Certifique-se de que mensagens ou erros inesperados não apareçam no Cloud Logging ou no Error Reporting.
Como melhorar a velocidade das futuras soluções de problemas
Neste exemplo de problema de produção, o erro estava relacionado à configuração operacional. Há alterações de código que minimizam o impacto desse problema no futuro.
- Melhore o registro de erros para incluir detalhes mais específicos.
- Em vez de retornar um erro, faça com que o serviço retorne a um padrão seguro. Se o uso de um padrão representar uma alteração na funcionalidade normal, use uma mensagem de aviso para fins de monitoramento.
Vamos remover a variável de ambiente NAME
como uma dependência forçada.
Remova o código de manipulação
NAME
atual:Node.js
Python
Go
Java
Adicione o novo código que define um valor substituto:
Node.js
Python
Go
Java
Teste localmente recriando e executando o contêiner por meio dos casos de configuração afetados:
Node.js
docker build --tag gcr.io/PROJECT_ID/hello-service .
Python
docker build --tag gcr.io/PROJECT_ID/hello-service .
Go
docker build --tag gcr.io/PROJECT_ID/hello-service .
Java
mvn compile jib:build
Confirme se a variável de ambiente
NAME
ainda funciona:PORT=8080 && docker run --rm -e PORT=$PORT -p 9000:$PORT \ -e NAME="Robust World" \ gcr.io/PROJECT_ID/hello-service
Confirme se o serviço funciona sem a variável
NAME
:PORT=8080 && docker run --rm -e PORT=$PORT -p 9000:$PORT \ gcr.io/PROJECT_ID/hello-service
Se o serviço não retornar um resultado, confirme a remoção do código na primeira etapa que não removeu linhas extras, como aquelas usadas para gravar a resposta.
Implemente esse recurso revisitando a seção Implantar seu código.
Cada implantação em um serviço cria uma nova revisão e inicia automaticamente o tráfego de serviço quando estiver pronto.
Para limpar as variáveis de ambiente definidas anteriormente:
gcloud run services update hello-service --clear-env-vars
Adicione a nova funcionalidade do valor padrão à cobertura de teste automatizada do serviço.
Como encontrar outros problemas nos registros
Talvez você veja outros problemas no Visualizador de registros deste serviço. Por exemplo, uma chamada de sistema incompatível aparecerá nos registros como uma "Limitação do sandbox de contêiner".
Por exemplo, os serviços do Node.js às vezes resultam nesta mensagem de registro:
Container Sandbox Limitation: Unsupported syscall statx(0xffffff9c,0x3e1ba8e86d88,0x0,0xfff,0x3e1ba8e86970,0x3e1ba8e86a90). Please, refer to https://gvisor.dev/c/linux/amd64/statx for more information.
Nesse caso, a falta de suporte não afeta o serviço de amostra hello-service.
Solução de problemas do Terraform
Para resolver problemas ou dúvidas relacionadas ao Terraform, consulte Solução de problemas de validação de políticas do Terraform ou entre em contato com o suporte do Terraform.
Limpar
Se você criou um novo projeto para este tutorial, exclua o projeto. Se você usou um projeto atual e quer mantê-lo sem as alterações incluídas neste tutorial, exclua os recursos criados para o tutorial.
Como excluir o projeto
O jeito mais fácil de evitar cobranças é excluindo o projeto que você criou para o tutorial.
Para excluir o projeto:
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
Como excluir recursos do tutorial
Exclua o serviço do Cloud Run que você implantou neste tutorial:
gcloud run services delete SERVICE-NAME
SERVICE-NAME é o nome escolhido do serviço.
Também é possível excluir os serviços do Cloud Run no Console do Google Cloud.
Remova a configuração da região padrão da gcloud que você adicionou durante a configuração do tutorial:
gcloud config unset run/region
Remova a configuração do projeto:
gcloud config unset project
Exclua outros recursos do Google Cloud criados neste tutorial:
- Exclua a imagem do contêiner denominada
gcr.io/<var>PROJECT_ID</var>/hello-service
do Container Registry.
- Exclua a imagem do contêiner denominada
A seguir
- Saiba mais sobre como usar o Cloud Logging e o Error Reporting para ter insights sobre o comportamento de produção.
- Para mais informações sobre a solução de problemas do Cloud Run, consulte o guia de solução de problemas.
- Confira arquiteturas de referência, diagramas e práticas recomendadas do Google Cloud. Confira o Centro de arquitetura do Cloud.