Concept · Running systems

Desired state and reconciliation

Declare what should exist; a controller keeps comparing it with what does and closes the gap.

3 mincontrollerdeclarativeoperatordrift

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:

text
loop:
    desired  = read spec        (what you declared)
    actual   = observe world    (what exists right now)
    if actual != desired:
        take one step towards desired

Kubernetes 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) and status (observed), so you can always see how far from done the system is.

The same idea elsewhere

  • Terraform and other IaC: plan compares the code with the real infrastructure, and apply closes 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 replicas in 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.

Learn it in depth