The Deployment controller turns "I want 3" into three running Pods, whatever happens.
One loop, three situations. The controller never needs to know why the numbers differ; it only closes the gap.
Observed: 2 Pods
+ 1 missing
A node died and took a Pod with it. Desired is 3, actual is 2.
Action: create 1 Pod
Observed: 4 Pods



Someone started an extra Pod by hand that matches the selector. Desired is 3, actual is 4.
Action: delete 1 Pod
Observed: 3 Pods

match
Everything agrees.
Action: do nothing, check again
Controllers are everywhere
Deployment, ReplicaSet, Node, Job, EndpointSlice, PersistentVolume and more. The controller manager runs dozens of loops in one process.
Level-triggered, not edge-triggered
A controller reacts to the current state, not to a single event. If it misses an event or restarts, the next pass still finds the gap.