Pod Restart Policy

When a container in a Pod exits, what should happen next? The restartPolicy field is the Pod-level default a container can override: Always brings the container back whatever the exit code, OnFailure retries only a non-zero exit, and Never leaves it alone. It separates a Pod that runs forever from one that retries and one that finishes. The Job controller relies on OnFailure and Never, and the per-container backoff only starts after the first restart.

Play the animation 5 steps, animated, best on a wide screen

Pod Restart Policy diagram: Pod restartPolicy

Pod Restart Policy, step by step

  1. The restartPolicy is a Pod-level field, immutable once the Pod is created, and covers every app and regular init container that does not set its own. Since 1.35 the ContainerRestartRules feature gate is beta and on by default, so a container may override it with its own restartPolicy and with restartPolicyRules matched on exit codes. The Pod-level default is Always. A sidecar (an initContainer with restartPolicy Always, on by default since 1.29 and GA in 1.33) ignores it. Kubelet reads the field from the Pod spec and applies it each time a container terminates.

    Play from step 1
  2. Scenario: a container exits 0, a clean success. Pod A (Always) restarts the container and stays Running. Pod B (OnFailure) does not restart a successful exit, so once the container is done the Pod phase becomes Succeeded. Pod C (Never) does not restart anything either and likewise ends Succeeded.

    Play from step 2
  3. Scenario: a container exits with a non-zero code, a failure. Pod A (Always) restarts it. Pod B (OnFailure) restarts it too, since OnFailure retries any non-zero exit. Pod C (Never) restarts nothing, so a single failure drives the Pod phase to Failed.

    Play from step 3
  4. The first restart is immediate, and every restart after it, whether driven by Always or by OnFailure, waits out the same exponential backoff schedule, kept per container, doubling from a 10s base to a 5 minute ceiling by default. The container sits in Waiting with reason=CrashLoopBackOff during the wait, and the timer resets after the container has run successfully for 10 minutes. A Never Pod whose containers set no policy of their own never restarts, so it never enters this loop.

    Play from step 4
  5. Long-running controllers (Deployment, ReplicaSet, DaemonSet, StatefulSet) only allow restartPolicy=Always, so their containers restart unless one carries its own policy. Job uses OnFailure or Never to let its Pods reach a terminal Succeeded or Failed phase instead of looping forever.

    Play from step 5

Sources