A Pod's status.phase is Pending (accepted, but images still pulling or init containers running), Running, Succeeded (all containers exited 0), Failed (all stopped, at least one with an error, none restarting) or Unknown (the node stopped reporting). spec.restartPolicy decides what the kubelet does when a container exits: Always (the default, for servers), OnFailure (batch work, Batch and Node-Level Workloads) or Never:
for p in Always OnFailure Never; do
kubectl run crash-${p,,} --restart=$p --image=localhost:33500/booknest-api:1.3 \
--command -- node -e 'process.exit(1)' >/dev/null
done
C=NAME:.metadata.name,PHASE:.status.phase,RESTARTS:.status.containerStatuses[0].restartCount
sleep 40 && kubectl get pods -l 'run in (crash-always,crash-onfailure,crash-never)' \
-o custom-columns=$C,STATE:.status.containerStatuses[0].state.*.reasonNAME PHASE RESTARTS STATE crash-always Running 3 Error crash-never Failed 0 Error crash-onfailure Running 3 Error
Always and OnFailure restarted the container three times in a Running Pod; Never left it Failed for kubectl 5,150 logs. Restarts back off exponentially (10 s, 20 s, 40 s, capped at five minutes); during a wait, kubectl get pods shows CrashLoopBackOff or, as here, the last exit reason. On deletion the kubelet sends SIGTERM, waits up to terminationGracePeriodSeconds, then sends SIGKILL; BookNest's server.js closes cleanly on SIGTERM.