CKA — DaemonSets & Static Pods

5 minute read

CKA Exam Domain

Domain Weight
Workloads & Scheduling 15%

DaemonSets and static Pods are CKA favorites. Expect questions on creating DaemonSets, identifying static Pods, and knowing where static Pod manifests live.

What Is a DaemonSet?

A DaemonSet ensures that a copy of a Pod runs on every node (or a selected subset of nodes) in the cluster. When a new node joins the cluster, the DaemonSet automatically schedules a Pod on it. When a node is removed, the Pod is garbage collected.

Key characteristics:

  • One Pod per node (by default).
  • Automatically adapts as nodes are added or removed.
  • Bypasses the scheduler in older versions; uses the default scheduler since v1.12.

DaemonSet Use Cases

Use Case Example
Log collection Fluentd, Filebeat
Monitoring agents Prometheus Node Exporter, Datadog Agent
Networking kube-proxy, Calico, Cilium CNI
Storage CSI node plugins
Security Falco, Twistlock

Exam Tip: When a question says “run on every node,” think DaemonSet.

Creating a DaemonSet

Here’s a DaemonSet that deploys a Fluentd log collector on every node:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
  namespace: kube-system
  labels:
    app: fluentd
spec:
  selector:
    matchLabels:
      app: fluentd
  template:
    metadata:
      labels:
        app: fluentd
    spec:
      containers:
        - name: fluentd
          image: fluentd:v1.16
          resources:
            requests:
              cpu: "100m"
              memory: "200Mi"
            limits:
              cpu: "200m"
              memory: "400Mi"
          volumeMounts:
            - name: varlog
              mountPath: /var/log
      volumes:
        - name: varlog
          hostPath:
            path: /var/log
      tolerations:
        - operator: "Exists"
kubectl apply -f fluentd-ds.yaml
kubectl get daemonset fluentd -n kube-system

Notice the tolerations with operator: "Exists" — this ensures the DaemonSet runs even on tainted nodes (including the control plane).

DaemonSet vs Deployment

Feature DaemonSet Deployment
Scheduling One Pod per node Replicas spread by scheduler
Replicas Determined by number of nodes Explicitly set
Use Case Node-level agents Stateless application workloads
Scaling Add/remove nodes Change replica count
Node targeting Automatic (all or selected nodes) Via affinity/nodeSelector

What Are Static Pods?

A static Pod is managed directly by the kubelet on a specific node — not by the API server or controllers. The kubelet watches a directory for Pod manifest files and automatically creates/deletes Pods based on what it finds.

Key characteristics:

  • Defined by YAML files on the node’s filesystem.
  • Managed by kubelet, not the control plane.
  • A mirror Pod is created in the API server so you can see it with kubectl, but you cannot modify or delete it through kubectl.
  • If you delete the mirror Pod, kubelet recreates it.

Static Pod Directory

The kubelet looks for static Pod manifests in a directory configured by staticPodPath. The default is:

/etc/kubernetes/manifests/

Verify the path:

cat /var/lib/kubelet/config.yaml | grep staticPodPath

Expected output:

staticPodPath: /etc/kubernetes/manifests

Exam Tip: On kubeadm clusters, the static Pod path is always /etc/kubernetes/manifests/. If a question asks you to find or create a static Pod, that’s where to look.

Creating Static Pods

To create a static Pod, place a YAML manifest in the static Pod directory on the target node:

# SSH to the node (if needed)
ssh <node-name>

# Create the manifest
cat <<EOF > /etc/kubernetes/manifests/static-nginx.yaml
apiVersion: v1
kind: Pod
metadata:
  name: static-nginx
spec:
  containers:
    - name: nginx
      image: nginx:1.27
      ports:
        - containerPort: 80
EOF

The kubelet detects the new file and starts the Pod automatically. Verify from the control plane:

kubectl get pods -A | grep static-nginx

The Pod name will have the node name appended, e.g., static-nginx-worker-1.

Delete a static Pod:

# On the node:
rm /etc/kubernetes/manifests/static-nginx.yaml

The kubelet will terminate the Pod automatically.

Static Pod vs Regular Pod

Feature Static Pod Regular Pod
Managed By kubelet API server / controllers
Visible in kubectl? Yes (mirror Pod) Yes
Can modify via kubectl? No Yes
Restart Behavior kubelet restarts it if it crashes Depends on restartPolicy and controller
Mirror Pod Created automatically N/A
Use Case Control plane components Application workloads

Control Plane as Static Pods

On kubeadm clusters, the control plane components are deployed as static Pods:

ls /etc/kubernetes/manifests/
etcd.yaml
kube-apiserver.yaml
kube-controller-manager.yaml
kube-scheduler.yaml

These are managed by the kubelet on the control plane node. This is why the control plane can recover even if the API server goes down — kubelet restarts the static Pods.

kubectl get pods -n kube-system | grep -E "etcd|apiserver|controller|scheduler"

Exam Tip: If a question asks “how are control plane components managed in kubeadm?”, the answer is static Pods.

Combining Scheduling with DaemonSets

You can use nodeSelector and tolerations with DaemonSets to limit which nodes get the Pod.

Run only on nodes with a specific label:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: monitoring-agent
spec:
  selector:
    matchLabels:
      app: monitoring
  template:
    metadata:
      labels:
        app: monitoring
    spec:
      containers:
        - name: agent
          image: prom/node-exporter:v1.7.0
      nodeSelector:
        monitoring: enabled
      tolerations:
        - key: "dedicated"
          operator: "Equal"
          value: "monitoring"
          effect: "NoSchedule"

This DaemonSet only places Pods on nodes labeled monitoring=enabled and tolerates the dedicated=monitoring:NoSchedule taint.

kubectl Commands

# List DaemonSets
kubectl get daemonsets -n kube-system

# Describe a DaemonSet
kubectl describe daemonset kube-proxy -n kube-system

# Check DaemonSet Pods
kubectl get pods -n kube-system -l k8s-app=kube-proxy -o wide

# Create a DaemonSet from YAML
kubectl apply -f daemonset.yaml

# Static Pods — check the manifests directory
ls /etc/kubernetes/manifests/

# Find the staticPodPath
cat /var/lib/kubelet/config.yaml | grep staticPodPath

# Identify static Pods (they have the node name appended)
kubectl get pods -n kube-system -o wide | grep <node-name>

Practice Questions

Q1. Create a DaemonSet named log-collector in the default namespace that runs busybox:1.36 on every node.

Show Answer
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: log-collector
spec:
  selector:
    matchLabels:
      app: log-collector
  template:
    metadata:
      labels:
        app: log-collector
    spec:
      containers:
        - name: busybox
          image: busybox:1.36
          command: ["sleep", "infinity"]
      tolerations:
        - operator: "Exists"
kubectl apply -f log-collector.yaml
kubectl get daemonset log-collector

Q2. Where are static Pod manifests stored on a kubeadm cluster? How do you verify this?

Show Answer

Static Pod manifests are stored in /etc/kubernetes/manifests/.

Verify:

cat /var/lib/kubelet/config.yaml | grep staticPodPath

Q3. How do you create a static Pod named static-web on node worker-1?

Show Answer

SSH to the node and place a manifest in the static Pod directory:

ssh worker-1
cat <<EOF > /etc/kubernetes/manifests/static-web.yaml
apiVersion: v1
kind: Pod
metadata:
  name: static-web
spec:
  containers:
    - name: nginx
      image: nginx:1.27
EOF

The kubelet will create the Pod automatically. Verify with kubectl get pods -A | grep static-web.

Q4. What happens if you kubectl delete a static Pod’s mirror Pod?

Show Answer

The kubelet recreates the mirror Pod immediately. The only way to permanently delete a static Pod is to remove its manifest file from the static Pod directory on the node.

Q5. A DaemonSet needs to run only on nodes labeled tier=edge. How do you configure this?

Show Answer

Add nodeSelector to the DaemonSet’s Pod template:

spec:
  template:
    spec:
      nodeSelector:
        tier: edge

The DaemonSet will only schedule Pods on nodes with the tier=edge label.

Updated: