In a Kubernetes object such as a Deployment, what is the difference between the spec section and the status section, and who writes each one?
answer
- spec = desired, status = observed
- controllers write status, humans write spec
- generation vs observedGeneration
- conditions = machine-readable why
- status is a separate subresource
basics
~10 sspec is the desired state you declare; status is the observed state the system reports. You and your tools write spec, controllers write status. Kubernetes keeps acting until status matches spec.
solid answer
~50 sNearly every Kubernetes object has two halves. **spec** is the desired state you declare (3 replicas, this image, this port), written by you via kubectl apply, Helm, or a GitOps tool. **status** is the observed state (replicas ready, conditions, assigned IP), written by the controller that owns the object based on what it actually sees. Hand-editing status is pointless: the controller overwrites it on its next pass. The gap between the two drives everything. A controller reads spec, compares it with the real world, acts to close the gap, and records what it observed in status. That loop never stops, which is why Kubernetes self-heals. Practically: you debug by comparing spec with status (kubectl describe, the Conditions list); status.observedGeneration versus metadata.generation tells you whether the controller has even processed your latest spec; and status is usually a separate subresource, so writing it needs its own RBAC verb and updating spec does not clobber it.
code
bash · 3 lineskubectl get deploy web -o jsonpath='{.spec.replicas}{"\n"}{.status.readyReplicas}{"\n"}'
kubectl get deploy web -o jsonpath='{.metadata.generation} {.status.observedGeneration}{"\n"}'
kubectl get deploy web -o jsonpath='{range .status.conditions[*]}{.type}={.status} {.reason}{"\n"}{end}'go deeper
Recall the definition crisply: spec = what I want, status = what is, controllers close the gap. Give one concrete Deployment example.
Add the mechanics: status subresource, conditions structure, generation versus observedGeneration, and why editing status is futile.
Frame it as the debugging method — read spec, read status, explain the delta — and mention RBAC separation via the status subresource.
Discuss it as an API design principle: derived state must be recomputable, intent must be the single durable source, and CRD authors should keep no unique data in status.
## Two halves of every object A Kubernetes resource is a document with a stable shape: apiVersion, kind, metadata, then almost always spec and status. **spec is desired state.** A declaration of intent authored by a human or a tool: "I want 3 replicas of image app:1.4 with this memory request." It says nothing about how to get there and nothing about what exists right now. It is durable — it stays exactly as written until someone changes it. **status is observed state.** A report written by the controller responsible for that kind: how many replicas are ready, which conditions hold, what IP was assigned, what generation the controller last acted on. It is derived, not authored. If you edit it by hand the owning controller recomputes it from reality and your edit disappears. ## Why the split exists Separating intent from observation is what makes the system declarative. The user writes only intent; the machinery owns the truth. Any component can look at an object and compute the delta (desired minus observed) without knowing what happened before — no event history, no transcript of past commands. If the delta is zero, do nothing. If not, act. It also gives clean ownership boundaries. RBAC can grant a controller permission to write only the status subresource of a resource, not its spec, so a controller cannot silently rewrite your intent. Conversely, a user's `kubectl apply` of the whole document does not overwrite status, because status is served and written through a separate endpoint (`/status`). ## Reading the pair when debugging The most useful debugging habit in Kubernetes is: read spec, read status, and explain the difference. - `spec.replicas: 3` with `status.readyReplicas: 1` means the controller is trying and something is blocking two pods — check events and pod status. - `metadata.generation: 7` with `status.observedGeneration: 5` means the controller has not yet processed your latest edit; it may be backlogged, crash-looping, or not running at all. - The `status.conditions` array is the standard, structured place controllers explain themselves: each condition has a type (Available, Progressing, Ready), a status of True/False/Unknown, plus reason and message strings. Conditions are the machine-readable version of "why isn't this working". ## Not every field follows the pattern A few objects have no meaningful status (ConfigMap, Secret). Some carry state that is neither pure intent nor pure observation — a Service's `spec.clusterIP` is written by the API server on creation and then immutable, and `metadata.deletionTimestamp` plus finalizers control deletion. Custom resources are expected to follow the convention, and CRDs opt in explicitly with a status subresource so controllers can be granted status-only write access. ## What this implies day to day Don't script against status as if you set it. Don't try to "fix" a bad status by editing it. When something is wrong, change spec (or the world) and let the controller re-observe. And when writing your own controller, treat status as strictly derived output: recomputable at any time from the cluster, never the only copy of important information.
- What does it mean when metadata.generation is higher than status.observedGeneration?generation is bumped by the API server every time spec changes; observedGeneration is written by the controller to record the generation it last reconciled. If observedGeneration lags, the controller has not processed your newest spec yet — it may be backlogged, crash-looping, or not running at all. It is the first thing to check when an edit appears to have no effect.
- Why can't you just edit status to mark a stuck object as healthy?status is derived output, not input. The owning controller recomputes it on the next reconcile from what it actually observes, so any manual edit is overwritten within seconds. Fixing the object means changing spec or fixing the underlying condition it is reporting.
A thermostat: spec is the temperature you dialed in, status is the thermometer reading. You set the dial; the thermostat reports and works to close the gap.
saying these in an interview costs you the question
- Saying users write status or that editing status changes behavior
- Claiming Kubernetes stops once desired state is reached, rather than continuously re-checking
- Confusing conditions with events — conditions are current state on the object, events are transient records
- Thinking spec is updated by controllers to reflect reality (for example, that the Deployment lowers spec.replicas when pods fail)