DaemonSet on Every Node
Understand how to use DaemonSets in Kubernetes to run a pod on every node. This lesson covers core concepts, hands-on deployment, and when to choose DaemonSets over other workload types.
Focus: use daemonset to run on every node
You’ve deployed Deployments that keep a desired number of Pods alive, and StatefulSets that manage sticky identity for stateful workloads. But what happens when you need every node in your cluster to run a specific Pod — like a logging agent, a monitoring collector, or a security scanner? A normal Deployment won't guarantee a Pod lands on each node, and you'd have to manually scale or use complex affinity rules. That's exactly where a DaemonSet shines: it ensures one copy of a Pod runs on every node (or a subset, if you use node selectors). Without it, you'd be constantly rebalancing workloads or missing critical coverage on new nodes.
The problem this lesson solves
Imagine you run a 50-node Kubernetes cluster. You need a log-forwarder (like Fluentd or Filebeat) on every machine to ship logs to a central store. With a Deployment, you could run 50 replicas, but if a node is added or removed, you'd need to manually adjust the replica count. Worse, during rolling updates, Pods might land on the same node, leaving others uncovered. A DaemonSet automates this: whenever a new node joins the cluster, a new Pod is created on it; when a node is removed, the Pod is garbage-collected. The core pain is ensuring per-node infrastructure runs reliably without manual intervention.
Core concept / mental model
Think of a DaemonSet as a "one-per-node" guarantee. Whereas a Deployment ensures a total replica count across the cluster, a DaemonSet ties the number of replicas to the number of nodes. The controller watches the node list and creates or deletes Pods to match. Key properties:
- Node-level services: DaemonSets are ideal for workloads that must run on every node (or a targeted subset), such as log collectors, node monitoring daemons, CNI plugins, or storage daemons.
- Automatic scaling: If you scale your cluster up or down, the DaemonSet adjusts without any action from you.
- Scheduling control: DaemonSets respect node selectors, taints/tolerations, and affinity rules — you can limit which nodes run the Pod.
Pro tip: A DaemonSet’s Pod is created on a node before the node is marked
Readyin some cases (e.g., for CNI plugins). This makes DaemonSets essential for cluster bootstrapping.
How it works step by step
- You define a DaemonSet YAML with a Pod template (similar to a Deployment, but without
replicas). - Kubernetes DaemonSet controller watches the node API — it maintains a list of all nodes that match the DaemonSet’s node selector (default: all nodes).
- For each matching node, the controller ensures exactly one Pod is running. If no Pod exists, it creates one; if the Pod dies, it re-creates it.
- When a node is removed, the Pod is automatically deleted (no manual cleanup).
- If a DaemonSet updates its Pod template, the controller rolls out new Pods node-by-node (configurable with
updateStrategy).
Key differences from a Deployment
| Aspect | Deployment | DaemonSet |
|---|---|---|
| Replica count | User-specified (e.g., 5) | Tied to node count |
| Scheduling per node | Not guaranteed | Guaranteed one per node |
| Typical use case | Stateless apps, web servers | Node-level daemons |
| Rolling update | Global rollout | Node-by-node rollout |
| Respects node selectors | Yes | Yes |
Hands-on walkthrough
Let's create a simple DaemonSet that runs an Nginx Pod on every node. We'll verify it works and then clean up.
1. Create a DaemonSet YAML
Save this as nginx-daemonset.yaml:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nginx-per-node
labels:
app: nginx
spec:
selector:
matchLabels:
name: nginx
template:
metadata:
labels:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
ports:
- containerPort: 80
Note: No
replicasfield — the controller handles that.
2. Apply the DaemonSet
kubectl apply -f nginx-daemonset.yaml
3. Verify Pods run on every node
kubectl get daemonset
# Output (example for 3-node cluster):
# NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
# nginx-per-node 3 3 3 3 3 <none> 10s
Check each Pod's node:
kubectl get pods -o wide | grep nginx
# Output:
# nginx-per-node-abc12 node-1
# nginx-per-node-def34 node-2
# nginx-per-node-ghi56 node-3
You should see one Pod per node. If you have a single-node cluster (e.g., Minikube), you'll see exactly one Pod.
4. Clean up
kubectl delete daemonset nginx-per-node
Compare options / when to choose what
| Feature | DaemonSet | Deployment (with PodAntiAffinity) | Static Pod (kubelet-managed) |
|---|---|---|---|
| Guaranteed per node | Yes | Partial (hard affinity works but clumsy) | Yes |
| Managed by Kubernetes API | Yes | Yes | No (kubelet-managed) |
| Rolling updates | Built-in | Built-in | Manual |
| Best for | Node-level infra (monitoring, logging) | General apps that benefit from distribution | Cluster bootstrap (e.g., control plane) |
When to choose DaemonSet: - You need a Pod on every node (e.g., node-exporter, kube-proxy). - You want automatic scaling with cluster size. - You need simple rolling updates per node.
When not to: - You need exactly N Pods total (use Deployment). - You need ordering between Pods (use StatefulSet). - You are managing control-plane components (use static Pods or systemd).
Troubleshooting & edge cases
Pod not created on a node
Check if the node has taints that your DaemonSet Pod doesn't tolerate. By default, DaemonSet Pods ignore node.kubernetes.io/unschedulable but respect other taints (e.g., node-role.kubernetes.io/control-plane). To run on master nodes, add tolerations:
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
DaemonSet starts Pod before node is Ready
This is by design — necessary for CNI and critical add-ons. If your Pod requires something that isn't available, set node.kubernetes.io/not-ready toleration.
Rolling update hangs
If a Pod fails to start on a node, the DaemonSet controller stops the rollout until the Pod becomes Ready. Check Pod logs with kubectl logs <pod-name>. Common issues: image pull errors, resource limits, or volume mounts.
One node runs two Pods
If you see more than one Pod per node, check that your selector.matchLabels is unique. Multiple DaemonSets can select overlapping labels, but each DaemonSet ensures exactly one per node. Use unique labels per DaemonSet.
What you learned & what's next
You now understand how to use a DaemonSet to run a Pod on every node — from the core concept to a hands-on YAML deployment. You can troubleshoot common issues like taints and update strategies. This knowledge is crucial for deploying cluster-level services like log collectors, monitoring agents, and networking components.
Next lesson: Learn about Jobs and CronJobs for running batch workloads to completion. With DaemonSets under your belt, you're ready to tackle ephemeral tasks that need to run once or on a schedule.
Practice recap
Create a DaemonSet that runs busybox:1.28 with the command sleep 3600 on every node. Verify one Pod per node using kubectl get pods -o wide. Then add a nodeSelector to run only on nodes labeled env=production. Clean up with kubectl delete daemonset busybox-per-node.
Common mistakes
- Forgetting to add tolerations for control-plane nodes — DaemonSet Pods won't schedule on master nodes unless you explicitly tolerate the
NoScheduletaint. - Using
replicasin the DaemonSet spec — it's invalid and will cause an error. DaemonSets control replica count automatically. - Expecting DaemonSet Pods to be evenly distributed across nodes with different resources — they run on every node regardless of capacity unless you set resource limits that could prevent scheduling.
- Not setting
updateStrategy: RollingUpdatewithmaxUnavailable: 1— default isOnDelete, which only updates Pods when you delete them manually.
Variations
- Use
nodeSelectorto target a subset of nodes (e.g.,disktype: ssd) instead of all nodes. - Combine DaemonSet with
affinityandtolerationsfor fine-grained placement, such as running on nodes with a specific GPU. - Create multiple DaemonSets with different images (e.g., Fluentd vs. Logstash) on the same nodes by using different label selectors.
Real-world use cases
- Deploying a log collector (e.g., Fluentd) on every node to ship container logs to a central Elasticsearch cluster.
- Running a node-exporter (Prometheus) on each Kubernetes node to collect hardware and OS metrics for monitoring.
- Installing a CNI plugin (e.g., Calico or Flannel) via a DaemonSet to configure networking on each node as the cluster scales.
Key takeaways
- A DaemonSet automatically runs one Pod on every matching node — no manual scaling needed.
- DaemonSets are ideal for node-level infrastructure services like log collection, monitoring, and networking.
- The DaemonSet controller creates Pods on new nodes and deletes them when nodes are removed.
- Use
nodeSelectorandtolerationsto restrict which nodes run the DaemonSet Pod. - Rolling updates in DaemonSets happen node-by-node to maintain availability.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.