Home DevOps Kubernetes DaemonSets
Intermediate 8 min · July 12, 2026

Kubernetes DaemonSets

Learn Kubernetes DaemonSets with plain-English explanations and real examples..

N
Naren Founder & Principal Engineer

20+ years shipping production infrastructure and CI/CD at scale. Notes here come from systems that actually shipped.

Follow
Verified
production tested
July 12, 2026
last updated
2,073
articles · all by Naren
Before you start⏱ 25 min
  • Kubernetes cluster (v1.20+), kubectl installed and configured, basic understanding of Pods and Deployments, familiarity with YAML manifests, access to create DaemonSets in a namespace.
✦ Definition~90s read
What is Kubernetes DaemonSets?

A DaemonSet ensures that all (or some) Nodes run a copy of a Pod. As nodes are added to the cluster, Pods are added to them. As nodes are removed, those Pods are garbage collected. Deleting a DaemonSet will clean up the Pods it created. Use DaemonSets for cluster-wide services like log collectors, monitoring agents, and kube-proxy.

Think of Kubernetes DaemonSets like a tool in your DevOps toolkit — once you understand what it does and when to reach for it, managing Kubernetes clusters becomes second nature.
Plain-English First

Think of Kubernetes DaemonSets like a tool in your DevOps toolkit — once you understand what it does and when to reach for it, managing Kubernetes clusters becomes second nature.

⚙ Browser compatibility
Latest versions — ✓ supported
ChromeFirefoxSafariEdge

You've just deployed a new logging agent across your 50-node Kubernetes cluster. Three hours later, you're paged because half the nodes have no logs. The rollout succeeded, but the DaemonSet didn't schedule on nodes with taints you forgot existed. This is the reality of DaemonSets: they look simple, but production will punish you for assumptions. DaemonSets are Kubernetes' answer to running a pod on every node — think kube-proxy, Calico, or Datadog agents. They're not for stateless apps; they're for infrastructure that must be everywhere. But 'everywhere' is a loaded word when you consider node taints, resource constraints, and rolling updates. In this guide, we'll cover DaemonSet mechanics, scheduling nuances, production patterns, and failure modes you'll encounter at scale.

What is a DaemonSet?

A DaemonSet is a Kubernetes workload resource that ensures a copy of a pod runs on every node in the cluster (or a subset, if node selectors are used). When nodes are added or removed, the DaemonSet controller automatically creates or deletes pods accordingly. This makes DaemonSets ideal for cluster-wide services that need to be present on each node, such as log collectors (Fluentd, Filebeat), monitoring agents (Prometheus Node Exporter, Datadog Agent), storage daemons (GlusterFS, Ceph), and network plugins (Calico, Flannel). Unlike Deployments, which aim for a desired number of replicas spread across nodes, DaemonSets guarantee one pod per node by default. This fundamental difference means DaemonSets are not scaled horizontally; they scale with the cluster size. The DaemonSet controller watches the Kubernetes API for node changes and ensures the desired state is maintained. It respects node taints and tolerations, node selectors, and affinity rules, giving you fine-grained control over which nodes run the pod.

daemonset-basic.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      containers:
      - name: fluentd-elasticsearch
        image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: dockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: dockercontainers
        hostPath:
          path: /var/lib/docker/containers
Output
daemonset.apps/fluentd-elasticsearch created
🔥DaemonSets vs Deployments
DaemonSets guarantee one pod per node; Deployments guarantee a desired number of replicas. Use DaemonSets for node-level infrastructure, Deployments for stateless applications.
📊 Production Insight
Always set resource requests and limits on DaemonSet pods. A single runaway logging agent can starve your application pods on that node.
🎯 Key Takeaway
DaemonSets run one pod per node, ideal for cluster-wide services like logging and monitoring.

DaemonSet Scheduling: How Pods Land on Nodes

The DaemonSet controller uses the Kubernetes scheduler to place pods on nodes, but with a twist: it bypasses the default scheduler for initial placement. Instead, the controller directly creates pods on each node that matches the DaemonSet's node selector and tolerations. This means DaemonSet pods are scheduled even if the cluster has a custom scheduler or if the default scheduler is misconfigured. The controller watches for new nodes and creates pods immediately, without going through the scheduling queue. However, if a node becomes unschedulable (e.g., due to taints), the DaemonSet will not create a pod there unless the pod template includes matching tolerations. This is a common pitfall: forgetting to add tolerations for master nodes or nodes with custom taints. Additionally, DaemonSets respect node affinity and anti-affinity rules, but anti-affinity is rarely needed since there's only one pod per node by design. The scheduling behavior can be further controlled using the .spec.template.spec.nodeSelector field or by setting .spec.template.spec.affinity.nodeAffinity. For advanced use cases, you can use .spec.updateStrategy.rollingUpdate.maxSurge to control how many extra pods are created during rolling updates.

daemonset-node-selector.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      nodeSelector:
        kubernetes.io/os: linux
      tolerations:
      - operator: Exists
      containers:
      - name: node-exporter
        image: prom/node-exporter:v1.3.1
        ports:
        - containerPort: 9100
          hostPort: 9100
        resources:
          requests:
            cpu: 100m
            memory: 50Mi
          limits:
            cpu: 200m
            memory: 100Mi
Output
daemonset.apps/node-exporter created
# Pods will only run on Linux nodes
⚠ Taints and Tolerations Gotcha
If your cluster has nodes with custom taints (e.g., for GPU or specialized hardware), your DaemonSet pods won't schedule there unless you add matching tolerations. Always audit your node taints before deploying a DaemonSet.
📊 Production Insight
In a multi-tenant cluster, a DaemonSet without tolerations can fail to run on critical nodes, causing gaps in monitoring. Always add tolerations for known taints.
🎯 Key Takeaway
DaemonSet scheduling is controller-driven, bypassing the default scheduler for initial placement.
kubernetes-daemonsets THECODEFORGE.IO DaemonSet Pod Scheduling Flow How DaemonSets ensure one pod per node Create DaemonSet Define pod template and node selector DaemonSet Controller Watches Nodes Listens for node add/remove events Node Added or Existing Node Controller detects eligible node Check Node Selector Match labels; skip if not matching Create Pod on Node Pod scheduled directly without scheduler Pod Runs Until Node Removed Pod deleted when node is removed ⚠ Node selector mismatch causes pod omission Ensure node labels match DaemonSet selector exactly THECODEFORGE.IO
thecodeforge.io
Kubernetes Daemonsets

Rolling Updates and Rollbacks

DaemonSets support rolling updates to update the pod template (e.g., image version, resource limits) without downtime. The update strategy is configured via .spec.updateStrategy.type, which can be RollingUpdate (default) or OnDelete. With RollingUpdate, the DaemonSet controller updates pods one by one, respecting maxUnavailable and maxSurge parameters. maxUnavailable (default 1) specifies how many pods can be unavailable during the update. maxSurge (default 0) specifies how many extra pods can be created above the desired per-node count. Setting maxSurge to 1 allows the controller to create a new pod on a node before deleting the old one, reducing downtime for critical daemons. However, this consumes extra resources. The OnDelete strategy only updates pods when they are manually deleted, giving you full control. Rollbacks are performed by reverting the DaemonSet's pod template to a previous version. Kubernetes does not automatically track revisions for DaemonSets like it does for Deployments, so you must manually apply an older YAML or use kubectl rollout undo. To enable revision history, you can annotate the DaemonSet, but it's not built-in. For production, consider using a GitOps workflow to manage DaemonSet versions.

rolling-update.shBASH
1
2
3
4
5
6
7
8
# Update the DaemonSet image
kubectl set image daemonset/fluentd-elasticsearch fluentd-elasticsearch=quay.io/fluentd_elasticsearch/fluentd:v2.5.3 -n kube-system

# Check rollout status
kubectl rollout status daemonset/fluentd-elasticsearch -n kube-system

# Rollback if needed
kubectl rollout undo daemonset/fluentd-elasticsearch -n kube-system
Output
daemonset.apps/fluentd-elasticsearch image updated
Waiting for daemon set "fluentd-elasticsearch" rollout to finish: 0 of 5 updated nodes...
daemon set "fluentd-elasticsearch" successfully rolled out
💡Use maxSurge for Critical Daemons
For daemons that must always be running (e.g., network plugins), set maxSurge: 1 to ensure a new pod starts before the old one is terminated. This prevents connectivity gaps.
📊 Production Insight
We once had a DaemonSet update that took down all Calico pods simultaneously because maxUnavailable was set too high. The entire cluster lost network connectivity. Always test updates on a non-production cluster first.
🎯 Key Takeaway
Rolling updates allow zero-downtime updates of DaemonSet pods, but require careful tuning of maxUnavailable and maxSurge.

Resource Management and Node Pressure

DaemonSet pods share node resources with other workloads. If a DaemonSet pod consumes too much CPU or memory, it can cause resource starvation for application pods on that node. This is especially dangerous for daemons like log collectors or monitoring agents that might have unbounded resource usage. Always set resource requests and limits on DaemonSet containers. Requests guarantee the pod gets that amount of resources; limits prevent it from consuming more. For example, a Fluentd DaemonSet might request 100m CPU and 200Mi memory, with limits of 200m CPU and 400Mi memory. If the node runs out of resources, the kubelet may evict pods, starting with those exceeding their limits. DaemonSet pods are typically not critical enough to warrant priority classes, but you can set them if needed. Additionally, consider using resourceQuota at the namespace level to cap total DaemonSet resource usage. Another common issue is disk pressure: DaemonSets that write to hostPath volumes (e.g., log collectors) can fill up the node's disk. Monitor disk usage and set log rotation policies. Finally, DaemonSets with high network I/O (e.g., network plugins) can saturate the node's bandwidth. Use resource limits and quality of service (QoS) classes to mitigate.

daemonset-resources.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: filebeat
  namespace: logging
spec:
  selector:
    matchLabels:
      app: filebeat
  template:
    metadata:
      labels:
        app: filebeat
    spec:
      containers:
      - name: filebeat
        image: docker.elastic.co/beats/filebeat:7.17.0
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
          limits:
            cpu: 200m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: data
          mountPath: /usr/share/filebeat/data
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: data
        hostPath:
          path: /var/lib/filebeat-data
Output
daemonset.apps/filebeat created
⚠ Unbounded Resource Usage
A DaemonSet without resource limits can consume all node resources, causing other pods to be evicted. Always set both requests and limits.
📊 Production Insight
We saw a node's disk fill up because a Fluentd DaemonSet was writing logs to a hostPath without rotation. The node became NotReady, and all pods were evicted. Implement log rotation and disk monitoring.
🎯 Key Takeaway
Set resource requests and limits on DaemonSet pods to prevent node resource starvation.

DaemonSets and Cluster Autoscaling

Cluster autoscalers (e.g., Karpenter, Cluster Autoscaler) add or remove nodes based on resource demands. DaemonSets interact with autoscaling in two ways: they consume resources on every node, and they must be considered when calculating node capacity. When a new node is added, the DaemonSet controller creates pods on it, consuming resources that could otherwise be used by pending pods. This can cause the autoscaler to add more nodes than necessary if DaemonSet resource requests are high. To avoid this, you can set .spec.template.spec.priorityClassName to a lower priority for DaemonSet pods, allowing application pods to preempt them. However, this is risky for critical daemons. Alternatively, configure the autoscaler to ignore DaemonSet resource consumption by setting --skip-nodes-with-system-pods=false (Cluster Autoscaler) or using karpenter.k8s.aws/do-not-disrupt annotations. Another approach is to use node affinity to exclude DaemonSets from certain node pools, but this defeats the purpose. Best practice: keep DaemonSet resource requests minimal and monitor their impact on autoscaling decisions. For example, a monitoring DaemonSet requesting 100m CPU per node on a 100-node cluster consumes 10 CPU cores total—non-trivial.

daemonset-priority.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: daemonset-priority
value: 1000
globalDefault: false
description: "Priority for DaemonSet pods"
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: low-priority-daemon
spec:
  template:
    spec:
      priorityClassName: daemonset-priority
      containers:
      - name: main
        image: busybox
        command: ["sleep", "infinity"]
        resources:
          requests:
            cpu: 10m
            memory: 10Mi
Output
priorityclass.scheduling.k8s.io/daemonset-priority created
daemonset.apps/low-priority-daemon created
🔥Autoscaler Considerations
DaemonSet resource requests count toward node capacity. If they're too high, the autoscaler may add unnecessary nodes. Keep requests minimal or use priority classes.
📊 Production Insight
We had a cluster where a DaemonSet requested 500m CPU per node. On a 50-node cluster, that's 25 CPU cores reserved. The autoscaler kept adding nodes because it thought there was no capacity, even though application pods were small. We reduced the request to 50m and the problem disappeared.
🎯 Key Takeaway
DaemonSet resource consumption affects cluster autoscaling decisions; keep requests low to avoid over-provisioning.

DaemonSets with Host Networking and Ports

DaemonSets often need to access host-level resources, such as network interfaces or ports. You can enable host networking by setting hostNetwork: true in the pod spec, which makes the pod use the node's network stack directly. This is common for network plugins (e.g., Calico, Flannel) and node monitoring tools. When using host networking, the pod can bind to host ports, but you must ensure port conflicts don't occur. Use hostPort to expose a container port on the host IP. For example, a Node Exporter DaemonSet might use hostPort: 9100 to make metrics available on the node's IP. However, hostPort is not recommended for production because it can cause port conflicts if multiple DaemonSets try to use the same port. Instead, use a hostNetwork with a unique port, or use a NodePort service to expose the daemon. Another consideration: when using host networking, the pod's network performance is identical to the host's, which is beneficial for latency-sensitive daemons. However, it also means the pod is not isolated from the host network, which is a security concern. For security, avoid host networking unless necessary.

daemonset-hostnetwork.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      hostNetwork: true
      hostPID: true
      containers:
      - name: node-exporter
        image: prom/node-exporter:v1.3.1
        args:
        - --path.procfs=/host/proc
        - --path.sysfs=/host/sys
        ports:
        - containerPort: 9100
          hostPort: 9100
        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
Output
daemonset.apps/node-exporter created
# Pod uses host network and can access node metrics
⚠ Host Network Security
Using hostNetwork gives the pod full access to the node's network stack. Only use it for trusted daemons. Consider network policies to restrict traffic.
📊 Production Insight
A misconfigured DaemonSet with hostNetwork accidentally bound to port 80, conflicting with the node's web server. We had to kill the pod and add port validation. Always check for port conflicts before deploying.
🎯 Key Takeaway
Host networking allows DaemonSets to access node-level network resources but reduces isolation.

DaemonSet and Persistent Volumes

DaemonSets can use persistent volumes, but with caveats. Since each pod runs on a different node, you typically need a volume that is node-local (e.g., hostPath) or a shared network filesystem (e.g., NFS, EFS). hostPath volumes are the most common, as they allow the pod to access the node's filesystem. However, hostPath volumes are not portable and can cause issues if the pod is rescheduled to a different node (which shouldn't happen with DaemonSets, but can during updates). For stateful daemons that need persistent storage across restarts, consider using a local persistent volume with node affinity, or a network volume like NFS. Be aware that network volumes introduce latency and potential single points of failure. Another option is to use emptyDir volumes for temporary data, but data is lost on pod restart. For log collectors, hostPath is standard. For databases running as DaemonSets (rare), you'd need a distributed storage solution. In production, avoid using DaemonSets for stateful workloads that require durable storage; use StatefulSets instead.

daemonset-hostpath.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: log-collector
  namespace: logging
spec:
  selector:
    matchLabels:
      app: log-collector
  template:
    metadata:
      labels:
        app: log-collector
    spec:
      containers:
      - name: log-collector
        image: busybox
        command: ["sh", "-c", "tail -f /var/log/syslog"]
        volumeMounts:
        - name: varlog
          mountPath: /var/log
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
          type: Directory
Output
daemonset.apps/log-collector created
🔥hostPath vs PersistentVolume
hostPath is simple but ties the pod to a specific node's filesystem. For portable storage, use a network volume like NFS, but expect performance trade-offs.
📊 Production Insight
We used hostPath for a log collector, but the node's /var/log was on a separate partition that filled up. The DaemonSet pod couldn't write, and we lost logs. Monitor disk usage on hostPath mounts.
🎯 Key Takeaway
DaemonSets commonly use hostPath volumes for node-local access; avoid persistent volumes for stateful data.
kubernetes-daemonsets THECODEFORGE.IO DaemonSet Component Stack Layered view of DaemonSet internals User API kubectl apply | YAML manifest Control Plane DaemonSet Controller | API Server | etcd Scheduling Logic Node Watcher | Node Selector Matcher | Pod Creator Node Agent kubelet | Container Runtime | Pod Lifecycle Daemon Pods Log Collector | Monitoring Agent | Network Plugin THECODEFORGE.IO
thecodeforge.io
Kubernetes Daemonsets

DaemonSet Health Checks and Readiness Probes

DaemonSet pods should have liveness and readiness probes to ensure they are healthy and ready to serve traffic. Liveness probes restart the pod if it becomes unhealthy; readiness probes control whether the pod receives traffic from services. For DaemonSets that expose a service (e.g., monitoring agents), readiness probes are crucial to avoid routing traffic to a broken pod. However, DaemonSets often don't have a service fronting them; they are accessed via hostIP or DNS. In that case, readiness probes are less critical but still useful for rolling updates. A common pattern is to use an HTTP probe on a health endpoint, or a TCP probe on a known port. For daemons that take time to initialize (e.g., loading rules), set initialDelaySeconds appropriately. Avoid using exec probes that run heavy commands, as they can consume resources. Also, consider using startupProbe for slow-starting containers to prevent premature restarts. In production, always define at least a liveness probe to detect deadlocks or OOM kills.

daemonset-probes.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
  namespace: logging
spec:
  selector:
    matchLabels:
      app: fluentd
  template:
    metadata:
      labels:
        app: fluentd
    spec:
      containers:
      - name: fluentd
        image: fluent/fluentd:v1.14-1
        ports:
        - containerPort: 24224
        livenessProbe:
          tcpSocket:
            port: 24224
          initialDelaySeconds: 10
          periodSeconds: 10
        readinessProbe:
          tcpSocket:
            port: 24224
          initialDelaySeconds: 5
          periodSeconds: 10
Output
daemonset.apps/fluentd created
💡Startup Probe for Slow Daemons
If your daemon takes a long time to load configuration (e.g., 30+ seconds), add a startupProbe with a higher failureThreshold to prevent the liveness probe from killing it prematurely.
📊 Production Insight
We had a Fluentd DaemonSet that would OOM occasionally. Without a liveness probe, it stayed in a crash loop, but the pod never restarted because the container exited. The liveness probe caught it and restarted it, but we also had to increase memory limits.
🎯 Key Takeaway
Liveness and readiness probes ensure DaemonSet pods are healthy and ready, critical for rolling updates and service reliability.

DaemonSet Security: ServiceAccounts and RBAC

DaemonSet pods often need to interact with the Kubernetes API to discover nodes, watch resources, or report metrics. This requires a ServiceAccount with appropriate RBAC permissions. For example, a network plugin DaemonSet might need permissions to create routes or modify nodes. Always follow the principle of least privilege: grant only the permissions the daemon needs. Create a dedicated ServiceAccount for the DaemonSet and bind it to a Role or ClusterRole. Avoid using the default ServiceAccount, which may have excessive permissions. Also, consider using Pod Security Standards (PSS) or OPA/Gatekeeper to enforce security policies on DaemonSet pods. For hostNetwork DaemonSets, restrict capabilities and enable seccomp profiles. Another security concern: DaemonSet pods running as privileged containers can escape to the host. If your daemon requires privileged mode (e.g., for network configuration), ensure it's absolutely necessary and audit the image. In production, scan DaemonSet images for vulnerabilities and use image signing.

daemonset-rbac.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
apiVersion: v1
kind: ServiceAccount
metadata:
  name: fluentd
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: fluentd
rules:
- apiGroups: [""]
  resources: ["pods", "namespaces"]
  verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: fluentd
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: fluentd
subjects:
- kind: ServiceAccount
  name: fluentd
  namespace: kube-system
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
  namespace: kube-system
spec:
  template:
    spec:
      serviceAccountName: fluentd
      containers:
      - name: fluentd
        image: fluent/fluentd:v1.14-1
Output
serviceaccount/fluentd created
clusterrole.rbac.authorization.k8s.io/fluentd created
clusterrolebinding.rbac.authorization.k8s.io/fluentd created
daemonset.apps/fluentd created
⚠ Least Privilege for DaemonSets
Grant only the minimum RBAC permissions required. A DaemonSet with cluster-admin can be a security disaster if compromised.
📊 Production Insight
A compromised DaemonSet with cluster-admin privileges allowed an attacker to exfiltrate secrets from all namespaces. We now enforce least privilege and audit RBAC bindings regularly.
🎯 Key Takeaway
Use dedicated ServiceAccounts with minimal RBAC permissions for DaemonSet pods to reduce security risks.

DaemonSet Monitoring and Observability

Monitoring DaemonSets is critical because they run on every node and can impact cluster health. Key metrics to track: number of pods scheduled vs. desired (should be equal), pod restart count, resource usage (CPU, memory, disk), and rollout status. Use Prometheus to scrape metrics from DaemonSet pods, or use the Kubernetes API to monitor DaemonSet status. Set up alerts for when a DaemonSet pod is not running on a node (e.g., due to taints or resource constraints). Also monitor for crash loops: a DaemonSet in a crash loop can cause cascading failures. For log collectors, ensure logs are being shipped correctly; missing logs from a node indicate a problem. Use tools like kubectl describe daemonset to see events, or use a dashboard like Grafana with the Kubernetes mixin. In production, implement a health check that verifies DaemonSet coverage: every node should have a running pod. This can be done with a custom script or using the kube-state-metrics exporter.

monitor-daemonset.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Check DaemonSet status
kubectl get daemonsets -A

# Get detailed status
kubectl describe daemonset fluentd -n kube-system

# Check pod distribution
kubectl get pods -n kube-system -l name=fluentd -o wide

# Alert if number of pods != number of ready nodes
NODES=$(kubectl get nodes --no-headers | wc -l)
PODS=$(kubectl get pods -n kube-system -l name=fluentd --field-selector=status.phase=Running --no-headers | wc -l)
if [ $PODS -ne $NODES ]; then
  echo "DaemonSet not covering all nodes: $PODS pods on $NODES nodes"
fi
Output
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
fluentd 5 5 5 5 5 <none> 10m
# Detailed events show scheduling issues if any
🔥DaemonSet Coverage Alert
Set up an alert that fires when the number of ready DaemonSet pods is less than the number of nodes. This catches scheduling failures early.
📊 Production Insight
We had a silent failure where a DaemonSet pod was not scheduled on a new node because the node had a taint we forgot to add tolerations for. The monitoring gap lasted 3 days until a user complained. Now we have automated coverage checks.
🎯 Key Takeaway
Monitor DaemonSet pod coverage and resource usage to detect issues before they affect the cluster.

Common DaemonSet Pitfalls and How to Avoid Them

  1. Forgetting tolerations: DaemonSet pods won't schedule on tainted nodes. Always add tolerations for known taints (e.g., master node taint). 2. Resource limits too high: DaemonSet resource requests can consume significant cluster capacity. Keep them minimal. 3. Host port conflicts: Multiple DaemonSets using the same hostPort will fail. Use unique ports or avoid hostPort. 4. Rolling update misconfiguration: Setting maxUnavailable too high can cause mass pod deletion. Use maxSurge for critical daemons. 5. Ignoring node selectors: If you use nodeSelector, ensure it matches all intended nodes. Otherwise, some nodes will be missed. 6. Not setting terminationGracePeriodSeconds: DaemonSet pods may need time to flush buffers before shutdown. Set an appropriate grace period. 7. Using DaemonSets for stateful workloads: DaemonSets are not designed for stateful applications; use StatefulSets. 8. Lack of monitoring: Without coverage alerts, you may not notice missing pods. 9. Privileged containers without need: Avoid privileged mode unless absolutely necessary. 10. Not testing updates: Always test DaemonSet updates in a staging environment first.
daemonset-pitfalls.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# Example of a DaemonSet with common fixes
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: good-daemon
spec:
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  template:
    spec:
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      terminationGracePeriodSeconds: 60
      containers:
      - name: main
        image: busybox
        command: ["sleep", "infinity"]
        resources:
          requests:
            cpu: 10m
            memory: 10Mi
          limits:
            cpu: 50m
            memory: 50Mi
        livenessProbe:
          exec:
            command: ["true"]
          initialDelaySeconds: 5
          periodSeconds: 10
Output
daemonset.apps/good-daemon created
⚠ Top Pitfall: Tolerations
The most common DaemonSet failure is missing tolerations for node taints. Always check your cluster's node taints before deploying.
📊 Production Insight
We once deployed a DaemonSet without tolerations for the master taint. The master nodes didn't run the daemon, causing a gap in monitoring. We now have a pre-deployment checklist that includes verifying taints.
🎯 Key Takeaway
Avoid common pitfalls by always adding tolerations, setting resource limits, and testing updates.
DaemonSet vs Deployment Key differences in pod placement and use cases DaemonSet Deployment Pod per Node Exactly one per eligible node Replicas distributed across nodes Scheduling By DaemonSet controller, not scheduler By Kubernetes scheduler Node Selector Required; controls which nodes get pods Optional; used for affinity/anti-affinit Use Case Node-level agents (logging, monitoring) Stateless applications (web servers, API Rolling Update Supported with maxSurge/maxUnavailable Supported with similar parameters THECODEFORGE.IO
thecodeforge.io
Kubernetes Daemonsets

DaemonSet Alternatives and When Not to Use Them

DaemonSets are not always the right choice. For workloads that don't need to run on every node, use Deployments or StatefulSets. For example, a web server should be a Deployment with replicas spread across nodes. If you need to run a task on each node once (e.g., node initialization), consider a Job or CronJob. For workloads that require ordered deployment and stable network identities, use StatefulSets. Another alternative is to use node affinity with a Deployment to ensure pods are scheduled on specific nodes, but this is less reliable than DaemonSets. For cluster-wide services that can tolerate missing a node (e.g., caching), a Deployment with anti-affinity might suffice. Also, consider using Kuberenetes Operators that manage node-level agents. In production, evaluate whether you truly need a pod on every node. If the service can function with fewer replicas, a Deployment is more flexible and easier to manage. DaemonSets add operational overhead: they consume resources on every node, and updates affect the entire cluster. Use them only for infrastructure that must be omnipresent.

deployment-alternative.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# Alternative: Deployment with node anti-affinity
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - my-app
            topologyKey: kubernetes.io/hostname
      containers:
      - name: app
        image: nginx
Output
deployment.apps/my-app created
🔥When to Avoid DaemonSets
If your workload doesn't need to run on every node, use a Deployment. DaemonSets are for node-level infrastructure only.
📊 Production Insight
We once used a DaemonSet for a caching sidecar that only needed to run on a subset of nodes. It wasted resources on nodes that didn't need it. We switched to a Deployment with nodeSelector and saved 30% cluster capacity.
🎯 Key Takeaway
Use DaemonSets only for workloads that must run on every node; for others, prefer Deployments or StatefulSets.
⚙ Quick Reference
12 commands from this guide
FileCommand / CodePurpose
daemonset-basic.yamlapiVersion: apps/v1What is a DaemonSet?
daemonset-node-selector.yamlapiVersion: apps/v1DaemonSet Scheduling
rolling-update.shkubectl set image daemonset/fluentd-elasticsearch fluentd-elasticsearch=quay.io/...Rolling Updates and Rollbacks
daemonset-resources.yamlapiVersion: apps/v1Resource Management and Node Pressure
daemonset-priority.yamlapiVersion: scheduling.k8s.io/v1DaemonSets and Cluster Autoscaling
daemonset-hostnetwork.yamlapiVersion: apps/v1DaemonSets with Host Networking and Ports
daemonset-hostpath.yamlapiVersion: apps/v1DaemonSet and Persistent Volumes
daemonset-probes.yamlapiVersion: apps/v1DaemonSet Health Checks and Readiness Probes
daemonset-rbac.yamlapiVersion: v1DaemonSet Security
monitor-daemonset.shkubectl get daemonsets -ADaemonSet Monitoring and Observability
daemonset-pitfalls.yamlapiVersion: apps/v1Common DaemonSet Pitfalls and How to Avoid Them
deployment-alternative.yamlapiVersion: apps/v1DaemonSet Alternatives and When Not to Use Them

Key takeaways

1
DaemonSets run one pod per node
Use them for cluster-wide infrastructure like log collectors, monitoring agents, and network plugins.
2
Scheduling respects taints and tolerations
Always add tolerations for node taints to ensure full coverage; missing tolerations is the most common failure.
3
Rolling updates require careful tuning
Set maxSurge and maxUnavailable to balance speed and safety; test updates in staging.
4
Resource management is critical
Set requests and limits to prevent node starvation; monitor DaemonSet resource usage and coverage.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01JUNIOR
What is the difference between a DaemonSet and a Deployment?
Q02JUNIOR
How do I update a DaemonSet without downtime?
Q03JUNIOR
Why is my DaemonSet pod not running on a node?
Q01 of 03JUNIOR

What is the difference between a DaemonSet and a Deployment?

ANSWER
A DaemonSet ensures one pod per node, while a Deployment ensures a desired number of replicas across the cluster. Use DaemonSets for node-level services (e.g., logging, monitoring) and Deployments for
FAQ · 6 QUESTIONS

Frequently Asked Questions

01
What is the difference between a DaemonSet and a Deployment?
02
How do I update a DaemonSet without downtime?
03
Why is my DaemonSet pod not running on a node?
04
Can I run multiple DaemonSets on the same node?
05
How do I roll back a DaemonSet update?
06
Should I use hostNetwork for my DaemonSet?
N
Naren Founder & Principal Engineer

20+ years shipping production infrastructure and CI/CD at scale. Notes here come from systems that actually shipped.

Follow
Verified
production tested
July 12, 2026
last updated
2,073
articles · all by Naren
🔥

That's Kubernetes. Mark it forged?

8 min read · try the examples if you haven't

Previous
Kubernetes Taints, Tolerations and Node Affinity
35 / 38 · Kubernetes
Next
Kubernetes Jobs and CronJobs