Topology Spread Constraints in Kubernetes

Khimananda Oli 8 min read Virtualization
Topology Spread Constraints in Kubernetes

By Khimananda Oli | Last reviewed: August 2026

Clusters that ignore physical topology are fragile, regardless of how many replicas you run. Topology Spread Constraints in Kubernetes solve this by instructing the scheduler to distribute pods evenly across defined failure domains like zones, nodes, or racks. Without these constraints, a single zone outage can silently wipe out your entire service even with ten replicas configured. This guide provides the exact configuration patterns and mathematical logic needed to guarantee true high availability in production environments.

What Are Topology Spread Constraints in Kubernetes and Why Do They Matter?

The default Kubernetes scheduler optimizes for resource packing and immediate schedulability, not necessarily for fault isolation. Left unconstrained, the scheduler might place all replicas of a critical microservice on nodes within the same availability zone simply because those nodes had available CPU at scheduling time. When that zone experiences an outage — a common occurrence in cloud regions from AWS us-east-1 to GCP asia-south1 — every replica fails simultaneously. Properly configuring blue-green and canary deploys on Kubernetes helps with safe rollouts, but only topology awareness prevents correlated infrastructure failures from causing total service loss.

Without Spread ConstraintsZone AP1P2P3 P4 P5 Zone BZone CWith Topology SpreadZone AP1P4Zone BP2P5Zone CP3
Naive scheduling risks total outage in one zone; Topology Spread Constraints in Kubernetes enforce even distribution

Topology spread constraints operate at the scheduler level, evaluating candidate nodes against a mathematical skew formula before binding a pod. Unlike pod anti-affinity rules which are binary (either satisfy or fail), spread constraints allow controlled imbalance through the maxSkew parameter. This flexibility means your deployment can still proceed during partial capacity issues rather than stalling entirely. For teams managing stateful workloads or databases, understanding this distinction is critical before attempting PostgreSQL replication and high availability setups where uneven distribution causes replication lag or split-brain scenarios.

How Do You Configure maxSkew and whenUnsatisfiable Correctly?

The two most misunderstood fields in topology spread constraints are maxSkew and whenUnsatisfiable. Getting these wrong either creates false security or causes unnecessary scheduling failures. The maxSkew value defines the maximum permitted difference in pod count between any two topology domains. If you set maxSkew: 1 across three zones, the scheduler ensures no zone has more than one pod difference from any other zone. With six replicas, valid distributions include 2-2-2 or 2-3-1, but never 4-1-1.

Choosing Between DoNotSchedule and ScheduleAnyway

The whenUnsatisfiable field determines scheduler behavior when no placement satisfies the maxSkew constraint. In production systems requiring strict compliance or genuine HA, always use DoNotSchedule. This leaves pods in Pending state rather than violating your topology guarantees. Use ScheduleAnyway only for batch jobs or non-critical workloads where some distribution is better than none. A common mistake in Nepal-based deployments targeting Singapore or Mumbai regions is setting ScheduleAnyway during testing and forgetting to change it before production promotion, leaving services vulnerable during regional incidents.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: payment-service
spec:
  replicas: 6
  selector:
    matchLabels:
      app: payment-service
  template:
    metadata:
      labels:
        app: payment-service
    spec:
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: topology.kubernetes.io/zone
          whenUnsatisfiable: DoNotSchedule
          labelSelector:
            matchLabels:
              app: payment-service
        - maxSkew: 1
          topologyKey: kubernetes.io/hostname
          whenUnsatisfiable: DoNotSchedule
          labelSelector:
            matchLabels:
              app: payment-service
      containers:
        - name: payment-api
          image: payments:v2.4.1
          resources:
            requests:
              cpu: 500m
              memory: 512Mi

This configuration applies two constraints simultaneously: first spreading across zones, then across individual nodes within each zone. The order matters — the scheduler evaluates constraints sequentially, and earlier constraints take precedence when conflicts arise. Always pair spread constraints with explicit resource requests; without them, the scheduler cannot accurately predict whether a node can accommodate additional pods, leading to suboptimal spreading or cascading pending states.

How Does Topology Spread Compare to Pod Anti-Affinity?

Many engineers default to pod anti-affinity rules because they existed before topology spread constraints reached GA status. While both mechanisms influence pod placement, their operational characteristics differ significantly. Understanding when to use each prevents over-constraining your cluster or creating unschedulable deployments during scaling events. Refer to Kubernetes resource limits and requests guidance to ensure your spreading strategy aligns with actual capacity planning rather than theoretical distribution.

CriteriaTopology Spread ConstraintsPod Anti-Affinity
Distribution ModelSoft balancing with configurable skew toleranceHard exclusion or soft preference (binary)
Scaling BehaviorGraceful degradation when domains exhaustPods pend immediately if no valid domain exists
Multi-Domain SupportNative support for zone + node + custom keysRequires separate rule per topology key
Operational ComplexitySingle declarative block covers most HA needsMultiple rules needed for equivalent coverage
Best ForStateless services, web frontends, API layersStrict singleton enforcement, leader election

In practice, I recommend topology spread constraints as the default for 90% of workloads. Reserve pod anti-affinity for cases where you absolutely cannot tolerate co-location, such as etcd members or database primaries. Combining both is valid but increases scheduling latency and debugging complexity. If your team struggles with frequent Pending pods after adopting spread constraints, the issue usually stems from insufficient node capacity in specific domains rather than misconfiguration — check your Cluster Autoscaler settings and ensure it can provision nodes in all targeted zones.

New Pod RequestCount Pods Per Domain(matching labelSelector)Calculate Global Skewmax(count) - min(count)Skew <= maxSkew?YesSchedule PodNoCheck PolicyDoNotSchedule / AnywayBound to NodeRemain Pending
Scheduler evaluates global skew across all domains before binding; DoNotSchedule enforces strict topology guarantees

What Happens When Capacity Is Uneven Across Zones?

Real-world clusters rarely have perfectly symmetric capacity. One zone might have older instance types, reserved capacity limitations, or spot interruptions. When a zone cannot accept additional pods while satisfying maxSkew, the scheduler's behavior depends entirely on your whenUnsatisfiable setting. With DoNotSchedule, new pods remain Pending until capacity rebalances or you manually intervene. This is correct behavior for HA-critical services but requires proactive monitoring.

Set up alerts on kube_pod_status_unschedulable metrics filtered by your spread-constrained deployments. In my experience supporting SOC 2 compliant environments, auditors specifically check whether teams monitor for topology violations and have documented remediation procedures. Consider implementing a secondary fallback constraint with ScheduleAnyway and higher maxSkew for graceful degradation during extended capacity issues. This pattern maintains partial topology awareness while preventing complete deployment stalls.

  • Audit node labels quarterly to ensure topology.kubernetes.io/zone values match actual cloud provider zones
  • Test zone failure scenarios in staging using chaos engineering tools before relying on spread constraints in production
  • Combine spread constraints with Pod Disruption Budgets to maintain minimum availability during voluntary disruptions
  • Document your maxSkew rationale in deployment manifests — future engineers need context for why 1 was chosen over 2
  • Review pending pod events weekly to identify chronic capacity imbalances before they cause incidents

How Do You Validate and Debug Topology Distribution in Production?

Configuration alone doesn't guarantee correct behavior. You must validate that pods actually distribute as intended after deployment. The most direct method uses kubectl with custom columns to visualize distribution:

kubectl get pods -l app=payment-service \
  -o custom-columns='NAME:.metadata.name,ZONE:.metadata.labels.topology\.kubernetes\.io/zone,NODE:.spec.nodeName' \
  --sort-by='.metadata.labels.topology\.kubernetes\.io/zone'

For continuous validation, implement admission controllers or OPA policies that reject deployments missing required spread constraints for critical labels. This shifts compliance left and prevents drift. When debugging unexpected distribution, check three things first: verify label selectors match exactly (typos here silently disable constraints), confirm nodes have correct topology labels, and ensure replica count exceeds the number of topology domains (you cannot achieve maxSkew:1 with 2 replicas across 3 zones).

Deploy Manifestwith TSC Configkubectl get pods-o custom-columnsZONE,NODE,STATUSVerify DistributionCheck skew <= maxSkewAll zones representedPrometheus Alertunschedulable_pods> 0 for 5mInvestigateNode capacity? Labels?Selector mismatch?RemediateScale nodes / adjust skewUpdate manifest & redeploy
End-to-end validation loop for Topology Spread Constraints in Kubernetes combines CLI verification with automated alerting

Integrate topology validation into your CI/CD pipeline using tools like kube-score or conftest. These catch misconfigurations before they reach production. For teams operating under ISO 27001 or similar frameworks, maintain evidence of topology validation runs as part of your change management documentation. Auditors appreciate seeing automated proof that HA controls function as designed, not just configuration files claiming they should.

Implementing Resilient Pod Distribution Today

Topology Spread Constraints in Kubernetes transform theoretical high availability into enforced operational reality. Start by adding zone-level spread constraints to your three most critical services this week, using maxSkew: 1 and DoNotSchedule. Validate distribution with the kubectl command provided above, then add Prometheus alerting for unschedulable pods. Once confident, extend to node-level spreading and integrate policy-as-code checks into your deployment pipeline. If your team needs help designing topology-aware architectures that pass compliance audits without sacrificing velocity, reach out to discuss your specific infrastructure challenges.

Frequently Asked Questions

They are scheduling directives that distribute pods across failure domains like zones, nodes, or racks. This ensures high availability by preventing all replicas from landing in a single domain during cluster scaling or node failures in 2026 environments.

Anti-affinity strictly rejects co-location on matching topology keys, potentially leaving pods unschedulable. Topology Spread Constraints allow configurable skew tolerances, enabling best-effort distribution without hard blocking, making them more flexible for dynamic cloud environments and autoscaling clusters.

It defines the maximum permitted difference in pod counts between any two topology domains. A value of one enforces strict balance, while higher values permit gradual imbalance during scaling events or when domain capacity differs significantly across zones.

Yes. You can combine zone, node, and rack constraints in a single pod spec. The scheduler evaluates all constraints simultaneously, satisfying each within its defined maxSkew to achieve multi-dimensional high availability across complex infrastructure topologies.

Yes. In 2026, modern autoscalers respect these constraints when provisioning nodes. If existing domains cannot satisfy the skew requirement, the autoscaler triggers new node creation in underrepresented zones to maintain balanced pod distribution during scale-up events.

Pods remain pending if whenUnsatisfiable is set to DoNotSchedule. Setting it to ScheduleAnyway allows placement in overrepresented domains as a fallback, prioritizing deployment completion over perfect balance during capacity shortages or zone outages.

Use kubectl get pods with wide output to check node assignments per zone. Compare actual distribution against expected skew limits. Monitoring tools like Prometheus can track per-domain pod counts to validate constraint effectiveness continuously in production.

Yes. EKS, GKE, and AKS fully support them in 2026 stable releases. Managed control planes apply these constraints identically to self-managed clusters, though some providers offer enhanced topology awareness through custom schedulers or zone-aware load balancers.

Minimally. The scheduler evaluates domain counts during filtering and scoring phases. With typical cluster sizes under five hundred nodes, overhead is negligible. Large fleets may benefit from scheduler profiles or pre-filtering optimizations to maintain sub-second scheduling performance.

No. They serve complementary purposes. Spread constraints optimize initial placement for availability, while PDBs protect running workloads during voluntary disruptions like upgrades. Use both together to ensure resilience during deployment and maintenance operations in 2026 clusters.

Check events with kubectl describe pod for FailedScheduling messages indicating skew violations. Verify node labels match your topologyKey. Confirm sufficient capacity exists in underrepresented domains or adjust maxSkew to allow temporary imbalance during recovery.

Define them in the pod template spec within deployments or statefulsets. This ensures all replicas inherit identical distribution rules. Namespace-wide defaults via PodTopologySpreadAdmission are possible but less common due to reduced workload-specific tuning flexibility.

Slightly. Enforcing even distribution may leave residual capacity fragmented across domains. However, the availability gains typically outweigh minor density losses. Tune maxSkew conservatively and pair with resource requests aligned to actual usage to optimize both balance and utilization.

Yes. Modify the pod template spec and apply the change. Existing pods retain their original placement until rescheduled. New replicas follow updated constraints immediately. Rolling updates gradually rebalance the deployment according to the revised topology rules.

Standard keys include kubernetes.io/hostname, topology.kubernetes.io/zone, and topology.kubernetes.io/region. Custom labels like rack-id or datacenter also work if consistently applied to nodes. Ensure keys exist on all candidate nodes to avoid unintended scheduling failures.