KubeGlanceDownload
How kubectl decides what to put in the STATUS column

kubectl

How kubectl decides what to put in the STATUS column

kubectl get pods never shows status.phase. Here is the real algorithm behind the STATUS column, and why a pod reads Running while a container crash-loops.

· 7 min read

The STATUS column in kubectl get pods is not a field. There is no status.status in the Pod API, and it is not status.phase either — phase only has five possible values (Pending, Running, Succeeded, Failed, Unknown), and none of them is CrashLoopBackOff.

STATUS is computed client-side, by kubectl, every time you run the command. Knowing the algorithm explains most of the confusing output you have ever seen from it.

Where the value actually comes from

kubectl builds the column in printPod in pkg/printers/internalversion/printers.go. The logic runs roughly like this:

kubectl's printPod logic, in order. The last check overrides almost everything above it.

Two details in there explain most surprises.

The container list is walked backwards

kubectl iterates status.containerStatuses in reverse order, and the last container it examines wins. So in a pod with an app container and a sidecar, the status you see is generally the sidecar’s problem, not the app’s — the sidecar is usually later in the list.

This is why a pod can be genuinely broken while STATUS reads something bland, and why the fix is to stop trusting the column and look at containers individually:

kubectl get pod my-pod -o jsonpath='{range .status.containerStatuses[*]}{.name}{"\t"}{.ready}{"\t"}{.state}{"\n"}{end}'

That prints one line per container with its actual state, in list order. The container kubectl reported on is the last line.

Terminating overrides nearly everything

The deletionTimestamp check happens at the end, not the beginning. A pod that is being deleted shows Terminating regardless of what its containers are doing — unless the phase is already Succeeded or Failed, in which case the terminal phase wins.

This is why a crash-looping pod appears to “fix itself” the moment you delete it. It did not fix itself. It is still crash-looping. The column is just telling you about the deletion now instead.

Init containers get their own namespace of statuses

If init containers have not finished, STATUS is prefixed with Init:, and you get one of three shapes: Init:M/N (how many completed), Init:<reason> such as Init:CrashLoopBackOff, or Init:ExitCode:N.

One modern wrinkle: restartable init containers — sidecars declared with restartPolicy: Always in the init section — count as done once they are running, not once they exit. Without that rule, every pod using the sidecar pattern would sit at Init:0/1 forever.

Why RESTARTS says “3 (5m ago)”

There is no pod-level restart counter either. RESTARTS is the sum of restartCount across all container statuses, including init containers. The parenthetical is the most recent lastState.terminated.finishedAt across those containers — so it is “when the most recent restart happened”, not “when this pod started failing”. A pod that crashed 400 times last week and once five minutes ago reads 401 (5m ago).

Reading this correctly matters more than it looks

Every tool that shows you a pod list has to reimplement this. Get it wrong and you show Running for something that is not running, or invent a status kubectl never produces — which is worse, because now two tools disagree and you do not know which one is lying.

We ported this algorithm into KubeGlance from kubectl’s source and test it against captured API fixtures, precisely so the STATUS column in the app matches what kubectl get pods would have told you. When they agree, you can stop double-checking.

Away from your desk? KubeGlance is a native Kubernetes client for iPhone and iPad, with a full Mac app on the same core — pods, workloads, logs and events straight from your kubeconfig.

Get KubeGlance
#kubectl #pods #troubleshooting

The Kubernetes dashboard that fits in your pocket

KubeGlance is a native Kubernetes client for iPhone and iPad — the real dashboard, not a companion — with a full Mac app on the same core. Pods, workloads, logs and events, straight from your kubeconfig.

Download KubeGlance