Controllers and the Reconciliation Loop

Controllers are where Kubernetes's core idea — declarative desired state plus reconciliation — becomes machinery. A controller is a loop that watches "what you want" versus "what exists" and acts to close the gap, forever. Self-healing, scaling, and zero-downtime rollouts are all just controllers doing that one thing. This is the engine of Kubernetes.

The first post named declarative-desired-state-plus-reconciliation as Kubernetes’s core idea; the pod post noted pods are managed by higher-level objects. This post covers those objects — controllers — and the reconciliation loop that is Kubernetes’s engine. A controller continuously drives actual state toward desired state, and the workload controllers (Deployments, ReplicaSets, and others) are how you actually run applications. Understand controllers and you understand how Kubernetes does everything.

The reconciliation loop

A controller is a control loop that watches some part of the cluster’s state and works to make actual match desired — the concrete implementation of the core idea. Every controller runs the same loop, forever:

loop forever:
    observe   — what is the ACTUAL state? (what pods exist, are they healthy?)
    compare   — how does actual differ from DESIRED? (you want 3, there are 2)
    act       — take action to close the gap (create 1 more pod)
    (repeat)

This loop is the engine of Kubernetes. It’s level-based, not edge-based: the controller doesn’t react to events (“a pod died”) so much as continuously compare state (“desired 3, actual 2, fix it”) — which is more robust, because it self-corrects toward the desired level regardless of what happened or whether it missed an event. This is why Kubernetes is resilient: even if something is missed or the controller restarts, the next loop iteration re-observes actual vs desired and corrects. The reconciliation loop is how declarative desired state becomes reality, continuously.

ReplicaSets: keeping N pods running

The most fundamental workload controller is the ReplicaSet, whose job is simple and illustrative: keep exactly N copies (replicas) of a pod running. You declare “I want 3 replicas of this pod,” and the ReplicaSet’s reconciliation loop ensures 3 are always running:

The ReplicaSet is pure “keep actual replica count == desired replica count,” forever. This single controller gives you self-healing (crashed/lost pods are replaced) and scaling (change the number) — both falling directly out of the reconciliation loop. You rarely use ReplicaSets directly, though; you use Deployments, which manage ReplicaSets to add rollouts.

Deployments: rollouts and rollbacks

The Deployment is the controller you’ll use most for stateless applications. It manages ReplicaSets to provide not just “keep N pods running” but controlled rollouts and rollbacks of new versions:

Deployment (desired: version v2, 3 replicas)
  → manages ReplicaSets to roll from v1 to v2 gradually:
     create v2 pods, wait until healthy, remove v1 pods, step by step
     → zero-downtime rolling update; roll back if v2 is unhealthy

So the Deployment is the practical unit for running a stateless service: declare what you want (version, replicas), and it handles keeping it running, updating it safely, and rolling back — all via reconciliation. The layering is: Deployment manages ReplicaSets manages Pods — each a controller reconciling toward desired state, composing into safe, self-healing, updatable application management.

The other workload controllers

Deployments are for stateless apps; Kubernetes has other workload controllers for other shapes, each a reconciliation loop for a different need:

Each is a controller applying the reconciliation loop to a different workload shape: N interchangeable replicas (Deployment), stable-identity replicas (StatefulSet), one-per-node (DaemonSet), run-to-completion (Job), on-a-schedule (CronJob). Choosing the right one is choosing the reconciliation behavior your workload needs — stateless service → Deployment, stateful → StatefulSet, node agent → DaemonSet, batch → Job/CronJob.

Controllers as the engine

The takeaway: controllers are Kubernetes’s engine — each a reconciliation loop (observe → compare → act, forever) that drives actual state toward the desired state you declared, level-based and self-correcting. The workload controllers turn this into application management: ReplicaSets keep N pods running (self-healing + scaling), Deployments add zero-downtime rollouts and rollbacks (the workhorse for stateless apps), and StatefulSets/DaemonSets/Jobs/CronJobs handle stateful, per-node, and batch/scheduled workloads. Everything Kubernetes does for your workloads — keep them running, scale them, update them safely, run them on schedule — is a controller reconciling toward desired state. This is the core idea (post one) made into machinery. The next post covers how these ever-changing pods are reached over the network: services.

Key takeaways

Further reading

Sources & References

Controllers and Deployments