Os pods do Kubernetes podem falhar de muitas maneiras, e cada estado de falha conta uma história diferente. Seja enfrentando CrashLoopBackOff, ImagePullBackOff, Pending, OOMKilled ou outros estados de erro, saber como diagnosticar e corrigir esses problemas sistematicamente é essencial para qualquer operador de Kubernetes. Este guia percorre os estados de falha mais comuns, os comandos kubectl para diagnosticá-los e estratégias comprovadas para resolver cada um.

Pré-requisitos

  • Um cluster Kubernetes em execução (v1.24 ou posterior recomendado)
  • kubectl instalado e configurado com acesso ao cluster
  • Conhecimento básico de objetos Kubernetes (pods, deployments, services)
  • Permissões para ler pods, eventos e recursos de nós no namespace alvo
  • Familiaridade com conceitos de contêineres (imagens, registros, limites de recursos)

Entendendo o Ciclo de Vida dos Pods e seus Estados

Antes de mergulhar na solução de problemas, é útil entender o ciclo de vida de um pod no Kubernetes. Um pod passa por várias fases:

FaseDescrição
PendingPod aceito pelo cluster, mas um ou mais contêineres ainda não estão executando
RunningPod vinculado a um nó e todos os contêineres iniciados
SucceededTodos os contêineres terminaram com sucesso (código de saída 0)
FailedTodos os contêineres terminaram e pelo menos um saiu com erro
UnknownEstado do pod não pode ser determinado, geralmente por falha na comunicação com o nó

Dentro dessas fases, os contêineres podem entrar em estados de espera específicos que indicam o que deu errado. Essas são as mensagens de status que você vê na saída do kubectl get pods — e são sua primeira pista de diagnóstico.

Estados Comuns de Falha de Pods

CrashLoopBackOff

CrashLoopBackOff é a falha de pod mais comum que você encontrará. Significa que o contêiner inicia, falha e o Kubernetes continua reiniciando-o com atrasos crescentes (10s, 20s, 40s, até 5 minutos).

Causas comuns:

  • Erro na aplicação causando saída imediata (configuração ausente, exceção não tratada)
  • Variáveis de ambiente ou secrets montados ausentes
  • Comando ou entrypoint incorreto no spec do contêiner
  • Health check (liveness probe) falhando de forma muito agressiva
  • Dependência de um serviço que não está disponível

Comandos de diagnóstico:

# Verificar o status do pod e contagem de reinícios
kubectl get pods -o wide

# Ver os logs do último contêiner
kubectl logs <nome-pod> --previous

# Verificar eventos do pod
kubectl describe pod <nome-pod>

A flag --previous é crítica — sem ela, você pode obter logs vazios ou parciais porque a nova instância do contêiner acabou de iniciar. A saída do describe mostra o Last State com o código de saída, que indica se o processo falhou (código de saída 1) ou foi encerrado (código de saída 137 para OOM, 143 para SIGTERM).

ImagePullBackOff

ImagePullBackOff significa que o Kubernetes não consegue baixar a imagem do contêiner do registro. O pod permanece neste estado, tentando novamente com backoff exponencial.

Causas comuns:

  • Erro de digitação no nome ou tag da imagem
  • Tag da imagem não existe (ex: referenciando latest quando apenas tags versionadas são publicadas)
  • imagePullSecrets ausentes ou expirados
  • Registro privado sem credenciais configuradas
  • Network policy ou firewall bloqueando acesso ao registro
  • Limites de taxa do registro (throttling do Docker Hub)

Comandos de diagnóstico:

# Verificar a referência exata da imagem
kubectl describe pod <nome-pod> | grep -A 5 "Image:"

# Procurar erros de pull nos eventos
kubectl get events --field-selector involvedObject.name=<nome-pod>

# Verificar se imagePullSecrets existem
kubectl get secrets -n <namespace>

Pending

Um pod no estado Pending significa que o scheduler ainda não o atribuiu a um nó. Isso pode persistir indefinidamente se o problema subjacente não for resolvido.

Causas comuns:

  • CPU ou memória insuficiente em todos os nós
  • Node selectors, taints ou affinities que nenhum nó satisfaz
  • PersistentVolumeClaim (PVC) não vinculado — nenhum PersistentVolume correspondente disponível
  • ResourceQuota excedido no namespace
  • Muitos pods no cluster (limite max-pods nos nós)

Comandos de diagnóstico:

# Verificar por que o pod está pendente
kubectl describe pod <nome-pod>

# Ver eventos do scheduler
kubectl get events --sort-by='.lastTimestamp' -n <namespace>

# Verificar recursos do nó
kubectl describe nodes | grep -A 5 "Allocated resources"

# Verificar status do PVC se o pod usa volumes
kubectl get pvc -n <namespace>

OOMKilled

OOMKilled (código de saída 137) significa que o OOM killer do kernel Linux encerrou o contêiner porque ele excedeu seu limite de memória.

Causas comuns:

  • Limite de memória configurado muito baixo para a aplicação
  • Vazamento de memória (memory leak) na aplicação
  • Tamanho do heap da JVM não alinhado com o limite de memória do contêiner
  • Contêineres sidecar consumindo memória compartilhada
  • Carregamento de grandes conjuntos de dados em memória

Comandos de diagnóstico:

# Verificar a razão da terminação
kubectl describe pod <nome-pod> | grep -A 3 "Last State"

# Ver uso atual de memória (requer metrics-server)
kubectl top pod <nome-pod>

# Verificar limites configurados
kubectl get pod <nome-pod> -o jsonpath='{.spec.containers[*].resources}'

Outros Estados de Falha

EstadoSignificadoSolução Típica
CreateContainerConfigErrorConfigMap ou Secret ausenteVerifique se os ConfigMaps e Secrets referenciados existem
RunContainerErrorFalha do runtime do contêinerVerifique o security context, montagens de volumes e logs do runtime do contêiner no nó
EvictedNó sob pressão de recursosVerifique as condições de pressão de disco/memória do nó e defina requests de recursos adequados
Init:ErrorInit container falhouVerifique os logs do init container com kubectl logs <pod> -c <init-container>
Terminating (preso)Finalizers bloqueando exclusãoVerifique os finalizers com kubectl get pod -o json e remova se seguro

Diagnosticando Problemas com kubectl

O fluxo de diagnóstico segue um padrão consistente independentemente do tipo de falha:

Etapa 1: Obter a Visão Geral

# Todos os pods no namespace com status
kubectl get pods -n <namespace> -o wide

# Eventos recentes ordenados por tempo
kubectl get events --sort-by='.lastTimestamp' -n <namespace> | tail -20

Etapa 2: Aprofundar no Pod

# Descrição completa do pod com eventos
kubectl describe pod <nome-pod> -n <namespace>

# Logs do contêiner (instância atual)
kubectl logs <nome-pod> -n <namespace>

# Logs do contêiner (instância anterior que falhou)
kubectl logs <nome-pod> -n <namespace> --previous

# Logs de um contêiner específico em um pod multi-contêiner
kubectl logs <nome-pod> -c <nome-conteiner> -n <namespace>

Etapa 3: Verificar o Nó

# Condições do nó (pressão de disco, memória, PIDs)
kubectl describe node <nome-no> | grep -A 10 "Conditions"

# Alocação de recursos no nó
kubectl describe node <nome-no> | grep -A 20 "Allocated resources"

Etapa 4: Depuração Interativa

# Exec em um contêiner em execução
kubectl exec -it <nome-pod> -- /bin/sh

# Usar contêiner de depuração efêmero (K8s 1.23+)
kubectl debug -it <nome-pod> --image=busybox --target=<nome-conteiner>

# Executar um pod de depuração no mesmo namespace de rede
kubectl run debug --rm -it --image=busybox -- /bin/sh

Comparação de Comandos kubectl

Estado de FalhaPrimeiro ComandoInformação Chave
CrashLoopBackOffkubectl logs <pod> --previousSaída de erro da aplicação antes da falha
ImagePullBackOffkubectl describe pod <pod>Nome da imagem, erros de pull, referências de secrets
Pendingkubectl describe pod <pod>Razão da falha do scheduler na seção Events
OOMKilledkubectl describe pod <pod>Razão da terminação no Last State e código de saída
CreateContainerConfigErrorkubectl get configmap,secret -n <ns>Recursos referenciados ausentes
Evictedkubectl describe node <node>Condições de pressão de recursos do nó
Init:Errorkubectl logs <pod> -c <init-container>Logs de falha do init container

Cenário Real

Você gerencia um cluster de produção executando uma aplicação de microsserviços. Após um deployment, o pod payment-service continua reiniciando e mostra CrashLoopBackOff. Veja como diagnosticar:

$ kubectl get pods -n production
NAME                              READY   STATUS             RESTARTS   AGE
payment-service-7d4f8b9c6-x2k9m  0/1     CrashLoopBackOff   5          8m
api-gateway-5c8f7d6b4-h3j7n      1/1     Running            0          2d
user-service-6b7c8d9e5-m4n8p     1/1     Running            0          2d

Você verifica os logs do contêiner anterior:

$ kubectl logs payment-service-7d4f8b9c6-x2k9m --previous
2026-02-28 10:15:03 ERROR: Failed to connect to database
  ConnectionRefused: tcp://db-service:5432
2026-02-28 10:15:03 FATAL: Cannot start without database connection. Exiting.

A aplicação requer uma conexão com o banco de dados na inicialização, mas db-service está inacessível. Você verifica o serviço:

$ kubectl get svc db-service -n production
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
db-service   ClusterIP   10.96.45.123   <none>        5432/TCP   30d

$ kubectl get endpoints db-service -n production
NAME         ENDPOINTS   AGE
db-service   <none>      30d

Sem endpoints — o pod do banco de dados está inativo. Você descobre que foi despejado devido à pressão de disco no nó:

$ kubectl get pods -n production | grep db
db-postgresql-0   0/1     Evicted   0   30d

A solução: liberar espaço em disco no nó (ou adicionar mais nós), reiniciar o pod do banco de dados, e o serviço de pagamento se recupera automaticamente. Você também adiciona um startupProbe com um timeout generoso para que o serviço de pagamento aguarde o banco de dados em vez de falhar imediatamente.

Armadilhas e Casos Especiais

  • Código de saída 137 vs 143: O código de saída 137 significa que o contêiner foi encerrado por SIGKILL (geralmente OOMKilled). O código 143 significa SIGTERM (encerramento gracioso). Não confunda — 137 requer investigação de memória, 143 é geralmente normal durante rollouts.

  • Atraso do CrashLoopBackOff: O Kubernetes usa backoff exponencial até 5 minutos entre reinícios. Se você corrigir o problema, pode precisar esperar ou excluir o pod para reiniciá-lo imediatamente.

  • ImagePullPolicy: Always: Se o spec do seu pod usa imagePullPolicy: Always (o padrão para tags latest), cada reinício do pod dispara um pull de imagem. Isso pode causar ImagePullBackOff se o registro estiver temporariamente inacessível, mesmo que a imagem estivesse previamente em cache no nó.

  • Resource requests vs limits: Pods são agendados com base nos requests, não nos limits. Um pod solicitando 100Mi mas limitado a 500Mi pode receber OOMKilled a 500Mi mesmo se o nó tiver 2Gi livres — o limite é aplicado independentemente da capacidade do nó.

  • Pods multi-contêiner: Em um pod com sidecars, kubectl logs usa por padrão o primeiro contêiner. Sempre especifique -c <nome-conteiner> ao depurar pods multi-contêiner.

  • Despejo por armazenamento efêmero: Mesmo se CPU e memória estiverem bem, alto uso de armazenamento efêmero (logs, arquivos temporários) pode disparar despejo. Verifique com kubectl describe node na seção Conditions.

  • PVC na zona de disponibilidade errada: Em ambientes cloud, um PVC vinculado a um volume em us-east-1a não pode ser montado por um pod agendado em um nó em us-east-1b. O pod fica em Pending sem um erro óbvio.

  • Atraso na resolução DNS: Serviços recém-criados podem não resolver imediatamente. Se seu contêiner falha porque não consegue resolver um nome de serviço, adicione um atraso na inicialização ou lógica de retry em vez de depender de propagação instantânea de DNS.

Resumo

  • CrashLoopBackOff significa que seu contêiner continua falhando — verifique os logs com --previous para ver o erro antes da falha
  • ImagePullBackOff indica uma falha ao baixar a imagem — verifique o nome da imagem, tag e credenciais do registro
  • Pending significa que o scheduler não consegue posicionar o pod — verifique disponibilidade de recursos, status do PVC e regras de afinidade
  • OOMKilled (código de saída 137) significa que o contêiner excedeu seu limite de memória — aumente os limites ou otimize o uso de memória
  • Sempre comece com kubectl describe pod e kubectl get events para entender o contexto da falha
  • Use kubectl debug para contêineres efêmeros quando precisar de depuração interativa sem modificar o spec do pod
  • Configure requests, limits e probes adequados para prevenir muitas falhas comuns de pods antes que aconteçam

Artigos Relacionados