Concept · Running systems
Desired state and reconciliation
Declare what should exist; a controller keeps comparing it with what does and closes the gap.
Imperative operations say what to do: "start 3 more containers." Declarative systems say what should be true: "there should be 5 replicas of this image." A controller then runs a reconciliation loop that keeps comparing the two and acting to close the gap:
loop:
desired = read spec (what you declared)
actual = observe world (what exists right now)
if actual != desired:
take one step towards desiredKubernetes is built entirely from these loops. You apply a Deployment saying replicas: 5. The Deployment controller makes sure a ReplicaSet exists. The ReplicaSet controller notices only 3 Pods and creates 2. The scheduler assigns them to nodes, and each node's kubelet starts their containers. Every component reconciles its own small piece.
Why it's robust
- Self-healing for free. Delete a Pod, or lose a node, and the loop sees 4 instead of 5 and creates another. Nothing special handles the failure; it's just another difference to close.
- Idempotent by design. Applying the same spec twice changes nothing. Re-running after a crash is always safe.
- Level-triggered, not edge-triggered. Controllers act on current state, not on a stream of events they might have missed. A controller that was down for ten minutes simply reconciles whatever it finds when it comes back.
- Status records progress. Objects carry
spec(desired) andstatus(observed), so you can always see how far from done the system is.
The same idea elsewhere
- Terraform and other IaC:
plancompares the code with the real infrastructure, andapplycloses the gap. Changes made by hand in the console show up as drift. - GitOps (Argo CD, Flux): the desired state is a Git repository, and a controller continuously syncs the cluster to it. Rollback is
git revert. - Autoscalers: the HPA's desired replica count is computed from metrics, then reconciled like any other.
Caveats
- Convergence takes time. "Applied" doesn't mean "running." Wait on status conditions or rollout status in your pipelines.
- Two controllers fighting over one field (for example, the HPA and a hard-coded
replicasin your GitOps manifests) will flip it back and forth forever. Give each field one owner. - Manual fixes get reverted. Change the source of truth instead.
Readiness checks are part of the "observe" step: they tell the controllers which Pods actually count.