Chapter 37 of 47 · More workload types

DaemonSets: one Pod on every node

A Deployment asks "how many copies of my app do users need?". Some programs do not care about users at all. They look after the machine: collect its logs, measure its CPU, set up its network. Those need exactly one copy on every node, and that is what a DaemonSet gives you.

The idea: a caretaker in every building

Imagine a company with many office buildings. Each building needs its own caretaker who checks the heating and empties the bins. You never want two caretakers in one building, and you never want a building without one. When the company buys a new building, a caretaker moves in on day one. When a building is sold, its caretaker leaves with it.

Nodes are the buildings. A DaemonSet is the rule "every building gets one caretaker".

A DaemonSet places one Pod on each nodeThree worker nodes each run one log-agent Pod created by the DaemonSet. App Pods from a Deployment are spread unevenly: two on node 1, one on node 3, none on node 2. DaemonSet log-agent node-1 node-2 node-3 log-agent log-agent log-agent posts posts posts
Purple: the DaemonSet, exactly one per node. Teal: a Deployment, placed wherever there is room.

DaemonSet vs Deployment

DeploymentDaemonSet
How many Pods?You choose: replicas: 3One per matching node; there is no replicas field
Where?Wherever the scheduler finds roomOn every node (or every node you select)
New node joinsNothing happensA Pod is started on it automatically
Node removedIts Pods are recreated elsewhereIts Pod simply goes away
ServesYour usersThe node itself, and the cluster

Try it: nodes come and go

Add and remove nodes, then try the two switches. Watch the DaemonSet keep "one per matching node" without you ever choosing a number:

The YAML

It looks like a Deployment without replicas. Click the highlighted parts:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: log-agent
  namespace: kube-system
spec:
  selector:
    matchLabels:
      app: log-agent
  template:
    metadata:
      labels:
        app: log-agent
    spec:
      tolerations:
        - key: node-role.kubernetes.io/control-plane
          operator: Exists
          effect: NoSchedule
      containers:
        - name: agent
          image: fluent/fluent-bit:3.0
          resources:
            requests: { cpu: 50m, memory: 64Mi }
            limits:   { memory: 128Mi }
          volumeMounts:
            - name: varlog
              mountPath: /var/log
              readOnly: true
      volumes:
        - name: varlog
          hostPath:
            path: /var/log

kind: DaemonSet

Same selector and template as a Deployment, but no replicas. The number of Pods is "however many nodes match".

$ kubectl get daemonset -n kube-system
NAME         DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR
log-agent    3         3         3       3            3           <none>
kube-proxy   3         3         3       3            3           kubernetes.io/os=linux

DESIRED is not something you typed: it is the number of matching nodes. Note that kube-proxy itself runs as a DaemonSet.

What people run as DaemonSets

Log collectors

Fluent Bit, Vector, Promtail: read every container's logs from the node and ship them to one place.

Node metrics

Prometheus node-exporter: CPU, memory and disk of each machine.

Networking

kube-proxy and the CNI plugin (Calico, Cilium) that wires Pods together (chapter 25).

Storage and security

CSI node drivers that attach disks, security scanners watching every process.

Your blog app's services do not belong here. posts and comments serve users, so they stay Deployments.

Only some nodes

Not every agent belongs everywhere. A GPU monitor only makes sense on GPU machines:

spec:
  template:
    spec:
      nodeSelector:
        accelerator: nvidia          # only nodes with this label get a copy
$ kubectl label node node-4 accelerator=nvidia     # node-4 now gets one
$ kubectl label node node-4 accelerator-           # remove the label: its copy is deleted

Node affinity works too, for more complex rules. Both are covered in chapter 40.

Talking to a DaemonSet Pod

Most DaemonSets push data out (to a log server, to Prometheus) and nobody calls them. When something does need to reach one, there are three common ways:

containers:
  - name: agent
    ports:
      - containerPort: 24224
        hostPort: 24224          # open this port on the node's own IP

Each app talks to the agent on its own node, using the node IP. Fast and local. The app can learn its node's IP from the Downward API (chapter 20).

Updating a DaemonSet

Change the image and apply, just like a Deployment. Two update strategies:

RollingUpdate (default)

Replaces the copy on one node at a time (maxUnavailable: 1). Each node briefly has no agent while its new copy starts.

OnDelete

Nothing happens until you delete a Pod; its replacement then uses the new template. Gives full control, for example to upgrade a network plugin one node at a time.

$ kubectl set image daemonset/log-agent agent=fluent/fluent-bit:3.1 -n kube-system
$ kubectl rollout status daemonset/log-agent -n kube-system

Static Pods

A static Pod is a Pod file placed directly in a folder on the node, usually /etc/kubernetes/manifests/. The node's kubelet runs it by itself, without the API server or any controller. That is how many clusters start the control plane: the API server cannot schedule itself before it exists. You will see these Pods (with the node name added to their names) in kube-system, but for your own agents, use a DaemonSet.

Which one?

Recap

Quick check

You add two new nodes to the cluster. How many new log-agent Pods do you need to create?
Show answer

None. The DaemonSet notices the new nodes and starts one copy on each, automatically.

DaemonSets: common questions

What is the difference between a DaemonSet and a Deployment?

A Deployment runs as many replicas as you choose, wherever there is room. A DaemonSet runs exactly one Pod on every matching node and follows nodes as they join or leave.