Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Kubernetes & Helm By James Joyner IV · · 9 min read

Kubernetes Error Guide: 'DaemonSet does not have minimum availability'

Fix a DaemonSet that won't run on every node: untolerated taints, nodeSelector mismatches, insufficient resources, and maxUnavailable rollout stalls.

  • #kubernetes-helm
  • #troubleshooting
  • #errors
  • #daemonset

Exact Error Message

A DaemonSet rollout or health check reports that the DaemonSet lacks minimum availability — fewer pods are ready than there are nodes that should run them:

$ kubectl rollout status daemonset/node-exporter
Waiting for daemon set "node-exporter" rollout to finish: 4 of 6 updated pods are available...

$ kubectl get daemonset node-exporter
NAME            DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
node-exporter   6         5         4       5            4           <none>          9d

$ kubectl describe daemonset node-exporter
Events:
  Type     Reason       Age   From                  Message
  ----     ------       ----  ----                  -------
  Warning  FailedPlacement  2m  daemonset-controller  failed to place pod on "ip-10-0-3-22": node(s) had untolerated taint

DESIRED 6 but READY 4 is the headline: a DaemonSet should run one pod per eligible node, and two of them are missing or not Ready.

What the Error Means

A DaemonSet’s job is to run exactly one pod on every node that matches its placement rules. The DaemonSet controller computes the set of eligible nodes and creates one pod per node. DESIRED reflects the number of eligible nodes; READY/AVAILABLE reflect how many of those pods are actually running and passing their probes.

When READY < DESIRED, either some pods were never placed (a node was filtered out by taints, nodeSelector, or resources) or placed pods are not becoming Ready (crash loop, failing probe). During a rolling update, the updateStrategy.rollingUpdate.maxUnavailable setting also gates how fast pods are replaced — a stuck new pod combined with a low maxUnavailable freezes the rollout and keeps availability below target. The “minimum availability” wording surfaces in waiters and Deployment-style health gates layered over the DaemonSet.

Common Causes

  • Untolerated node taints — nodes carry taints (control-plane, dedicated pools, NoSchedule) the DaemonSet pod does not tolerate, so no pod is placed there.
  • nodeSelector / nodeAffinity mismatch — the DaemonSet targets a label only some nodes have, so excluded nodes never get a pod.
  • Insufficient resources — the pod’s requests exceed a node’s allocatable capacity, leaving its pod Pending.
  • Crash loop / failing readiness probe — pods are placed but never become Ready, so AVAILABLE lags CURRENT.
  • maxUnavailable too low during update — a single stuck new pod blocks the rolling update from progressing.
  • Node pressure / disk taintsnode.kubernetes.io/disk-pressure or similar conditions evict or block the pod.

How to Reproduce the Error

Run a DaemonSet whose pods request more memory than a node can offer, or that lacks a toleration for a tainted node:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
spec:
  selector:
    matchLabels: { app: node-exporter }
  template:
    metadata:
      labels: { app: node-exporter }
    spec:
      containers:
        - name: exporter
          image: registry.k8s.io/pause:3.9
          resources:
            requests:
              memory: "64Gi"
kubectl apply -f node-exporter-ds.yaml
kubectl get daemonset node-exporter
NAME            DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   AGE
node-exporter   6         6         0       6           0           40s

Every pod is Pending for Insufficient memory, so READY stays at 0 and the DaemonSet never reaches minimum availability.

Diagnostic Commands

# Compare desired vs ready across the cluster
kubectl get daemonset <DS> -o wide

# Find which nodes are missing a pod
kubectl get pods -l app=<APP> -o wide
kubectl get nodes -o name | wc -l

# Why was a pod not placed or not Ready?
kubectl describe daemonset <DS> | grep -A8 Events
kubectl describe pod <DS-POD> | grep -A10 Events

# Inspect node taints, labels, and conditions
kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints
kubectl describe node <NODE> | grep -i 'taint\|Allocatable\|pressure'

# Check the rollout strategy
kubectl get daemonset <DS> -o jsonpath='{.spec.updateStrategy}'

Comparing the per-node pod list against the node list pinpoints exactly which nodes are missing their DaemonSet pod.

Step-by-Step Resolution

1. Determine whether pods are missing or just not Ready. If CURRENT < DESIRED, pods were never placed (taints/selector/resources). If CURRENT == DESIRED but READY < CURRENT, pods run but fail to become Ready (crash/probe).

kubectl get daemonset <DS> -o wide

2. Fix untolerated taints. DaemonSets often need broad tolerations to cover every node. Add the matching toleration (or a wildcard) so pods can land on tainted nodes:

tolerations:
  - operator: "Exists"   # tolerate all taints, common for node agents

3. Fix nodeSelector / affinity mismatches. If you intend to run on all nodes, remove the restrictive selector. If you target a subset, label the intended nodes:

kubectl get nodes --show-labels | grep -o 'role=[^,]*'

4. Fix insufficient resources. Right-size requests to fit the smallest eligible node’s allocatable capacity:

kubectl describe pod <DS-POD> | grep -A4 Events   # Insufficient memory?

5. Fix crash loops / readiness probes. If pods are placed but not Ready, diagnose the container the same way as any pod and correct the image or probe. See CrashLoopBackOff.

6. Unblock a stuck rolling update. If one new pod is wedged and maxUnavailable is 1, the rollout cannot proceed. Fix the underlying pod; the controller resumes automatically. Raising maxUnavailable speeds replacement but does not fix a broken pod.

Prevention and Best Practices

  • Give node-agent DaemonSets broad tolerations (operator: Exists) so new tainted node pools are covered automatically.
  • Keep DaemonSet requests small and realistic — they must fit your smallest node, including constrained edge or spot nodes.
  • Set updateStrategy.rollingUpdate.maxUnavailable to a value that balances rollout speed against keeping the agent running fleet-wide.
  • Alert when a DaemonSet’s numberAvailable drops below desiredNumberScheduled; agents like log shippers and CNI plugins are cluster-critical.
  • When adding node pools with new taints or labels, re-check that every cluster-wide DaemonSet still covers them. More in Kubernetes & Helm guides.
  • FailedScheduling — the per-node filtering reasons (taints, resources) behind missing DaemonSet pods.
  • CrashLoopBackOff — why placed DaemonSet pods may never become Ready.
  • OOMKilled — DaemonSet agents killed for exceeding memory limits.

Frequently Asked Questions

Why is DESIRED less than my node count? DESIRED counts only nodes eligible after placement rules. Nodes filtered out by nodeSelector, nodeAffinity, or untolerated taints are excluded from the desired count entirely, so a smaller number is expected when you intentionally target a subset.

My DaemonSet has no nodeSelector but still skips a node — why? That node almost certainly carries a taint the pod does not tolerate, or it lacks allocatable resources for the pod’s requests. kubectl describe daemonset events name the node and reason.

How do I make a DaemonSet run on control-plane nodes? Add a toleration for the control-plane taint (node-role.kubernetes.io/control-plane:NoSchedule) or use operator: Exists to tolerate everything. By default those nodes are tainted and excluded.

The rollout is stuck at one pod — is maxUnavailable the cause? maxUnavailable controls how many pods can be down at once, but it does not cause the stall; a pod that never becomes Ready does. Fix that pod and the rolling update continues within the maxUnavailable budget.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.