How to Debug CrashLoopBackOff Pods
Master troubleshooting Kubernetes pods stuck in CrashLoopBackOff. Learn systematic debugging techniques, common causes, and solutions.
💡 Quick Answer: To fix CrashLoopBackOff, run
kubectl logs <pod> --previousto see why the container crashed. Check the exit code: 137 means out of memory (increaseresources.limits.memory), 1 means application error (check configs/env vars), 139 means segfault (debug the app). Usekubectl describe pod <pod>to see events and last state.
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.