How to Debug CrashLoopBackOff Pods
Master troubleshooting Kubernetes pods stuck in CrashLoopBackOff. Learn systematic debugging techniques, common causes, and solutions.
The Problem
Your pod is in CrashLoopBackOff state, repeatedly crashing and restarting with increasing backoff delays.
Understanding CrashLoopBackOff
CrashLoopBackOff means:
- The container starts
- The container crashes or exits
- Kubernetes restarts it
- It crashes again
- Kubernetes increases the wait time before the next restart
Backoff delays: 10s → 20s → 40s → … → 5 minutes (max)
Step 1: Check Pod Status
# Get pod status
kubectl get pods
# Output example:
# NAME READY STATUS RESTARTS AGE
# myapp 0/1 CrashLoopBackOff 5 10mStep 2: Describe the Pod
kubectl describe pod myappLook for:
- Events: Shows restart history and reasons
- Last State: Exit code and reason
- Containers: Image, command, and configuration
Key exit codes:
| Code | Meaning |
|---|---|
| 0 | Graceful exit (shouldn’t restart) |
| 1 | Application error |
| 137 | OOMKilled (out of memory) |
| 139 | Segmentation fault |
| 143 | SIGTERM (graceful shutdown) |
Step 3: Check Container Logs
# Current container logs
kubectl logs myapp
# Previous container logs (before crash)
kubectl logs myapp --previous
# Follow logs
kubectl logs myapp -f
# Specific container in multi-container pod
kubectl logs myapp -c container-nameCommon Causes and Solutions
1. Application Error (Exit Code 1)
Symptoms:
Last State: Terminated
Exit Code: 1Solutions:
- Check logs for error messages
- Verify environment variables
- Check configuration files
- Test the image locally:
docker run -it myapp:tag2. OOMKilled (Exit Code 137)
Symptoms:
Last State: Terminated
Reason: OOMKilled
Exit Code: 137Solution: Increase memory limit:
resources:
limits:
memory: "512Mi" # Increase this3. Missing Configuration
Symptoms:
Error: ConfigMap "myapp-config" not foundSolution: Create the missing ConfigMap/Secret:
kubectl create configmap myapp-config --from-file=config.yaml4. Image Pull Error
Symptoms:
Warning Failed ImagePullBackOffSolution: Check image name and registry credentials:
# Verify image exists
docker pull myapp:tag
# Create registry secret
kubectl create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=user \
--docker-password=password5. Failing Health Checks
Symptoms:
Liveness probe failed: connection refusedSolution: Fix or adjust probe configuration:
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30 # Give app time to start
periodSeconds: 10
failureThreshold: 36. Permission Errors
Symptoms:
Error: permission deniedSolution: Fix security context:
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 10007. Wrong Command/Entrypoint
Symptoms: Container exits immediately.
Solution: Verify the command:
containers:
- name: myapp
image: myapp:tag
command: ["/bin/sh", "-c"]
args: ["./start.sh"] # Ensure this script existsDebug with Ephemeral Containers
For running pods (Kubernetes 1.25+):
kubectl debug myapp -it --image=busybox --target=myappDebug by Running a Shell
Replace the command temporarily:
containers:
- name: myapp
image: myapp:tag
command: ["/bin/sh"]
args: ["-c", "sleep 3600"] # Keep container runningThen exec into it:
kubectl exec -it myapp -- /bin/shQuick Debugging Checklist
# 1. Get pod events
kubectl describe pod myapp | grep -A 20 Events
# 2. Get logs
kubectl logs myapp --previous
# 3. Check exit code
kubectl get pod myapp -o jsonpath='{.status.containerStatuses[0].lastState.terminated.exitCode}'
# 4. Check resource usage
kubectl top pod myapp
# 5. Check events in namespace
kubectl get events --sort-by=.metadata.creationTimestampPrevention Tips
- Always set resource limits to prevent OOMKills
- Use proper health checks with adequate delays
- Test images locally before deploying
- Use init containers for dependencies
- Log to stdout/stderr for easy debugging
One-Liner Debug Commands
# Get all failing pods
kubectl get pods --field-selector=status.phase=Failed
# Get pods with restarts
kubectl get pods -o wide | awk '$5 > 0'
# Watch events
kubectl get events -w
# Get last termination reason
kubectl get pod myapp -o jsonpath='{.status.containerStatuses[0].lastState.terminated.reason}'Key Takeaways
- Check logs first with
kubectl logs --previous - Exit code 137 = memory issue
- Exit code 1 = application error
- Use
kubectl describe podfor events - Debug by overriding the command to sleep
📘 Go Further with Kubernetes Recipes
Love this recipe? There’s so much more! This is just one of 100+ hands-on recipes in our comprehensive Kubernetes Recipes book.
Inside the book, you’ll master:
- ✅ Production-ready deployment strategies
- ✅ Advanced networking and security patterns
- ✅ Observability, monitoring, and troubleshooting
- ✅ Real-world best practices from industry experts
“The practical, recipe-based approach made complex Kubernetes concepts finally click for me.”
👉 Get Your Copy Now — Start building production-grade Kubernetes skills today!
📘 Get All 100+ Recipes in One Book
Stop searching — get every production-ready pattern with detailed explanations, best practices, and copy-paste YAML.
Want More Kubernetes Recipes?
This recipe is from Kubernetes Recipes, our 750-page practical guide with hundreds of production-ready patterns.