Troubleshooting Pods
Diagnose and fix the five most common Pod failure modes: CrashLoopBackOff, OOMKilled, ImagePullBackOff, Pending, and Init container failures.
CrashLoopBackOff with 15 restarts. kubectl logs returns nothing. Why? What is the relationship between the backoff timer and when you can see logs? What flag gives you the previous container's logs?The Troubleshooting Decision Tree
Always follow this workflow. Do not skip steps.
kubectl get pods
β
βββ CrashLoopBackOff βββΊ kubectl logs <pod> --previous
β kubectl describe pod <pod> (check Exit Code, Last State)
β
βββ OOMKilled βββββββββββΊ kubectl describe pod <pod> (look for Exit Code: 137)
β Increase resources.limits.memory
β
βββ ImagePullBackOff ββββΊ kubectl describe pod <pod> (Events: Failed to pull image)
β Check image name/tag spelling
β Check imagePullSecrets for private registries
β
βββ Pending βββββββββββββΊ kubectl describe pod <pod> (Events: FailedScheduling)
β kubectl get nodes (are nodes Ready?)
β kubectl describe node <node> (check Allocatable vs Requests)
β Check nodeSelector, tolerations, affinity rules
β
βββ Init:0/1 ββββββββββββΊ kubectl logs <pod> -c <init-container-name>
β kubectl describe pod <pod> (Init Containers section)
β
βββ Running but unhealthyβΊ kubectl exec -it <pod> -- /bin/sh
kubectl logs <pod> -f
kubectl describe pod <pod> (check probe failures)CrashLoopBackOff
The most common failure. Kubernetes restarts a crashing container with exponential backoff:
Restart 1: wait 10s Restart 2: wait 20s Restart 3: wait 40s Restart 4: wait 80s Restart 5: wait 160s Restart 6+: wait 300s (5 min cap)
This means after several restarts, the container is only UP for a few seconds every 5 minutes. Running kubectl logs during the backoff window shows an empty or stale log. Use --previous to see the terminated container's logs:
kubectl logs <pod> --previous kubectl logs <pod> -c <container> --previous # multi-container pods
The kubectl describe output tells you the exit code:
Last State: Terminated Reason: Error Exit Code: 1 β application crashed Exit Code: 137 β OOMKilled (128 + SIGKILL signal 9) Exit Code: 126 β permission denied (can't execute command) Exit Code: 127 β command not found (bad entrypoint)
OOMKilled
When a container exceeds its resources.limits.memory, the Linux kernel OOM killer sends SIGKILL (signal 9). Exit code = 128 + 9 = 137.
Last State: Terminated Reason: OOMKilled Exit Code: 137 Started: Mon, 05 Jun 2026 10:01:00 +0000 Finished: Mon, 05 Jun 2026 10:01:03 +0000
Fix: increase resources.limits.memory or profile the application for a memory leak.
ImagePullBackOff
Kubernetes tries to pull the image, fails (ErrImagePull), then retries with backoff (ImagePullBackOff). Common causes:
- Wrong image name or tag β typo in the image field
- Private registry β no
imagePullSecretsconfigured - Rate limiting β Docker Hub pull limit (unauthenticated: 100 pulls/6h)
Events:
Warning Failed 3s kubelet Failed to pull image "nginx:does-not-exist":
rpc error: code = NotFound desc = failed to pull and unpack image
"docker.io/library/nginx:does-not-exist": not found
Warning Failed 3s kubelet Error: ErrImagePull
Warning BackOff 2s kubelet Back-off pulling image "nginx:does-not-exist"Pending β Scheduler Cannot Place the Pod
The scheduler evaluates every node and rejects them all. The Events section explains why:
Events:
Warning FailedScheduling 5s default-scheduler
0/2 nodes are available:
1 Insufficient cpu.
1 node(s) had untolerated taint {node-role.kubernetes.io/control-plane: ""}.Decode "0/2 nodes are available: 1 Insufficient cpu, 1 node(s) had taint":
- Node 1: not enough CPU
- Node 2: has a control-plane taint and the Pod has no toleration
Other common Pending causes:
nodeSelectorwith a label that no node has- PersistentVolumeClaim in Pending state (no matching PV)
- Resource quota exhausted in the namespace
Init Container Failures
Init containers run sequentially before app containers start. If one fails, the Pod status shows Init:0/2 (0 of 2 init containers completed).
# Check init container logs β must specify -c with the init container name kubectl logs <pod> -c init-db-check # describe shows each init container's state separately kubectl describe pod <pod> # Look for: # Init Containers: # init-db-check: # State: Terminated # Reason: Error # Exit Code: 1