| name | k8s-troubleshoot |
| description | Guia de diagnóstico passo a passo para problemas comuns em clusters Kubernetes. Cobre: CrashLoopBackOff, OOMKilled, ImagePullBackOff, pods Pending, rolling update travado, Ingress 502/503/404, secrets não montando, HPA não escalando. Use quando: uma aplicação não está rodando como esperado no cluster. |
| user-invocable | true |
Diagnóstico de Problemas no Kubernetes
Princípio Geral
Sempre coletar evidências antes de agir. A ordem é:
kubectl get — estado atual dos recursos
kubectl describe — eventos e motivo do problema
kubectl logs — output da aplicação
- Corrigir com base nos dados, não em suposição
Cheatsheet de Diagnóstico Rápido
kubectl get all -n {namespace}
kubectl get pods -n {namespace} --field-selector=status.phase!=Running
kubectl get events -n {namespace} --sort-by='.lastTimestamp'
kubectl logs {pod} -n {namespace}
kubectl logs {pod} -n {namespace} --previous
kubectl describe pod {pod} -n {namespace}
kubectl top pods -n {namespace}
kubectl top nodes
CrashLoopBackOff
Sintoma: Pod reinicia repetidamente; status CrashLoopBackOff
Diagnóstico:
kubectl logs {pod} -n {namespace} --previous
kubectl describe pod {pod} -n {namespace} | grep -A 10 "Last State:"
Causas comuns e soluções:
| Código de Saída | Causa | Ação |
|---|
| 1 | Erro de aplicação (uncaught exception) | Verificar logs da aplicação |
| 137 | Killed por OOM ou SIGKILL externo | Aumentar resources.limits.memory ou verificar liveness probe |
| 139 | Segmentation fault | Bug no binário ou dependência nativa corrompida |
| 143 | SIGTERM não tratado — timeout no shutdown | Implementar graceful shutdown |
| 1 com "permission denied" | Arquivo sem permissão de execução ou volume montado como root | Verificar securityContext.runAsUser e permissões do volume |
Verificação de liveness probe muito agressiva:
kubectl describe pod {pod} | grep -A 5 "Liveness:"
Correção de probe:
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 3
OOMKilled
Sintoma: Pod reinicia; kubectl describe mostra OOMKilled
Diagnóstico:
kubectl describe pod {pod} -n {namespace} | grep -A 5 "OOMKilled\|memory"
kubectl top pod {pod} -n {namespace} --containers
Causas e soluções:
- Limit muito baixo:
resources:
limits:
memory: "64Mi"
resources:
requests:
memory: "128Mi"
limits:
memory: "256Mi"
-
Memory leak na aplicação: escalone horizontal enquanto corrige (não vertical)
-
JVM sem limite configurado (Java):
# ✅ JVM respeitando limit do container
ENV JAVA_OPTS="-XX:MaxRAMPercentage=75.0 -XX:+UseContainerSupport"
ImagePullBackOff / ErrImagePull
Sintoma: Pod não inicia; status ImagePullBackOff
Diagnóstico:
kubectl describe pod {pod} -n {namespace} | grep -A 5 "Events:"
Causas e soluções:
| Mensagem | Causa | Solução |
|---|
unauthorized | Sem credencial ou credencial expirada | Verificar imagePullSecrets |
not found | Tag ou repositório inexistente | Verificar nome e tag da imagem |
network timeout | Cluster sem acesso ao registry | Verificar NetworkPolicy e DNS |
x509 certificate | Registry com cert auto-assinado | Adicionar CA ao nó ou usar mirror |
Verificar e corrigir imagePullSecrets:
kubectl get secrets -n {namespace} | grep kubernetes.io/dockerconfigjson
kubectl create secret docker-registry reg-cred \
--docker-server=myregistry.io \
--docker-username=usuario \
--docker-password=senha \
--docker-email=email@email.com \
-n {namespace}
spec:
imagePullSecrets:
- name: reg-cred
Pods em Pending
Sintoma: Pod criado mas não inicia; status Pending
Diagnóstico:
kubectl describe pod {pod} -n {namespace} | tail -20
Causas e soluções:
| Evento | Causa | Solução |
|---|
Insufficient cpu | Nenhum nó tem CPU disponível | Adicionar nó ou reduzir requests.cpu |
Insufficient memory | Nenhum nó tem memória disponível | Idem para memória |
Unschedulable: 0/3 nodes ... taint | Taint sem toleration | Adicionar tolerations no Pod |
no persistent volumes available | PVC não vinculado | Verificar StorageClass e capacidade do PV |
nodeSelector/affinity not matched | Nenhum nó satisfaz as regras | Revisar nodeSelector ou affinity |
Verificar taints dos nós:
kubectl describe nodes | grep -i taint
kubectl get nodes -o json | jq '.items[].spec.taints'
Verificar PVC:
kubectl get pvc -n {namespace}
kubectl describe pvc {pvc-name} -n {namespace}
Rolling Update Travado
Sintoma: kubectl rollout status não avança; pods novos não ficam Running
Diagnóstico:
kubectl rollout status deployment/{nome} -n {namespace}
kubectl get replicaset -n {namespace}
kubectl describe deployment/{nome} -n {namespace} | grep -A 10 "Conditions:"
Causas e soluções:
- Readiness probe falhando nos pods novos:
kubectl describe pod {novo-pod} | grep -A 10 "Readiness"
maxUnavailable: 0 com apenas 1 réplica — o novo pod precisa iniciar antes do antigo ser removido, mas sem recursos disponíveis:
strategy:
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
- Rollback manual:
kubectl rollout undo deployment/{nome} -n {namespace}
kubectl rollout history deployment/{nome} -n {namespace}
kubectl rollout undo deployment/{nome} --to-revision=2 -n {namespace}
Ingress 502 / 503 / 404
Sintoma: Aplicação no cluster mas retorna erro HTTP ao acessar pelo Ingress
Diagnóstico:
kubectl get svc -n {namespace}
kubectl get endpoints {service-name} -n {namespace}
kubectl describe ingress {ingress-name} -n {namespace}
kubectl logs -l app.kubernetes.io/name=ingress-nginx -n ingress-nginx --tail=50
Causas e soluções:
| Status | Causa | Solução |
|---|
| 404 | regra de path errada no Ingress | Verificar spec.rules[].http.paths[].path |
| 502 | pod não está aceitando conexões na porta | Verificar containerPort vs targetPort no Service |
| 503 | Endpoints vazio (sem pods saudáveis) | Verificar selector do Service vs labels do Pod |
Verificar selector do Service vs labels do Pod:
kubectl get pod {pod} -n {namespace} --show-labels
kubectl get svc {service} -n {namespace} -o jsonpath='{.spec.selector}'
Secrets Não Montando / Variável Ausente
Sintoma: Aplicação não encontra variável de ambiente; pod em CreateContainerConfigError
Diagnóstico:
kubectl describe pod {pod} -n {namespace} | grep -A 5 "Error\|Warning"
kubectl get secret {secret-name} -n {namespace} -o jsonpath='{.data}' | jq 'keys'
Causas e soluções:
- Secret no namespace errado:
kubectl get secret {secret-name} --all-namespaces
- Nome da chave errado no
secretKeyRef:
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
- Secret não criado:
kubectl create secret generic db-secret \
--from-literal=password=minhasenha \
-n {namespace}
HPA Não Escalando
Sintoma: Carga alta mas número de réplicas não aumenta
Diagnóstico:
kubectl describe hpa {hpa-name} -n {namespace}
kubectl get hpa -n {namespace}
Causas e soluções:
TARGETS | Causa | Solução |
|---|
<unknown>/50% | metrics-server não instalado | Instalar metrics-server |
0%/50% sem escalonamento | resources.requests não definido no Pod | Definir requests.cpu obrigatório para HPA de CPU |
| Valor correto mas sem escalonamento | minReplicas = maxReplicas | Ajustar o range |
Instalar metrics-server (se não presente):
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
Verificar que requests está definido:
resources:
requests:
cpu: "100m"
limits:
cpu: "500m"
Diagnóstico do Cluster (Visão Geral)
kubectl get nodes
kubectl describe node {node-name} | grep -A 10 "Conditions:"
kubectl describe nodes | grep -A 10 "Allocated resources:"
kubectl get pods --all-namespaces | grep -v Running | grep -v Completed
kubectl get events --all-namespaces --sort-by='.lastTimestamp' | tail -30
Output Esperado
- Identificação da causa raiz com evidências dos comandos
- Correção aplicada com explicação
- Comando de validação pós-correção (ex:
kubectl rollout status ou kubectl get pods -w)
- Recomendação para evitar o problema futuramente (probe configuration, resource limits, etc.)