Kubernetes DaemonSets Explained
A Kubernetes DaemonSet runs exactly one copy of a pod on every node in the cluster, automatically, for tasks like logging and monitoring agents.
A DaemonSet is a Kubernetes controller that ensures a copy of a specific pod runs on every node in the cluster — or on every node matching a selector — automatically, including nodes added after the DaemonSet was created. Where a Deployment manages a target number of replicas spread wherever the scheduler decides, a DaemonSet manages coverage: one pod per node, no more, no less.
What DaemonSets are for
Most workloads don’t care which node they land on. A stateless API server is happy to run three replicas on any three nodes the scheduler picks; that’s exactly what Deployments are built for. But some workloads are inherently per-node: something needs to run on every machine because it’s collecting or forwarding data that only exists locally on that machine.
Typical DaemonSet workloads:
- Log collectors — an agent like Fluentd or Fluent Bit that tails container logs on each node and ships them to a central store. See log aggregation explained for the pipeline this usually feeds into.
- Node monitoring agents — exporters that scrape node-level metrics (CPU, memory, disk) for a system built on logs, metrics, and traces.
- Cluster networking components — CNI plugins and kube-proxy itself often run as DaemonSets, since networking setup is inherently per-node.
- Storage daemons — a distributed filesystem client that needs a process running on every node that might mount its volumes.
- Security agents — an intrusion-detection or eBPF-based sensor that needs kernel-level visibility into every node, not just some of them.
How scheduling differs from a Deployment
A Deployment’s ReplicaSet asks the scheduler to place N pods somewhere sensible, balancing resource requests across available nodes; if you scale a cluster from 5 nodes to 50, your Deployment still runs the same number of replicas unless you change it or attach a horizontal pod autoscaler. A DaemonSet works the opposite way: the node count is the replica count. Add a node, and the DaemonSet controller schedules a new pod onto it without anyone touching a replicas field, because there is no such field — DaemonSets don’t have one. Remove a node, and its pod is garbage collected along with it.
This inversion is enforced by a scheduling detail specific to DaemonSets: by default they bypass normal scheduler resource-fit scoring in favor of always placing one pod per matching node, and they tolerate the NoSchedule taints that control-plane nodes usually carry, which is why kube-proxy or a CNI agent can run even on nodes that reject ordinary workloads.
| Deployment | DaemonSet | |
|---|---|---|
| Replica count | Fixed number you set, or autoscaled | One per matching node, automatic |
| New node behavior | No change unless autoscaled | New pod scheduled automatically |
| Removed node behavior | Pod rescheduled elsewhere | Pod is simply gone |
| Typical use | Stateless application workloads | Per-node agents and infrastructure |
| Update strategy | RollingUpdate or Recreate | RollingUpdate or OnDelete |
Targeting a subset of nodes
A DaemonSet doesn’t have to target every node. A nodeSelector or node affinity rule restricts it to a subset — for example, running a GPU-monitoring agent only on nodes labeled gpu: "true", rather than wasting a pod slot on every CPU-only node in the cluster. This is the same label-matching mechanism that governs pod placement generally; a DaemonSet is just a controller that reads “every node matching this selector” instead of “N nodes, any that fit.”
Updates and health
DaemonSets support the same RollingUpdate strategy as Deployments: change the pod template, and the controller replaces pods node by node, respecting maxUnavailable so you don’t take down your logging agent on every node simultaneously. The older OnDelete strategy leaves existing pods alone until you delete them manually, useful when a per-node agent restart is riskier than the update itself — for example, a CNI plugin update that could briefly interrupt networking on that node.
Because DaemonSet pods are infrastructure, not application logic, it’s worth giving them the same liveness and readiness probes you’d give any other workload, and modest resource requests — an unbounded log collector that starts consuming a node’s memory can degrade every other pod scheduled there.
The takeaway
A DaemonSet exists for the specific shape of problem where “one instance everywhere” is the requirement, not “N instances somewhere” — log shippers, node exporters, CNI plugins, and per-node security agents all fit that shape. It automatically tracks the cluster’s node membership so you never manually reconcile pod count against node count, which is exactly the property Deployments don’t give you and DaemonSets exist to provide.
Tagged
Keep reading
Chisato · · 4 min read Kubernetes Init Containers Explained
Init containers run to completion before a pod's main containers start, making them the standard way to handle setup steps and startup ordering.
Chisato · · 4 min read Kubernetes Service Types: ClusterIP vs NodePort vs LoadBalancer
Kubernetes offers four Service types for exposing pods on the network. How ClusterIP, NodePort, LoadBalancer, and ExternalName each route traffic.
Chisato · · 4 min read Helm vs Kustomize for Kubernetes Config
Helm templates and packages Kubernetes manifests with a templating language; Kustomize patches plain YAML declaratively, with no templates at all.