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)
kubectlinstalado 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:
| Fase | Descrição |
|---|---|
| Pending | Pod aceito pelo cluster, mas um ou mais contêineres ainda não estão executando |
| Running | Pod vinculado a um nó e todos os contêineres iniciados |
| Succeeded | Todos os contêineres terminaram com sucesso (código de saída 0) |
| Failed | Todos os contêineres terminaram e pelo menos um saiu com erro |
| Unknown | Estado 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
latestquando apenas tags versionadas são publicadas) imagePullSecretsausentes 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
| Estado | Significado | Solução Típica |
|---|---|---|
| CreateContainerConfigError | ConfigMap ou Secret ausente | Verifique se os ConfigMaps e Secrets referenciados existem |
| RunContainerError | Falha do runtime do contêiner | Verifique o security context, montagens de volumes e logs do runtime do contêiner no nó |
| Evicted | Nó sob pressão de recursos | Verifique as condições de pressão de disco/memória do nó e defina requests de recursos adequados |
| Init:Error | Init container falhou | Verifique os logs do init container com kubectl logs <pod> -c <init-container> |
| Terminating (preso) | Finalizers bloqueando exclusão | Verifique 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 Falha | Primeiro Comando | Informação Chave |
|---|---|---|
| CrashLoopBackOff | kubectl logs <pod> --previous | Saída de erro da aplicação antes da falha |
| ImagePullBackOff | kubectl describe pod <pod> | Nome da imagem, erros de pull, referências de secrets |
| Pending | kubectl describe pod <pod> | Razão da falha do scheduler na seção Events |
| OOMKilled | kubectl describe pod <pod> | Razão da terminação no Last State e código de saída |
| CreateContainerConfigError | kubectl get configmap,secret -n <ns> | Recursos referenciados ausentes |
| Evicted | kubectl describe node <node> | Condições de pressão de recursos do nó |
| Init:Error | kubectl 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 tagslatest), 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 logsusa 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 nodena seçãoConditions. -
PVC na zona de disponibilidade errada: Em ambientes cloud, um PVC vinculado a um volume em
us-east-1anão pode ser montado por um pod agendado em um nó emus-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
--previouspara 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 podekubectl get eventspara entender o contexto da falha - Use
kubectl debugpara 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