DaemonSet Controller
How does a DaemonSet decide how many Pods to run, when there is no replicas field to set? With no nodeSelector or affinity it runs one Pod on every eligible Node, and with a selector it matches each Node against it, so desiredNumberScheduled is computed from the cluster, not declared by you. Labelling a Node to match adds a Pod, removing the Node takes its Pod and nothing is rescheduled, and updateStrategy picks RollingUpdate with maxUnavailable or OnDelete.
Play the animation 6 steps, animated, best on a wide screen
DaemonSet Controller, step by step
-
The controller reads no replica count, because a DaemonSet has no replicas field. It lists Nodes through the API and matches each one against the nodeSelector in its Pod template. All three Nodes carry logging=enabled, so desiredNumberScheduled counts three. Nothing is running yet.
Play from step 1 -
The controller creates one Pod per matching Node through the API, each one pinned to its own Node by nodeAffinity. A DaemonSet keeps exactly one Pod per Node, and only a non-zero maxSurge during a rollout ever puts a second there, so the fleet follows the Node set instead of a replica number. A Node counts in numberReady once its Pod reports Ready.
Play from step 2 -
Node-4 joins the cluster, but it carries no logging=enabled label, so the nodeSelector in the Pod template does not select it. The controller sees the new Node object and leaves desiredNumberScheduled at three. Joining the cluster is not what earns a Node a Pod, matching the selector is.
Play from step 3 -
An operator labels Node-4 with logging=enabled. The controller watches Node objects, sees the update, recomputes desiredNumberScheduled to four and creates one Pod there. The three Pods already running are untouched, because the controller reconciles the difference and nothing about their Nodes changed.
Play from step 4 -
The image is bumped from fluentd v1 to v2. RollingUpdate with maxUnavailable=1 replaces the Pods one Node at a time: numberReady drops to three while the Pod on Node-1 is recreated, and is back at four once the v2 Pod is Ready. Log collection keeps running on the rest. OnDelete would instead wait until you delete each Pod by hand.
Play from step 5 -
Node-2 leaves the cluster and its Node object is deleted, so desiredNumberScheduled drops back to three and the Pod on Node-2 is garbage collected, not recreated elsewhere as a Deployment replica would be. A drain would not have removed it: a drain never evicts running DaemonSet Pods.
Play from step 6