Skip to main content

Kubernetes Ep 10: DaemonSets & Cluster Node Agents

Rachmat Hidayat
Author
Rachmat Hidayat
Learn & sharing insights on TypeScript, Go, Kubernetes, DevOps, DevSecOps, SRE, Platform Engineering, AI/ML Engineering, and MLOps.
kubernetes - This article is part of a series.
Part 10: This Article
While Deployments distribute Pods across nodes based on available capacity, DaemonSets ensure that a copy of a specific Pod runs on all (or selected) worker nodes in the cluster. As nodes are added to or removed from the cluster, DaemonSet Pods are added or garbage-collected automatically.

TL;DR (Quick Summary)
#

  • Use Cases: Node monitoring agents (prometheus-node-exporter), container log shippers (fluentbit, logstash), storage daemons (glusterfs, ceph), and CNI network plugins (cilium, calico, kube-proxy).
  • Node Lifecycle Integration: When a new node joins the cluster, the DaemonSet controller schedules a DaemonSet pod onto it automatically.
  • Tolerations: DaemonSets frequently specify tolerations to ensure they run on Control Plane nodes despite master taints.

1. DaemonSet Architecture
#


graph TD
    DS["DaemonSet Controller: node-exporter"] -->|Ensures 1 Pod per Node| N1["Worker Node 1"]
    DS -->|Ensures 1 Pod per Node| N2["Worker Node 2"]
    DS -->|Ensures 1 Pod per Node| N3["Control Plane Node
(Tolerates Master Taint)"] N1 --> P1["Pod: node-exporter-n1
(Collects CPU/RAM metrics)"] N2 --> P2["Pod: node-exporter-n2
(Collects CPU/RAM metrics)"] N3 --> P3["Pod: node-exporter-n3
(Collects CPU/RAM metrics)"]

2. Declarative DaemonSet Manifest (Prometheus Node Exporter)
#

Let’s write a production-ready DaemonSet manifest deploying the Prometheus Node Exporter to collect hardware and OS metrics directly from worker host filesystems (/proc and /sys).

Create daemonset-node-exporter.yaml:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
  namespace: kube-system
  labels:
    app.kubernetes.io/name: node-exporter
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: node-exporter
  template:
    metadata:
      labels:
        app.kubernetes.io/name: node-exporter
    spec:
      # Run on control plane nodes as well
      tolerations:
      - key: node-role.kubernetes.io/control-plane
        operator: Exists
        effect: NoSchedule
      - key: node-role.kubernetes.io/master
        operator: Exists
        effect: NoSchedule
      containers:
      - name: node-exporter
        image: prom/node-exporter:v1.7.0
        args:
        - --path.procfs=/host/proc
        - --path.sysfs=/host/sys
        - --collector.filesystem.mount-points-exclude=^/(dev|proc|sys|var/lib/docker/.+)($|/)
        ports:
        - name: metrics
          containerPort: 9100
          hostPort: 9100 # Binds directly to node host IP port 9100
        resources:
          requests:
            cpu: "50m"
            memory: "32Mi"
          limits:
            cpu: "100m"
            memory: "64Mi"
        volumeMounts:
        - name: proc
          mountPath: /host/proc
          readOnly: true
        - name: sys
          mountPath: /host/sys
          readOnly: true
      hostNetwork: true
      hostPID: true
      volumes:
      - name: proc
        hostPath:
          path: /proc
      - name: sys
        hostPath:
          path: /sys

Apply manifest:

kubectl apply -f daemonset-node-exporter.yaml

3. Inspecting DaemonSet Execution
#

Check DaemonSet status in kube-system:

kubectl get daemonsets -n kube-system node-exporter

Expected Terminal Output:

NAME            DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
node-exporter   3         3         3       3            3           <none>          20s

List the individual DaemonSet pods scheduled per node:

kubectl get pods -n kube-system -l app.kubernetes.io/name=node-exporter -o wide
NAME                  READY   STATUS    RESTARTS   AGE   IP             NODE
node-exporter-4z8kl   1/1     Running   0          35s   192.168.1.10   minikube
node-exporter-8p2mx   1/1     Running   0          35s   192.168.1.11   minikube-worker-01
node-exporter-k9q1w   1/1     Running   0          35s   192.168.1.12   minikube-worker-02

Notice how exactly 1 Pod instance runs on every single worker node!


4. Summary & Next Steps
#

DaemonSets are essential for managing cluster observability, log shipping, and network daemons.

In Episode 11: Jobs, CronJobs & Batch Processing, we will explore run-to-completion workloads: Jobs (batch tasks) and CronJobs (scheduled maintenance & backup tasks)!

kubernetes - This article is part of a series.
Part 10: This Article