Pular para o conteúdo principal

Solução de problemas de pods

Seu pod não está rodando. Esta página explica o porquê e o que fazer. Comece com o status que você vê no kubectl get pods, siga a árvore de decisão e corrija o problema.

Comece aqui​

kubectl get pods -n <namespace> -o wide
kubectl describe pod <pod-name> -n <namespace>

A saída do describe tem a resposta 95% das vezes. Olhe a seção Events no final.


Pending​

O pod existe, mas nenhum nó o aceita.

Árvore de decisão​

1. Verifique eventos de falhas de agendamento:

kubectl describe pod <pod> -n <ns> | grep -A 5 "Events:"

2. O que o evento diz?

Mensagem do eventoCausaCorreção
Insufficient cpu ou Insufficient memoryO nó não tem espaço para as solicitações de recursos do podReduza os requests, adicione nós ou aumente o max-count no autoscaler
0/N nodes are available: N node(s) had taintO pod não tolera os taints do nóAdicione a toleration correta ao spec do pod
0/N nodes are available: N node(s) didn't match Pod's node affinity/selectorNode affinity ou nodeSelector não corresponde a nenhum nóCorrija o label selector ou adicione um node pool com labels correspondentes
persistentvolumeclaim "X" not foundO PVC não existe ou está em um namespace diferenteCrie o PVC no namespace correto
0/N nodes are available: N pod has unbound immediate PersistentVolumeClaimsO PV não pode ser provisionadoVerifique se a StorageClass existe, quota de disco, incompatibilidade de zona
Too many podsO nó atingiu o limite máximo de pods (padrão 110 no kubenet, 250 no Azure CNI Overlay)Use menos pods por nó ou adicione nós

3. Cluster Autoscaler não está escalando?

kubectl -n kube-system get configmap cluster-autoscaler-status -o yaml
kubectl -n kube-system logs -l app=cluster-autoscaler --tail=50

Razões comuns: max-count atingido, pod tem um nodeSelector que nenhum pool satisfaz, pod solicita mais recursos do que qualquer SKU de VM pode fornecer.

dica

Se um pod está Pending e o autoscaler não está respondendo, verifique se o pod tem regras de nodeSelector ou affinity que correspondem a um node pool com min-count: 0 e max-count: 0. O autoscaler não pode criar nós em um pool com max-count 0.


CrashLoopBackOff​

O contêiner inicia, roda por alguns segundos e depois termina. O Kubernetes o reinicia com backoff exponencial (10s, 20s, 40s, até 5 min).

Árvore de decisão​

1. Obtenha os logs da última falha:

kubectl logs <pod> -n <ns> --previous

2. Verifique o exit code:

kubectl describe pod <pod> -n <ns> | grep -A 3 "Last State"
Exit codeSignificadoCausa mais comum
0Saída normalA aplicação completou e encerrou. Se for um servidor web, ele não deveria encerrar. Verifique o entrypoint.
1Erro na aplicaçãoExceção não tratada, arquivo de configuração ausente, URL de banco de dados incorreta
127Comando não encontradocommand ou args incorretos no spec do contêiner. O binário não existe na imagem.
137OOMKilled (SIGKILL)O contêiner excedeu seu limite de memória. Veja a seção OOMKilled abaixo.
139Segfault (SIGSEGV)Bug na aplicação. Verifique core dumps.
143SIGTERMSinal de encerramento gracioso. Se o contêiner reiniciar após isto, verifique o liveness probe.

3. Correções comuns:

  • Variável de ambiente ou secret ausente: Verifique kubectl describe pod para eventos CreateContainerConfigError. Confirme que todos os secrets e configmaps referenciados existem.
  • Liveness probe falhando: O probe mata um contêiner saudável mas lento. Aumente initialDelaySeconds e periodSeconds.
  • A aplicação precisa de tempo para iniciar: Adicione um startupProbe com timeout generoso antes que o liveness probe entre em ação.
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 30
periodSeconds: 10
# Gives the app 300 seconds (5 min) to start
aviso

Não "corrija" CrashLoopBackOff removendo o liveness probe. O probe está dizendo que a aplicação está com problemas. Corrija a aplicação.


ImagePullBackOff​

O Kubernetes não consegue baixar a imagem do contêiner.

Árvore de decisão​

1. Verifique o erro exato:

kubectl describe pod <pod> -n <ns> | grep -A 3 "Failed"
Mensagem de erroCausaCorreção
repository does not exist or may require authorizationNome da imagem incorreto ou registro privado sem autenticaçãoVerifique o nome da imagem, vincule o ACR com az aks update --attach-acr
unauthorized: authentication requiredCredenciais do registro ausentes ou expiradasPara ACR, use az aks check-acr. Para Docker Hub, crie um imagePullSecret
manifest unknownA tag não existe no registroVerifique as tags disponíveis com az acr repository show-tags --name myACR --repository myapp
ErrImagePull seguido de Back-offProblema de rede transitório ou rate limitAguarde e tente novamente. O Docker Hub limita pulls anônimos a 100/6h. Use ACR.

2. Verificações específicas do ACR:

# Verify ACR is attached
az aks check-acr --resource-group myRG --name myAKS --acr myACR.azurecr.io

# If not attached
az aks update --resource-group myRG --name myAKS --attach-acr myACR

# Verify the image exists
az acr repository show-tags --name myACR --repository myapp -o tsv

3. Usando imagePullSecrets (registros não-ACR):

kubectl create secret docker-registry my-reg-cred \
--docker-server=registry.example.com \
--docker-username=user \
--docker-password=pass \
-n <namespace>

Depois referencie no spec do pod:

spec:
imagePullSecrets:
- name: my-reg-cred

OOMKilled​

O contêiner usou mais memória do que o limite permite. O kernel o mata com sinal 137.

Árvore de decisão​

1. Confirme que é OOMKilled:

kubectl describe pod <pod> -n <ns> | grep -E "OOMKilled|Exit Code: 137"

2. Verifique o uso atual de memória vs. limite:

kubectl top pod <pod> -n <ns> --containers

3. Decida a correção:

SituaçãoCorreção
A aplicação genuinamente precisa de mais memóriaAumente resources.limits.memory. Mas também investigue se há um vazamento.
O limite de memória está muito baixoDefina o limite para 1,5-2x do uso típico. Use o VPA em modo de recomendação para encontrar o valor correto.
Vazamento de memória (uso cresce ao longo do tempo)Corrija a aplicação. Causas comuns: caches sem limite, vazamento de pool de conexões, processamento de arquivos grandes sem streaming.
Aplicação JVM terminada apesar de -Xmx configuradoA JVM usa mais memória do que apenas o heap (thread stacks, metaspace, native buffers). Defina o limite para Xmx + 500Mi no mínimo.

4. Use VPA para recomendações de dimensionamento:

# Install VPA and set it to recommendation-only mode
# Then check recommendations
kubectl get vpa -n <ns> -o yaml
dica

Nunca defina limites de memória iguais aos requests para aplicações JVM ou .NET. Esses runtimes precisam de espaço adicional acima do heap para GC, JIT e thread stacks. Um bom ponto de partida: requests = uso típico, limits = requests * 2.


CreateContainerConfigError​

O contêiner não pode iniciar porque um recurso referenciado está ausente.

Causas comuns​

kubectl describe pod <pod> -n <ns> | grep -A 5 "Warning"
ErroCorreção
secret "X" not foundCrie o secret no namespace correto
configmap "X" not foundCrie o configmap no namespace correto
key "Y" not found in secret "X"O secret existe mas está sem a chave esperada. Verifique kubectl get secret X -n <ns> -o jsonpath='{.data}'
projected volume mount failedProblema de volume de token do Workload Identity. Verifique o OIDC issuer e as annotations do service account.

Stuck terminating​

Um pod está travado no estado Terminating e não desaparece.

Árvore de decisão​

1. Verifique finalizers:

kubectl get pod <pod> -n <ns> -o jsonpath='{.metadata.finalizers}'

Se finalizers estão presentes, algo está esperando para fazer a limpeza. Removê-los à força pode causar vazamento de recursos.

2. Verifique se o PDB está bloqueando a remoção:

kubectl get pdb -n <ns>

Se o PDB impede a disrupção do último pod restante, a operação de drain fica bloqueada.

3. Exclusão forçada (último recurso):

kubectl delete pod <pod> -n <ns> --grace-period=0 --force
aviso

Excluir à força um pod com PersistentVolume anexado pode fazer com que o volume permaneça anexado ao nó antigo. O pod substituto não consegue montá-lo. Use a exclusão forçada apenas quando tiver certeza de que não há dependências de volume.


Script de diagnóstico rápido​

Execute isto quando precisar de uma visão geral rápida de todos os problemas em um namespace:

NS=my-namespace

echo "=== Non-running pods ==="
kubectl get pods -n $NS --field-selector=status.phase!=Running,status.phase!=Succeeded

echo "=== Warning events (last 1h) ==="
kubectl get events -n $NS --field-selector type=Warning --sort-by='.lastTimestamp' | tail -20

echo "=== Resource pressure ==="
kubectl top pods -n $NS --sort-by=memory | head -10

echo "=== PVC status ==="
kubectl get pvc -n $NS | grep -v Bound

Recursos​