Docker & Kubernetes
Reconcile loop
Learn the controller reconcile loop.
The reconcile loop
All Kubernetes controllers follow the same pattern: the reconcile loop. A controller reads the desired state (spec) and the actual state (status, the objects in the world), calculates the difference, and takes the smallest action to close it; then it starts again.
for {
desired := read spec
actual := observe the world
if desired != actual {
take the action closing the gap // create, delete, update pods
}
update status
}
The loop is level-triggered: it relies on the latest state, not on events. Even if an event is missed, the gap is caught on the next round.
spec, status and watch
The user writes each object's spec, the controller its status. Instead of constantly querying the API, controllers listen to a stream of changes with watch; resourceVersion specifies from which version it's watched. observedGeneration shows which version of the spec the controller has processed:
$ kubectl get deploy web -o jsonpath='{.metadata.generation} {.status.observedGeneration}'
7 7 # the controller processed the latest spec
$ kubectl get pods --watch -o name
Exercise Observe reconciliation
Write three commands: print the generation and observedGeneration of the web deployment with jsonpath='{.metadata.generation} {.status.observedGeneration}'; scale web to 5 replicas; watch the ReplicaSets live with -l app=web.
Show example solution
kubectl get deploy web -o jsonpath='{.metadata.generation} {.status.observedGeneration}'
kubectl scale deploy web --replicas=5
kubectl get rs -l app=web -w
Test yourself
-
What is the advantage of level-triggered design over edge-triggered?
- Missed events don't cause lasting inconsistency; the latest state is read again
- Less code
- Less memory
- No network needed
Show answer
Missed events don't cause lasting inconsistency; the latest state is read again — Even if the controller crashes, it reaches the right state after restarting.
-
Listen to the change stream.
kubectl get pods ____ -o name
Show answer
kubectl get pods --watch -o name
-
Match.
- spec
- What the user wants
- status
- What the controller observed
- watch
- Change stream
- observedGeneration
- Processed spec version
Next lesson: Summary - Internals