
Table of Contents
By Khimananda Oli | Last reviewed: August 2026
Debugging unstable workloads requires a precise mental model of the Pod Lifecycle and Restart Policies governing your cluster. When containers fail repeatedly or hang in pending states, the root cause is often a mismatch between application startup behavior and Kubernetes orchestration logic rather than code defects. This guide maps the exact state transitions, probe interactions, and restart backoff algorithms you need to stabilize production systems.
What are the distinct phases of the Pod Lifecycle and Restart Policies?
A pod is not simply "up" or "down"; it traverses a strict finite state machine managed by the kubelet. Understanding these phases is prerequisite to interpreting kubectl get pods output accurately. Before diving into restart mechanics, review how Kubernetes resource limits and requests influence scheduling decisions that gate entry into the Running phase.
Pending phase constraints
The Pending phase encompasses two distinct sub-states: scheduling and image pulling. A pod remains here until the scheduler assigns a node AND all container images are successfully pulled. In practice, extended Pending times usually indicate insufficient CPU/memory for the requested resources, persistent volume binding failures, or image pull secrets misconfiguration. The kubelet does not initiate any restart logic during this phase; the scheduler and kubelet image manager must resolve blockers first.
Running versus Ready distinction
A pod enters Running when at least one container executes, but this does not guarantee service availability. The Ready condition depends entirely on readiness probe success. Traffic from Services only routes to pods with Ready=True. Confusing Running with Ready is the most common source of "intermittent 502 errors" after deployments. Your application may be running (process alive) but not ready (database connection pool warming, cache hydration incomplete).
Terminal states: Succeeded and Failed
These phases are terminal for pods with restartPolicy: Never or OnFailure (when exit code is 0 for Succeeded). For restartPolicy: Always, pods never reach these terminal states visibly; they continuously cycle through Running. The Failed state triggers immediately when a container exits non-zero under Never policy, or when backoff limits exhaust under OnFailure. Audit trails for compliance frameworks like SOC 2 require capturing these terminal events to demonstrate incident detection capability.
How do Kubernetes restart policies interact with container probes?
Restart policies do not operate in isolation; they form a feedback loop with liveness, readiness, and startup probes. Misconfiguring this interaction causes the infamous CrashLoopBackOff where Kubernetes kills healthy-but-slow applications. If you are building observability around these events, understand how metrics, logs, and traces compared provide different signals for diagnosing probe failures.
Startup probe: the slow-start safeguard
Startup probes exist solely to protect legacy or heavy applications from premature liveness kills. While active, liveness and readiness probes are disabled. Configure failureThreshold × periodSeconds to exceed your worst-case cold start time. For Java/Spring Boot apps taking 90 seconds to initialize, set failureThreshold: 30, periodSeconds: 5 (150s budget). Once the startup probe succeeds once, it never runs again and liveness takes over permanently.
Liveness probe anti-patterns
Never include external dependencies (database, Redis, downstream API) in liveness checks. If your database goes down, killing every application pod simultaneously guarantees zero recovery capacity. Liveness should verify only that the process can make forward progress: a simple /healthz endpoint returning 200 confirms the HTTP stack works. Dependency health belongs in readiness probes or separate monitoring. This distinction directly determines whether your Pod Lifecycle and Restart Policies cause cascading outages or graceful degradation.
Exponential backoff mechanics
Kubernetes applies a 10-second base delay between restarts, doubling each attempt up to a 5-minute cap. After five minutes of continuous success, the backoff resets. During CrashLoopBackOff, the pod status reflects this waiting period; the container is not running but the pod remains in Running phase (confusingly). Use kubectl describe pod <name> to see the actual backoff timer and last termination reason. This backoff prevents resource exhaustion from tight crash loops but extends mean-time-to-recovery for transient failures.
When should you use Always versus OnFailure versus Never restart policies?
Selecting the correct restart policy is an architectural decision tied to workload semantics, not a default to accept blindly. Each policy serves distinct operational patterns.
| Policy | Use Case | Terminal State | Job Controller Compatible | Risk Profile |
|---|---|---|---|---|
| Always | Long-running services, APIs, web servers | Never (loops indefinitely) | No | Low — ensures availability |
| OnFailure | Batch jobs, data pipelines, migrations | Succeeded (exit 0) or Failed (max retries) | Yes | Medium — respects completion |
| Never | One-shot tasks, forensic debugging, audit scripts | Succeeded or Failed immediately | Yes | High — no auto-recovery |
Always: the service default
This is correct for 95% of Deployments and DaemonSets. The kubelet restarts containers regardless of exit code, treating every termination as transient. Combined with proper liveness probes, this creates self-healing infrastructure. The trade-off: buggy applications that crash immediately will consume cluster resources indefinitely via backoff loops. Always pair with resource limits to contain blast radius.
OnFailure: idempotent batch workloads
Jobs and CronJobs typically use OnFailure. Containers restart only on non-zero exit codes, allowing successful completions to persist without re-execution. This assumes your job is idempotent; if partial execution corrupts state, OnFailure amplifies damage. For ETL pipelines processing external data, implement checkpoint/resume logic so restarted executions skip completed work. Review debugging CrashLoopBackOff in Kubernetes for systematic diagnosis when OnFailure jobs stall.
Never: explicit human intervention required
Reserve Never for scenarios where automatic retry is dangerous or meaningless: database migration scripts that cannot safely re-run, forensic evidence collection, or compliance-mandated single-execution audits. Failed pods remain visible for inspection. Operators must manually delete and recreate. This policy surfaces failures loudly rather than masking them through silent retries—valuable for security-sensitive workflows where unnoticed failures violate control objectives.
How do you troubleshoot pods stuck in restart loops or unexpected phases?
Systematic debugging follows the state machine backwards. Start with kubectl get pod <name> -o yaml to inspect status.containerStatuses for lastState.terminationReason and exitCode. Cross-reference events via kubectl describe. Common patterns emerge predictably.
- OOMKilled (exit 137): Container exceeded memory limit. Increase limits or optimize application memory usage. Check if JVM heap settings align with container limits (-Xmx should be ~75% of limit).
- Error (exit 1/2/126/127): Application bug, missing binary, permission denied, or config error. Inspect logs with
kubectl logs <pod> --previousto see the crashing instance's output. - ImagePullBackOff: Registry auth failure, network egress blocked, or image tag typo. Verify imagePullSecrets and test pulls manually from a debug pod on the same node.
- CreateContainerConfigError: Missing ConfigMap/Secret referenced in spec. Validate all volume mounts and envFrom sources exist in the namespace.
Validating probe configuration empirically
Before deploying probe changes to production, test timing assumptions. Run kubectl exec <pod> -- curl -w '%{time_total}' localhost:8080/healthz repeatedly during startup to measure actual response latency distribution. Set initialDelaySeconds or startup probe thresholds at p99 observed latency plus margin. Synthetic testing beats guessing. Document measured values in Helm chart comments or Kustomize patches so future maintainers understand why thresholds exist.
Audit and compliance considerations
For regulated environments, restart events constitute operational evidence. Ensure your logging pipeline captures kubelet events and container termination reasons with timestamps aligned to your SIEM. Automated evidence collection for SOC 2 or ISO 27001 audits should include restart frequency metrics as availability controls. Excessive restarts signal inadequate testing or resource planning—treat them as compliance findings, not just operational noise.
Stabilizing Workloads Through Correct Pod Lifecycle and Restart Policies
Reliable Kubernetes operations demand treating the Pod Lifecycle and Restart Policies as configurable engineering parameters, not opaque defaults. Map your application's actual startup characteristics to appropriate probe thresholds. Select restart policies based on workload semantics and failure tolerance. Instrument restart events as first-class observability signals. When systems behave unexpectedly, trace the state machine methodically before assuming platform bugs. If your team needs hands-on guidance stabilizing critical workloads or preparing infrastructure for compliance audits, reach out to discuss your specific architecture.