Combine tudo: exemplo de cenário de resolução de problemas


Compreender as ferramentas de resolução de problemas individuais do Google Kubernetes Engine (GKE) é útil, mas vê-las usadas em conjunto para resolver um problema do mundo real pode ajudar a consolidar os seus conhecimentos.

Siga um exemplo orientado que combina a utilização da Google Cloud consola, da ferramenta de linha de comandos kubectl, do Cloud Logging e do Cloud Monitoring para identificar a causa principal de um erro OutOfMemory (OOMKilled).

Este exemplo é benéfico para qualquer pessoa que queira ver uma aplicação prática das técnicas de resolução de problemas descritas nesta série, particularmente para administradores e operadores da plataforma, bem como programadores de aplicações. Para mais informações sobre as funções comuns e as tarefas de exemplo a que fazemos referência no Google Cloud conteúdo, consulte Funções e tarefas comuns do utilizador do GKE.

O cenário

É o engenheiro de serviço para uma app Web denominada product-catalog que é executada no GKE.

A investigação começa quando recebe um alerta automático do Cloud Monitoring:

Alert: High memory utilization for container 'product-catalog' in 'prod' cluster.

Este alerta indica que existe um problema e que este está relacionado com a carga de trabalho product-catalog.

Confirme o problema na Google Cloud consola

Começa com uma vista de alto nível das suas cargas de trabalho para confirmar o problema.

  1. Na Google Cloud consola, navegue para a página Workloads e filtre a sua carga de trabalho product-catalog.
  2. Consultar a coluna de estado Pods. Em vez do valor normal 3/3, vê o valor a apresentar constantemente um estado não normal: 2/3. Este valor indica que um dos pods da sua app não tem o estado Ready.
  3. Quer investigar mais a fundo, por isso, clica no nome da carga de trabalho para aceder à respetiva página de detalhes.product-catalog
  4. Na página de detalhes, veja a secção Pods geridos. Identifica imediatamente um problema: a coluna Restarts para o seu agrupamento mostra 14, um número invulgarmente elevado.

Esta elevada contagem de reinícios confirma que o problema está a causar instabilidade na app e sugere que um contentor está a falhar nas respetivas verificações de estado ou a falhar.

Encontre o motivo com os comandos kubectl

Agora que sabe que a sua app está a ser reiniciada repetidamente, tem de descobrir o motivo. O comando kubectl describe é uma boa ferramenta para este efeito.

  1. Obtém o nome exato do pod instável:

    kubectl get pods -n prod
    

    O resultado é o seguinte:

    NAME                             READY  STATUS            RESTARTS  AGE
    product-catalog-d84857dcf-g7v2x  0/1    CrashLoopBackOff  14        25m
    product-catalog-d84857dcf-lq8m4  1/1    Running           0         2h30m
    product-catalog-d84857dcf-wz9p1  1/1    Running           0         2h30m
    
  2. Descreve o pod instável para obter o histórico detalhado de eventos:

    kubectl describe pod product-catalog-d84857dcf-g7v2x -n prod
    
  3. Reveja o resultado e encontre pistas nas secções Last State e Events:

    Containers:
      product-catalog-api:
        ...
        State:          Waiting
          Reason:       CrashLoopBackOff
        Last State:     Terminated
          Reason:       OOMKilled
          Exit Code:    137
          Started:      Mon, 23 Jun 2025 10:50:15 -0700
          Finished:     Mon, 23 Jun 2025 10:54:58 -0700
        Ready:          False
        Restart Count:  14
    ...
    Events:
      Type     Reason     Age                           From                Message
      ----     ------     ----                          ----                -------
      Normal   Scheduled  25m                           default-scheduler   Successfully assigned prod/product-catalog-d84857dcf-g7v2x to gke-cs-cluster-default-pool-8b8a777f-224a
      Normal   Pulled     8m (x14 over 25m)             kubelet             Container image "us-central1-docker.pkg.dev/my-project/product-catalog/api:v1.2" already present on machine
      Normal   Created    8m (x14 over 25m)             kubelet             Created container product-catalog-api
      Normal   Started    8m (x14 over 25m)             kubelet             Started container product-catalog-api
      Warning  BackOff    3m (x68 over 22m)             kubelet             Back-off restarting failed container
    

    O resultado dá-lhe duas pistas importantes:

    • Primeiro, a secção Last State mostra que o contentor foi terminado com Reason: OOMKilled, o que indica que ficou sem memória. Este motivo é confirmado pelo Exit Code: 137, que é o código de saída padrão do Linux para um processo que foi terminado devido ao consumo excessivo de memória.
    • Em segundo lugar, a secção Events mostra um evento Warning: BackOff com a mensagem Back-off restarting failed container. Esta mensagem confirma que o contentor está num ciclo de falhas, que é a causa direta do estado CrashLoopBackOff que viu anteriormente.

Visualize o comportamento com métricas

O comando kubectl describe indicou o que aconteceu, mas o Cloud Monitoring pode mostrar-lhe o comportamento do seu ambiente ao longo do tempo.

  1. Na Google Cloud consola, aceda ao Explorador de métricas.
  2. Seleciona a métrica container/memory/used_bytes.
  3. Filtra a saída até ao cluster, namespace e nome do pod específicos.

O gráfico mostra um padrão distinto: a utilização de memória aumenta de forma constante e, em seguida, diminui abruptamente para zero quando o contentor é terminado por falta de memória e reinicia. Estas provas visuais confirmam uma fuga de memória ou um limite de memória insuficiente.

Encontre a causa principal nos registos

Agora, sabe que o contentor está a ficar sem memória, mas ainda não sabe exatamente porquê. Para descobrir a causa principal, use o Explorador de registos.

  1. Na Google Cloud consola, navegue para o Explorador de registos.
  2. Escreve uma consulta para filtrar os registos do seu contentor específico apenas antes da hora da última falha de sistema (que viu no resultado do comando kubectl describe):

    resource.type="k8s_container"
    resource.labels.cluster_name="example-cluster"
    resource.labels.namespace_name="prod"
    resource.labels.pod_name="product-catalog-d84857dcf-g7v2x"
    timestamp >= "2025-06-23T17:50:00Z"
    timestamp < "2025-06-23T17:55:00Z"
    
  3. Nos registos, encontra um padrão repetitivo de mensagens imediatamente antes de cada falha do sistema:

    {
      "message": "Processing large image file product-image-large.jpg",
      "severity": "INFO"
    },
    {
      "message": "WARN: Memory cache size now at 248MB, nearing limit.",
      "severity": "WARNING"
    }
    

Estas entradas de registo indicam que a app está a tentar processar ficheiros de imagem grandes carregando-os totalmente na memória, o que acaba por esgotar o limite de memória do contentor.

As conclusões

Ao usar as ferramentas em conjunto, tem uma imagem completa do problema:

  • O alerta de monitorização notificou que existia um problema.
  • A Google Cloud consola mostrou-lhe que o problema estava a afetar utilizadores (reinícios).
  • Os comandos kubectl indicaram o motivo exato dos reinícios (OOMKilled).
  • O explorador de métricas visualizou o padrão de fuga de memória ao longo do tempo.
  • O Explorador de registos revelou o comportamento específico que estava a causar o problema de memória.

Já pode implementar uma solução. Pode otimizar o código da app para processar ficheiros grandes de forma mais eficiente ou, como correção a curto prazo, aumentar o limite de memória do contentor (especificamente, o valor spec.containers.resources.limits.memory) no manifesto YAML da carga de trabalho.

O que se segue?