🎉 DevOps Interview Prep Bundle is live — 1000+ Q&A across 20 topicsGet it →
All Articles

What is a Kubernetes DaemonSet — Explained Simply

DaemonSets ensure a pod runs on every node. Here's what they are, when you need them, and how they differ from Deployments with practical examples.

DevOpsBoysJun 2, 20263 min read
Share:Tweet

A DaemonSet ensures that one copy of a pod runs on every node in your cluster. As nodes are added, pods are added to them. As nodes are removed, those pods are garbage collected.


The Problem DaemonSets Solve

Some workloads need to run on every single node — not just some nodes, not multiple copies per node, but exactly one per node:

  • Log collectors — Fluentd, Fluent Bit (needs access to all node logs)
  • Monitoring agents — Prometheus Node Exporter (collects node metrics)
  • Network agents — Calico, Cilium, Weave (manage node networking)
  • Storage agents — Ceph, GlusterFS per-node daemons
  • Security agents — Falco, Sysdig (monitor syscalls on each node)

You can't use a regular Deployment for this — a Deployment might put 3 replicas on 1 node and 0 on another.


DaemonSet vs Deployment

Deployment with replicas: 3
Cluster: Node A, Node B, Node C

Possible distribution:
- Node A: 2 pods
- Node B: 1 pod  
- Node C: 0 pods ← missed!

DaemonSet:
- Node A: 1 pod  ✅
- Node B: 1 pod  ✅
- Node C: 1 pod  ✅

DaemonSet Example: Node Exporter

Prometheus Node Exporter needs to run on every node to collect hardware/OS metrics:

yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      hostPID: true        # Access host process namespace
      hostNetwork: true    # Use host network (see host metrics)
      containers:
        - name: node-exporter
          image: prom/node-exporter:v1.7.0
          ports:
            - containerPort: 9100
              hostPort: 9100     # Expose on node's IP:9100
          securityContext:
            runAsNonRoot: true
            runAsUser: 65534
          volumeMounts:
            - name: proc
              mountPath: /host/proc
              readOnly: true
            - name: sys
              mountPath: /host/sys
              readOnly: true
      volumes:
        - name: proc
          hostPath:
            path: /proc
        - name: sys
          hostPath:
            path: /sys
      tolerations:
        - operator: Exists    # Run on ALL nodes including control plane

After applying:

bash
kubectl get pods -n monitoring -o wide
# NAME                  READY   NODE
# node-exporter-abc12   1/1     node-1
# node-exporter-def34   1/1     node-2
# node-exporter-ghi56   1/1     node-3
# One pod per node — exactly what we want

Log Collector DaemonSet (Fluent Bit)

yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluent-bit
  namespace: logging
spec:
  selector:
    matchLabels:
      app: fluent-bit
  template:
    metadata:
      labels:
        app: fluent-bit
    spec:
      containers:
        - name: fluent-bit
          image: fluent/fluent-bit:2.2
          volumeMounts:
            - name: varlog
              mountPath: /var/log          # Read all pod logs
            - name: varlibdockercontainers
              mountPath: /var/lib/docker/containers
              readOnly: true
      volumes:
        - name: varlog
          hostPath:
            path: /var/log
        - name: varlibdockercontainers
          hostPath:
            path: /var/lib/docker/containers

Tolerations — Running on Control Plane Nodes

By default, DaemonSets respect taints. Control plane nodes have a NoSchedule taint. If you want your DaemonSet on ALL nodes including control plane:

yaml
tolerations:
  - key: node-role.kubernetes.io/control-plane
    operator: Exists
    effect: NoSchedule
  - key: node-role.kubernetes.io/master
    operator: Exists
    effect: NoSchedule

Node Selector — Run on Specific Nodes Only

Sometimes you only want the DaemonSet on certain nodes (e.g., only GPU nodes for a GPU monitoring agent):

yaml
spec:
  template:
    spec:
      nodeSelector:
        accelerator: nvidia-tesla-v100

Or use node affinity for more complex selection:

yaml
affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
        - matchExpressions:
            - key: kubernetes.io/os
              operator: In
              values: [linux]

Managing DaemonSet Updates

bash
# Check DaemonSet status
kubectl rollout status daemonset/node-exporter -n monitoring
 
# Update to new image
kubectl set image daemonset/node-exporter \
  node-exporter=prom/node-exporter:v1.8.0 \
  -n monitoring
 
# Check rollout (updates one node at a time)
kubectl rollout status daemonset/node-exporter -n monitoring
 
# Rollback if needed
kubectl rollout undo daemonset/node-exporter -n monitoring

DaemonSets update using RollingUpdate strategy by default — updates one node at a time to avoid losing all monitoring simultaneously.


Common Use Cases Summary

Use CaseExample
Log collectionFluent Bit, Fluentd
Metrics collectionPrometheus Node Exporter
Network pluginCalico, Cilium, Weave
Storage daemonGlusterFS, Ceph OSD
Security monitoringFalco
Distributed storageOpenEBS

When you need something running on every node — monitoring, logging, networking — DaemonSet is the right tool. For everything else, use Deployment.

Practice DaemonSets and understand Kubernetes workloads with hands-on labs at KodeKloud.

🔧

Today I Fixed

Short real fixes from production — posted daily

Browse fixes
Newsletter

Stay ahead of the curve

Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.

Related Articles

Comments