Skip to content
Latchkey

Kubernetes "topology spread constraints" Unsatisfiable in CI

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: 1
    topologyKey: topology.kubernetes.io/zone
    whenUnsatisfiable: ScheduleAnyway   # was DoNotSchedule
    labelSelector:
      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.

Related guides

References

Not every red build is your code. Latchkey repairs the ones that are not, on the runner. Start free → 30-day trial · No credit card