DaemonSets

DaemonSets

One Pod per node - automatically, including nodes that join later.

graph TB DS[DaemonSet log-agent] --> P1[Pod on control01] DS --> P2[Pod on worker01] DS --> P3[Pod on worker02] DS --> P4[Pod on worker03] N[new node joins] -.-> P5[Pod created automatically]

There is no replicas field. The node list is the replica count.

Typical users: CNI agents, kube-proxy, log shippers, node exporters, storage drivers. Your cluster is already running several - kubectl get ds -A.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-logger
spec:
  selector:
    matchLabels: { app: node-logger }
  template:
    metadata:
      labels: { app: node-logger }
    spec:
      tolerations:
        - key: node-role.kubernetes.io/control-plane
          operator: Exists
          effect: NoSchedule       # without this, no Pod on the control plane
      containers:
        - name: logger
          image: busybox
          command: ["sh", "-c", "while true; do date; sleep 30; done"]

Two things that surprise people:

  • Taints. Control plane nodes carry a NoSchedule taint, so a DaemonSet skips them unless it tolerates it. Compare kubectl get ds -A with kubectl describe node control01 | grep -i taint.
  • Drain. kubectl drain refuses to evict DaemonSet Pods, which is why --ignore-daemonsets is on every drain command you will ever type. The Pod is supposed to be there as long as the node is.

Restrict a DaemonSet to a subset of nodes with nodeSelector - for example only nodes labelled storage=nfs.

References