✦ For everyone, free.

Practical knowledge for real and everyday life

Home

Kubernetes DaemonSet Node Coverage Management

Kubernetes DaemonSet ensures node coverage by running pods across all nodes, providing consistent service availability and infrastructure management across the cluster.

Kubernetes DaemonSet Node Coverage Management is the ongoing practice of ensuring that a DaemonSet's Pods are actually running, healthy, and correctly placed on every node they are intended to cover, and of detecting and remediating gaps in that coverage as the cluster's node population and scheduling constraints change over time. While the DaemonSet controller automatically reconciles Pod placement against node membership, coverage is not something that is guaranteed to remain perfect indefinitely without attention — new nodes can join in states that momentarily prevent scheduling, tolerations can drift out of sync with taints, and scheduling constraints can silently exclude nodes that were meant to be covered.

Coverage management is fundamentally about closing the gap between "the DaemonSet's desired scheduling constraints" and "the actual set of nodes with a healthy, running Pod," since a coverage gap for an infrastructure daemon (a log collector, a CNI agent, a security scanner) means that specific node is silently missing whatever function the daemon provides.


Coverage Status Fields

Reading numberReady and desiredNumberScheduled

.status.desiredNumberScheduled reports how many nodes the DaemonSet's scheduling constraints currently consider eligible; .status.numberReady reports how many of those have a Pod that is both scheduled and passing readiness. A persistent gap between these two numbers is the primary quantitative signal of a coverage problem.

kubectl get daemonset codartium-log-agent -o jsonpath='{.status.numberReady}/{.status.desiredNumberScheduled}'

numberMisscheduled

.status.numberMisscheduled flags Pods running on nodes that no longer satisfy the DaemonSet's current scheduling constraints — typically the result of a nodeSelector or taint change made after Pods were already placed. A non-zero value here indicates the controller will be removing those Pods from now-ineligible nodes, which is a normal part of reconciliation following a scheduling constraint change, not necessarily an error condition on its own.


Common Causes of Coverage Gaps

New Nodes Not Yet Ready

A newly joined node that has not yet completed its own initialization (kubelet registration, required taints not yet removed by a node-readiness controller) will not immediately receive DaemonSet Pods; a coverage gap here is typically transient and resolves once the node finishes becoming ready, but persistent gaps on specific nodes suggest the node itself has a deeper initialization problem.

Taint and Toleration Drift

If a cluster introduces a new taint on a class of nodes (for cost allocation, workload isolation, or security segmentation) without updating the tolerations on daemon templates that are supposed to cover those nodes, the daemon silently stops being scheduled there going forward. Because this produces no error — the Pods simply are never created — it is one of the more common, quietly accumulating causes of coverage drift in clusters that add node taints without an accompanying audit of existing DaemonSet tolerations.

Resource Pressure Preventing Scheduling

A node under sufficient memory or CPU pressure may be unable to accommodate even a lightweight daemon Pod if the node's allocatable capacity is already exhausted by other workloads, producing a Pod stuck in Pending on that specific node rather than an outright scheduling exclusion.

PodDisruptionBudget or Eviction Interactions

While DaemonSet Pods are typically excluded from voluntary eviction under PodDisruptionBudget accounting by default cluster behavior, misconfigured node maintenance tooling that does not correctly account for DaemonSet Pods can still produce transient coverage gaps during node drains if the tooling attempts to evict them unnecessarily.


Detecting and Remediating Gaps

Cross-Referencing Nodes Against Daemon Pods

comm -23 <(kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' | sort) \
         <(kubectl get pods -l app=codartium-log-agent -o jsonpath='{range .items[*]}{.spec.nodeName}{"\n"}{end}' | sort)

A comparison like this — listing all nodes, listing all nodes with a healthy daemon Pod, and diffing the two — is a direct way to identify exactly which nodes lack coverage, more precise than relying solely on the aggregate counters in .status.

Auditing Toleration Coverage Against Cluster Taints

kubectl get nodes -o json | jq -r '.items[].spec.taints[]?.key' | sort -u
kubectl get daemonset codartium-log-agent -o jsonpath='{.spec.template.spec.tolerations}'

Periodically comparing the full set of taints present across cluster nodes against the tolerations configured on each daemon intended for full coverage catches drift before it silently accumulates into a growing set of uncovered nodes.

Monitoring Coverage as an Ongoing Signal

kubectl get daemonsets -A -o custom-columns=NAME:.metadata.name,DESIRED:.status.desiredNumberScheduled,READY:.status.numberReady

Alerting on a sustained gap between desiredNumberScheduled and numberReady — rather than only checking during incident investigation — turns coverage management from a reactive exercise into a continuously monitored operational metric.


Example

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: codartium-coverage-example
spec:
  selector:
    matchLabels:
      app: codartium-node-agent
  template:
    metadata:
      labels:
        app: codartium-node-agent
    spec:
      tolerations:
        - operator: "Exists"
          effect: "NoSchedule"
        - operator: "Exists"
          effect: "NoExecute"
      containers:
        - name: agent
          image: codartium/node-agent:latest