Kubernetes DaemonSets Explained with Practical Examples
Learn how DaemonSets run exactly one pod per node for logging, monitoring, and networking agents. Includes tolerations and update strategies.
What you'll learn
- ✓What DaemonSets are and when to use them instead of Deployments
- ✓How DaemonSets schedule pods on every node
- ✓Targeting specific nodes with node selectors and tolerations
- ✓Update strategies for rolling out DaemonSet changes
- ✓Common patterns for log collectors, monitoring agents, and CNI plugins
Prerequisites
None — this post is self-contained.
A Deployment runs N replicas wherever the scheduler finds room. A DaemonSet runs exactly one pod on every node (or a selected subset). This distinction makes DaemonSets the right choice for node-level infrastructure: log collectors, metrics exporters, storage daemons, and network plugins.
When to Use a DaemonSet
Use a DaemonSet when the workload must run on every node:
- Log collection - Fluentd, Fluent Bit, or Promtail tailing container logs on each node
- Monitoring - Node Exporter exposing host metrics to Prometheus
- Networking - CNI plugins like Calico or Cilium that configure pod networking
- Storage - CSI node plugins that mount volumes on each node
- Security - Falco or other runtime security agents inspecting system calls
If your workload does not need to be on every node, use a Deployment instead.
Basic DaemonSet
A minimal DaemonSet that runs a log collector on every node:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentbit
namespace: logging
labels:
app: fluentbit
spec:
selector:
matchLabels:
app: fluentbit
template:
metadata:
labels:
app: fluentbit
spec:
containers:
- name: fluentbit
image: fluent/fluent-bit:latest
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
volumeMounts:
- name: varlog
mountPath: /var/log
readOnly: true
- name: containers
mountPath: /var/lib/docker/containers
readOnly: true
volumes:
- name: varlog
hostPath:
path: /var/log
- name: containers
hostPath:
path: /var/lib/docker/containers
Apply it, and Kubernetes creates one Fluent Bit pod on every node in the cluster. When a new node joins, the DaemonSet controller automatically schedules a pod on it. When a node is removed, the pod is garbage collected.
How Scheduling Works
DaemonSets bypass the normal scheduler. The DaemonSet controller creates a pod for each eligible node and sets the spec.nodeName field directly (in older versions) or uses node affinity (in current versions). This means:
- DaemonSet pods ignore most scheduling constraints like resource pressure
- They tolerate the
node.kubernetes.io/not-readytaint by default - They are not evicted during node drain unless explicitly told to
Check DaemonSet status with:
kubectl get daemonset -n logging
# Output:
# NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE
# fluentbit 5 5 5 5 5
DESIRED matches the number of eligible nodes. If READY is less than DESIRED, pods are failing to start.
Targeting Specific Nodes
Sometimes you want a DaemonSet on a subset of nodes. Use a node selector:
spec:
template:
spec:
nodeSelector:
node-role.kubernetes.io/worker: ""
containers:
- name: agent
image: monitoring-agent:latest
This runs the agent only on nodes labeled node-role.kubernetes.io/worker. Control plane nodes are excluded.
For more expressive matching, use node affinity:
spec:
template:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: storage-agent
image: storage-agent:latest
Tolerations for Control Plane Nodes
By default, control plane nodes have taints that prevent regular workloads from scheduling on them. If your DaemonSet must run on control plane nodes (for example, a monitoring agent), add tolerations:
spec:
template:
spec:
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
containers:
- name: node-exporter
image: prom/node-exporter:latest
To run on every node regardless of taints, use a blanket toleration:
tolerations:
- operator: Exists
Be cautious with blanket tolerations. They schedule pods even on nodes tainted for specific reasons like being unready or having disk pressure.
Update Strategies
DaemonSets support two update strategies:
RollingUpdate (Default)
Pods are updated one node at a time. The old pod is terminated before the new one is created on the same node:
spec:
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 0
maxUnavailable controls how many nodes can have their DaemonSet pod down simultaneously. Setting it to 1 (the default) means nodes are updated sequentially. Setting it to 25% or a higher number speeds up rollouts at the cost of temporary gaps in coverage.
Starting in Kubernetes 1.22, maxSurge allows creating the new pod before terminating the old one, enabling zero-downtime updates for DaemonSets:
spec:
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
This creates the new pod first, waits for it to be ready, then terminates the old pod. This is ideal for networking plugins where a gap in coverage would disrupt traffic.
OnDelete
Pods are only updated when manually deleted:
spec:
updateStrategy:
type: OnDelete
This gives you full control over the rollout order. Update a node by deleting its DaemonSet pod, and the controller creates a replacement with the new spec. This is useful for critical infrastructure where you want to update nodes one at a time during maintenance windows.
Monitoring a DaemonSet Rollout
# Watch rollout progress
kubectl rollout status daemonset/fluentbit -n logging
# Check rollout history
kubectl rollout history daemonset/fluentbit -n logging
# Roll back to previous version
kubectl rollout undo daemonset/fluentbit -n logging
Resource Limits
DaemonSet pods compete for resources with application pods on each node. Always set resource requests and limits to prevent a misbehaving agent from starving application workloads:
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
Account for DaemonSet resource consumption when sizing nodes. If every node runs a log collector (128 Mi), a monitoring agent (64 Mi), and a CNI plugin (128 Mi), that is 320 Mi of memory per node reserved for infrastructure before any application pods.
Priority Classes
Infrastructure DaemonSets should use a high-priority PriorityClass to avoid being evicted when a node is under memory pressure:
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: system-node-critical
value: 2000001000
globalDefault: false
description: "Critical node-level infrastructure"
---
spec:
template:
spec:
priorityClassName: system-node-critical
containers:
- name: fluentbit
image: fluent/fluent-bit:latest
Kubernetes provides built-in priority classes system-node-critical and system-cluster-critical for this purpose.
Practical Recommendations
Use DaemonSets for any workload that must run on every node. Always set resource requests to prevent resource starvation. Use RollingUpdate with maxSurge: 1 for zero-downtime updates of critical infrastructure. Add tolerations explicitly rather than using blanket tolerations. Assign high priority classes to infrastructure DaemonSets so they survive node pressure events. Monitor DESIRED vs READY counts to detect nodes where the DaemonSet pod is failing.
Related articles
- Kubernetes Kubernetes Persistent Volumes and Storage Classes
Understand PersistentVolumes, PersistentVolumeClaims, and StorageClasses to give your Kubernetes workloads reliable, portable storage.
- Kubernetes Kubernetes Network Policies: Pod-to-Pod Security Guide
Lock down pod communication with Kubernetes NetworkPolicies. Learn ingress and egress rules, label selectors, and namespace isolation.
- Kubernetes Kubernetes Resource Limits, Requests, and QoS Classes
Set CPU and memory requests and limits correctly. Understand QoS classes, OOMKilled errors, and CPU throttling in Kubernetes.
- Kubernetes Kubernetes Rolling Updates and Rollback Strategies
Master zero-downtime deployments with Kubernetes rolling updates, rollback commands, and deployment strategies like blue-green and canary.