Kubernetes "topology spread constraints" Unsatisfiable in CI
By Kaveh Alemi·Latchkey
A topologySpreadConstraints rule with whenUnsatisfiable: DoNotSchedule keeps pods Pending when there are not enough topology domains (zones/nodes) to honor maxSkew. The scheduler refuses to place a pod that would violate the spread.
What this error means
New pods stay Pending with FailedScheduling noting the topology spread constraint. It reproduces whenever the cluster has fewer eligible domains than the constraint needs.
kubectl describe pod
0/3 nodes are available: 3 node(s) didn't match pod topology spread constraints
(missing required label) / 3 node(s) didn't satisfy existing pods anti-affinity rules.
Diagnose it: read events, not just status
A deployment that never becomes ready has the reason in its events and in the pod state, not in the deployment status. Read both before changing the manifest.
Terminal
kubectl rollout status deploy/<name> --timeout=120s
kubectl describe deploy/<name> | sed -n "/Events/,$p"
kubectl get pods -l app=<name> -o wide
kubectl describe pod <pod> | sed -n "/Events/,$p"
kubectl logs <pod> --previous --tail=50 # the crash before the restart
Common causes
Too few topology domains for the skew
Spreading across topology.kubernetes.io/zone with maxSkew: 1 needs enough zones to balance replicas. With one zone (or unlabeled nodes), the constraint can never be satisfied.
Nodes missing the topology label
If the topologyKey label is absent on nodes, those nodes count as a missing domain and cannot receive the pod, leaving it Pending.
How to fix it
Inspect the domains and the constraint
Confirm how many labeled domains actually exist for the chosen topologyKey.
Terminal
kubectl get nodes -L topology.kubernetes.io/zone
kubectl get nodes -L kubernetes.io/hostname
Loosen the constraint or let it degrade gracefully
Use ScheduleAnyway so the scheduler still places the pod (preferring spread) when the hard rule cannot be met, or relax maxSkew.
deployment.yaml
topologySpreadConstraints:- maxSkew:1topologyKey:topology.kubernetes.io/zonewhenUnsatisfiable:ScheduleAnyway # was DoNotSchedulelabelSelector:matchLabels:{ app: api }
How to prevent it
Match maxSkew/DoNotSchedule to the number of labeled domains you actually run.
Label nodes with the topology key the constraint references.
Prefer ScheduleAnyway when high availability is best-effort rather than mandatory.
Frequently asked questions
What causes Kubernetes "topology spread constraints" unsatisfiable in CI?
There are 2 common causes: too few topology domains for the skew and nodes missing the topology label. Spreading across topology.kubernetes.io/zone with maxSkew: 1 needs enough zones to balance replicas.
How do I fix Kubernetes "topology spread constraints" unsatisfiable in CI?
There are 2 fixes depending on which cause you have: inspect the domains and the constraint and loosen the constraint or let it degrade gracefully. Work through them in order, since the first is the most common.
What does Kubernetes "topology spread constraints" unsatisfiable in CI actually mean?
New pods stay Pending with FailedScheduling noting the topology spread constraint.
How do I stop Kubernetes "topology spread constraints" unsatisfiable in CI happening again?
Match maxSkew/DoNotSchedule to the number of labeled domains you actually run. The prevention section lists 3 changes that keep it from recurring.