DaemonSet
A Kubernetes controller that ensures exactly one copy of a pod runs on every node in the cluster (or a filtered subset). When new nodes join, the DaemonSet automatically schedules a pod on them. When nodes leave, those pods are garbage collected. Used for infrastructure agents that must run everywhere — log collectors, monitoring exporters, network plugins, and security scanners.
DaemonSet — One Agent Per Node, Always
What is a DaemonSet in Simple Terms?
A DaemonSet is a standing order to the scheduler: "This pod must always run on every node — one copy per node, no more, no less." Not one total replica. One per node. When a new node joins the cluster, the DaemonSet pod is automatically placed on it. When a node is removed, the pod is cleaned up automatically.
DaemonSet vs Deployment — The Key Difference
+------------------------------------------+ +------------------------------------------+| Deployment | | DaemonSet || | | || You control replica count | | Cluster controls replica count || replicas: 3 (on any 3 nodes) | | 1 pod per node (on ALL nodes) || | | || Use for: application workloads | | Use for: infrastructure agents |+------------------------------------------+ +------------------------------------------+One Pod Per Node — How It Looks
+---------------+ +---------------+ +---------------+ +---------------+| mumbai-node-1| | mumbai-node-2| | mumbai-node-3| | mumbai-node-4|| | | | | | | || [fluentd-0] | | [fluentd-1] | | [fluentd-2] | | [fluentd-3] |+---------------+ +---------------+ +---------------+ +---------------+ ^ ^ | | New node added to cluster -----> DaemonSet auto-schedules pod hereWhen to Use a DaemonSet
Use DaemonSet for infrastructure agents:
- Log collection — Fluentd, Filebeat, Promtail (must read log files from every node's disk)
- Metrics scraping — Node Exporter (must collect CPU/memory/disk from every node)
- Network plugins — Calico, Cilium CNI agents (must configure networking on every node)
- Security agents — Falco, CrowdStrike (must inspect every node's syscalls and processes)
- Storage drivers — CSI node drivers that attach and mount volumes
Do NOT use DaemonSet for:
- Application workloads (use Deployment)
- Batch processing (use Jobs or CronJobs)
- Anything where you want explicit control over replica count
A Real DaemonSet — Node Exporter for Prometheus
# node-exporter-daemonset.yaml# Runs Prometheus Node Exporter on every node in mumbai-prod-clusterapiVersion: apps/v1kind: DaemonSetmetadata: name: node-exporter namespace: monitoringspec: selector: matchLabels: app: node-exporter template: metadata: labels: app: node-exporter spec: hostNetwork: true # Uses the node's network namespace directly hostPID: true # Sees all processes on the node (required for metrics) tolerations: - operator: Exists # Tolerate ALL taints — run on control-plane nodes too effect: NoSchedule containers: - name: node-exporter image: prom/node-exporter:v1.7.0 ports: - containerPort: 9100 hostPort: 9100 # Binds directly to the node's port 9100 args: - '--path.procfs=/host/proc' - '--path.sysfs=/host/sys' volumeMounts: - name: proc mountPath: /host/proc readOnly: true - name: sys mountPath: /host/sys readOnly: true volumes: - name: proc hostPath: path: /proc # Mounts the node's /proc filesystem - name: sys hostPath: path: /sys # Mounts the node's /sys filesystemTargeting Specific Nodes — Not Always Every Node
You do not always want a DaemonSet on every node. A GPU monitoring agent should only run on GPU nodes:
# nodeSelector — simple label matchspec: template: spec: nodeSelector: accelerator: nvidia-gpu # Only schedule on nodes labelled as GPU nodesFor more complex targeting, use nodeAffinity:
# nodeAffinity — skip control-plane, run only on worker nodesaffinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: node-role operator: In values: - worker # Excludes control-plane nodes explicitlyTolerations — Getting onto Tainted Nodes
Control-plane nodes carry a default taint: node-role.kubernetes.io/control-plane:NoSchedule. Without a matching toleration, your DaemonSet will skip them. The operator: Exists toleration bypasses ALL taints — use it for critical agents that must run everywhere like Falco or CNI plugins.
tolerations: - key: node-role.kubernetes.io/control-plane operator: Exists effect: NoSchedule # Specific — only bypass this one taintKey DaemonSet Commands
| Task | Command |
|---|---|
| List DaemonSet status | kubectl get ds -n monitoring |
| See which nodes have the pod | kubectl get pods -o wide -n monitoring |
| Check rollout status | kubectl rollout status ds/node-exporter -n monitoring |
| Force restart all pods | kubectl rollout restart ds/node-exporter -n monitoring |
| Describe DaemonSet events | kubectl describe ds/node-exporter -n monitoring |
| Check pod count vs node count | kubectl get ds node-exporter -n monitoring |
# Verify a DaemonSet pod is running on every nodekubectl get pods -n monitoring -l app=node-exporter -o wide # Output should show one pod per node:# NAME READY NODE# node-exporter-4xk2p 1/1 mumbai-node-1# node-exporter-7hq9r 1/1 mumbai-node-2# node-exporter-m2pzn 1/1 mumbai-node-3SecuritySetting
hostNetwork: trueandhostPID: truegives the container full visibility into the host's network stack and every process running on the node. Only use these flags for trusted infrastructure agents like Node Exporter or Falco — never for application workloads. In Hotstar or PhonePe production clusters, DaemonSet pods with host access should be reviewed as part of every security audit.
RememberDaemonSet pod count equals node count. If your cluster has 12 nodes and your DaemonSet shows 10 pods, two nodes have issues — either they are tainted without a matching toleration, or the pods are failing on those nodes. Use
kubectl get pods -o wideto identify which nodes are missing coverage.
Common MistakeUsing a Deployment with
replicasmatching your node count as a substitute for a DaemonSet. If a node is added later, the Deployment will not automatically place a pod on it — you are back to manual scaling. Always use a DaemonSet for anything that must run on every node.
TipIn Zerodha or Swiggy-scale clusters, DaemonSets for log collection (Fluentd/Promtail) are often the highest-volume pods in the cluster. Set proper
resources.requestsandresources.limitson them — an unthrottled Fluentd pod can consume enough CPU to starve application pods on the same node during log bursts.
Frequently Asked Questions
Why not just use a Deployment with enough replicas to cover every node?
A Deployment's replica count is a static number you have to update manually as nodes are added or removed, and the scheduler doesn't guarantee one pod per node — you could end up with two pods on one node and zero on another. A DaemonSet ties pod count directly to cluster topology: it watches the node list and schedules exactly one pod per matching node automatically, which is what you need for per-node agents like Fluentd or Node Exporter.
What's a common mistake teams make when running DaemonSets?
Not setting resource requests/limits on the DaemonSet pod. Since it runs on every node including ones running critical workloads, an unbounded log collector or scanner can starve application pods for CPU or memory during a spike. Also worth watching: DaemonSet pods bypass normal scheduler resource-based placement by default (they tolerate most taints), so they'll land on nodes you might have wanted kept clear, like dedicated GPU nodes, unless you add explicit tolerations/node selectors.