didn't match pod anti-affinity rules: The pod's spreading rules cannot be satisfied at the current node count
A required anti-affinity rule forbids placing a pod where a matching pod already runs. With fewer eligible nodes than replicas, the surplus replicas can never be scheduled.
Applies to: All Kubernetes versions
What it means
Pod anti-affinity keeps replicas apart, usually one per node or one per zone, and in its requiredDuringSchedulingIgnoredDuringExecution form it is a hard constraint. The arithmetic is simple and unforgiving: with a topology key of hostname and three eligible nodes, a fourth replica has nowhere to go and stays Pending forever. This shows up on scale-up, during rolling updates where the surge pod needs a node that is already occupied by the pod it will replace, and after a node failure reduces the eligible count below the replica count.
Most common causes
- More replicas than eligible nodes under a required per-node anti-affinity rule.
- A rolling update needing a surge pod placed where anti-affinity forbids it.
- A node failure or cordon reducing the eligible node count.
- A topology key such as zone, where the number of zones is small and fixed.
- An anti-affinity selector matching more pods than intended, including pods from other workloads.
- Anti-affinity combined with a node selector, narrowing the eligible set further than expected.
How to diagnose it
- Read the scheduler's message:
kubectl describe pod PODnames the anti-affinity rule among the rejection reasons. - Count eligible nodes against replicas:
kubectl get nodes, filtered by whatever selectors also apply. - Check the topology key and the selector:
kubectl get pod POD -o jsonpath='{.spec.affinity.podAntiAffinity}'. - Check whether the selector matches pods you did not intend it to.
- For a stalled rollout, check whether the surge pod is the one that cannot be placed.
How to fix it
- Relax the rule from
requiredtopreferredif strict spreading is a preference rather than a requirement. This is usually the right answer. - Add nodes so the eligible count exceeds the replica count.
- Use topology spread constraints instead, which express spreading with a tunable skew rather than an absolute prohibition.
- Set
maxSurge: 0so a rolling update does not need an extra node. - Narrow the anti-affinity selector so it matches only this workload's own pods.
Notes
Topology spread constraints are the more flexible modern tool for this. They express "spread these pods evenly, tolerating a skew of N" rather than "never co-locate", which handles node failures and rollouts without becoming unschedulable.
Related
- FailedScheduling — The scheduler could not find a suitable node
- Pending — Pod accepted but not yet running
Sources
- Kubernetes documentation — Assigning Pods to Nodes
- Kubernetes documentation — Pod Topology Spread Constraints
- Kubernetes documentation — Kubernetes Scheduler