Every Kubernetes pod goes through a well-defined lifecycle. Understanding each phase is critical for debugging issues like CrashLoopBackOff, stuck terminations, and resource starvation.
Pod phases
A pod can be in one of five phases:
| Phase | Description |
|---|---|
| Pending | The pod has been accepted but containers aren't running yet |
| Running | At least one container is running, starting, or restarting |
| Succeeded | All containers terminated successfully (exit code 0) |
| Failed | All containers terminated, at least one with a non-zero exit code |
| Unknown | The pod state cannot be determined (usually a node communication issue) |
The creation flow
When you kubectl apply a pod manifest, here's what happens:
- API Server validates and stores the pod spec in etcd
- Scheduler assigns the pod to a node based on resource requests, affinity rules, and constraints
- Kubelet on the assigned node pulls container images
- Container runtime (containerd/CRI-O) creates and starts the containers
- Pod transitions from Pending to Running
Init containers
Init containers run before the main application containers. They're perfect for:
- Waiting for a dependent service to be ready
- Running database migrations
- Populating shared volumes with config data
initContainers:
- name: wait-for-db
image: busybox
command: ['sh', '-c', 'until nc -z postgres 5432; do sleep 2; done']
Init containers run sequentially — each must complete successfully before the next one starts.
Health probes
Kubernetes uses three types of probes to check container health:
Liveness probes determine if a container is running. If a liveness probe fails, the kubelet kills the container and restarts it.
Readiness probes determine if a container is ready to accept traffic. Failing readiness probes remove the pod from service endpoints.
Startup probes are used for containers that need extra time to initialize. They disable liveness checks until the startup probe succeeds.
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
periodSeconds: 5
Graceful shutdown
When a pod is deleted, Kubernetes sends a SIGTERM to all containers and waits for a grace period (default: 30 seconds). If containers don't exit within this period, SIGKILL is sent.
Your application should handle SIGTERM to:
- Stop accepting new requests
- Finish processing in-flight requests
- Close database connections
- Flush logs and metrics
Common debugging tips
- CrashLoopBackOff: Check container logs with
kubectl logs <pod> --previous - ImagePullBackOff: Verify image name, tag, and registry credentials
- Pending forever: Check node resources with
kubectl describe nodeand look for taint/toleration mismatches - Stuck terminating: Check if finalizers are preventing deletion
Understanding the pod lifecycle turns mysterious failures into predictable, debuggable events.