DaemonSets
Summary
- A DaemonSet ensures a copy of a pod runs on every matching node, adding and removing pods automatically as nodes join and leave.
- Insight: A DaemonSet has no replica count; its size is defined by the set of nodes it targets.
- Key Concepts: node-scoped placement, tolerations for tainted nodes, host access via hostPath and hostNetwork, and RollingUpdate across nodes.
- When to Use: Per-node infrastructure such as log collectors, metrics exporters, CNI plugins, and CSI node drivers.
- Limitations: DaemonSet pods compete for node resources and often need elevated privileges, so they demand tight limits and careful security.
- Related Topics: Node taints and tolerations, node affinity, Pod Security Standards, rolling updates.
Recipe
Define a DaemonSet with a pod template and, if needed, a node selector and tolerations.
The controller schedules one pod per matching node with no replica field.
Apply it and confirm one pod exists per node.
kubectl apply -f daemonset.yaml
kubectl get daemonset -n monitoring
kubectl get pods -o wide -n monitoringWorking Example
This node exporter runs on every node, including tainted ones, and reads host metrics safely.
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
namespace: monitoring
spec:
selector:
matchLabels:
app: node-exporter
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
template:
metadata:
labels:
app: node-exporter
spec:
hostNetwork: true
hostPID: true
tolerations:
# run even on control-plane nodes
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
securityContext:
runAsNonRoot: true
runAsUser: 65534
containers:
- name: node-exporter
image: prom/node-exporter:v1.8.2
args:
- "--path.rootfs=/host"
ports:
- name: metrics
containerPort: 9100
resources:
requests:
cpu: "50m"
memory: 64Mi
limits:
memory: 128Mi
volumeMounts:
- name: rootfs
mountPath: /host
readOnly: true
volumes:
- name: rootfs
hostPath:
path: /Verify the rollout covers every node and inspect a pod.
kubectl rollout status daemonset/node-exporter -n monitoring
kubectl describe daemonset/node-exporter -n monitoringThe DESIRED count in get daemonset equals the number of matching nodes.
Deep Dive
How placement works
The DaemonSet controller watches nodes and creates a pod for each node that matches the selector and tolerates its taints.
When Karpenter or the cluster autoscaler adds a node, a DaemonSet pod appears there without any change to the manifest.
Draining or removing a node deletes its DaemonSet pod along with the node.
Targeting a subset of nodes
Use spec.template.spec.nodeSelector or affinity to restrict a DaemonSet to specific nodes, such as GPU or storage hosts.
For example, nodeSelector: { gpu: "true" } runs the pod only on labeled GPU nodes.
This is how you deploy device plugins or drivers to hardware-specific pools.
Tolerations and critical daemons
Kubernetes taints nodes that are not-ready, unschedulable, or under memory or disk pressure.
Core DaemonSets like CNI plugins and CSI node drivers must tolerate these taints, or networking and storage never initialize on a fresh node.
A common pattern is a broad toleration with operator: Exists so the daemon lands regardless of taint.
Rolling updates across nodes
DaemonSets support RollingUpdate with maxUnavailable to bound how many nodes update at once.
Setting maxUnavailable: 1 updates node agents one node at a time, which protects cluster-wide observability during a rollout.
There is also maxSurge for daemons that can briefly run two copies during an update.
Host access and security
Per-node agents often need host resources, so they mount hostPath, use hostNetwork, or set hostPID.
These are privileges that violate the restricted Pod Security Standard, so run infrastructure DaemonSets in a dedicated namespace labeled for a looser profile and keep them minimal, scanned, and pinned by digest.
Gotchas
A DaemonSet has no replicas field; adding one is a manifest error, and count comes only from matching nodes.
Missing tolerations mean the daemon silently skips control-plane, tainted, or pressured nodes, leaving blind spots in monitoring or networking.
Unbounded resource requests let a busy log agent starve tenant workloads, so always set requests and tight limits.
A too-aggressive maxUnavailable can black out observability across many nodes at once during an update.
Broad hostPath mounts are a real attack surface; scope them to the exact paths the agent needs and mount read-only where possible.
Deploying a DaemonSet to a huge cluster without limits can also pressure the API server and node kubelets, so test at scale.
Alternatives
A Deployment is the right tool when you want N replicas placed anywhere rather than one per node.
A static pod managed directly by a node's kubelet is an option for the most foundational components that must run before the API server is reachable, at the cost of central management.
A sidecar container inside each application pod can collect that pod's logs when you need per-app rather than per-node collection, though it multiplies resource overhead.
Cloud-managed node agents installed by the provider can replace self-managed DaemonSets for logging or monitoring, trading control for less operational burden.
FAQs
How many pods does a DaemonSet run? Exactly one per node that matches its selector and tolerates the node's taints. There is no replica count.
Do new nodes get the DaemonSet automatically? Yes. The controller schedules a pod as soon as a matching node joins the cluster.
How do I run a DaemonSet only on some nodes?
Add a nodeSelector or node affinity so only labeled nodes match, such as GPU or storage pools.
Why is my DaemonSet skipping the control-plane nodes? Those nodes carry a taint. Add a matching toleration so the pod can be scheduled there.
Can DaemonSets do rolling updates?
Yes, with an updateStrategy of RollingUpdate and maxUnavailable to update nodes gradually.
Is Docker involved in running these pods? No. containerd runs the pods via the CRI on each node. Docker is only for building the images you deploy.
Related
- When Identity and Node Placement Matter
- StatefulSets Basics
- Headless Services + StatefulSets
- StatefulSets Best Practices
Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).