Add a topologySpreadConstraints entry to the Deployment pod spec: maxSkew: 1, topologyKey: topology.kubernetes.io/zone, whenUnsatisfiable: DoNotSchedule, labelSelector matching the pod labels
Set matchLabelKeys: [pod-template-hash] so the spread constraint considers only pods from the current ReplicaSet revision during a rolling update, preventing the new pods from being over-concentrated relative to old pods on the old revision
Set minDomains equal to the number of availability zones (e.g., 3) so the scheduler treats a missing zone as an available domain and spreads there rather than concentrating in the existing zones
Combine with nodeAffinity or nodeTaints to ensure worker nodes are labeled with topology.kubernetes.io/zone; without this label the constraint is silently ignored by the scheduler for unlabeled nodes
Verify spreading after a rollout: kubectl get pods -o wide and confirm pods are distributed across zones; use kubectl describe node <name> | grep zone to confirm zone labels are present
Test disruption resilience by cordoning all nodes in one zone and running kubectl drain to confirm the remaining replicas maintain service given the spread and PDB settings
Known gotchas
matchLabelKeys is a beta feature gated by MatchLabelKeysInPodTopologySpread (enabled by default in Kubernetes 1.27+); on older clusters the field is ignored, causing mixing of old and new revision pods in the spread calculation during rolling updates
whenUnsatisfiable: DoNotSchedule blocks pod scheduling if the constraint cannot be satisfied (e.g., not enough nodes across zones for the required maxSkew), which can stall a Deployment rollout indefinitely — use DoNotSchedule only when you have confirmed sufficient capacity across zones
Topology spread constraints interact with PodAffinity rules; conflicting affinity and spread constraints can result in unschedulable pods without clear error messages beyond FailedScheduling events
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp