Topology Spread or Pod Anti-Affinity? Designing Failure-Domain Placement

Choose topology spread vs pod anti-affinity by the availability invariant, domain labels, skew tolerance, degraded-cluster behavior, and scheduling cost.

Edilec Research Updated 2026-07-13 Cloud & DevOps

Topology spread vs pod anti-affinity is not a choice between modern and obsolete syntax. The mechanisms express different placement ideas. Anti-affinity says that a pod should or must avoid a topology domain containing another selected pod. Topology spread says that matching pods should remain within a permitted skew across eligible domains. One models separation; the other models distribution. The correct choice follows from the service failure invariant and what should happen when a zone or node disappears.

A manifest that looks highly available can reduce availability if it becomes impossible to schedule replacement pods. Required anti-affinity across hostnames limits one matching pod per node. That may be exactly right for quorum members, but it blocks a fourth replica in a three-node cluster and can stall a rolling update. A hard maxSkew: 1 zone spread can also block when labels or eligible domains are wrong. Design ordinary and degraded states together, then test scheduler decisions rather than reading intent from YAML.

Define the placement invariant in six steps

Write the failure statement first: for example, loss of any one zone must leave two ready replicas, or loss of one node must not remove both copies of a shard. Name the selected pod set, required surviving capacity, recognized domains, and acceptable skew. Then calculate replica counts for normal operation, rolling surge, scale-out, one unavailable domain, and a partially drained cluster. If the arithmetic cannot satisfy the invariant, no scheduler feature will repair it; add replicas, nodes, zones, or a controlled relaxation.

Six-stage Kubernetes placement matrix covering availability invariant, domains, replica arithmetic, topology spread, pod anti-affinity, and degraded-state testing.
A placement rule protects availability only when labels are trustworthy and replacement replicas remain schedulable in the intended degraded state.
RequirementTopology spreadPod anti-affinityRecommended expression
Keep replicas roughly even across zonesDirect fit through maxSkewIndirect and often too rigidZone spread constraint
Never co-locate two quorum members on a nodeCan express skew but needs domain mathDirect required separationRequired node anti-affinity
Prefer separation but schedule during shortageScheduleAnyway with scoringPreferred anti-affinityChoose based on evenness need
Support many replicas per domainDesigned for this caseRequired rule prevents itTopology spread
Place near or away from another applicationSelector can count it but intent is awkwardDirect pod affinity or anti-affinityAffinity mechanism

Model distribution with topology spread constraints

A topology spread constraint combines maxSkew, topologyKey, whenUnsatisfiable, and a label selector. The official constraint reference explains how eligible domains and global minimum affect skew. Use DoNotSchedule only for a true invariant; use ScheduleAnyway when evenness is preferred but service capacity is more important during shortage. Multiple constraints are combined, so a pod may need to satisfy both zone and hostname distribution alongside resource, volume, affinity, and taint filters.

The selector must match the intended population and normally the incoming pod itself. Otherwise, pods can accumulate without being counted as expected. minDomains can prevent a hard constraint from treating one surviving zone as a satisfactorily balanced universe, but it may leave pods pending until enough domains exist. Review nodeAffinityPolicy and nodeTaintsPolicy where available because they change which domains participate in calculations. Use stable labels such as topology.kubernetes.io/zone only after verifying every eligible node carries accurate values.

Use pod anti-affinity for explicit separation

Inter-pod anti-affinity selects existing pods and a topology key, then either requires or prefers separation. The Kubernetes pod assignment guide cautions that inter-pod affinity and anti-affinity can slow scheduling substantially in large clusters. Required rules are appropriate when co-location violates fault tolerance, security, licensing, or quorum design. Preferred rules provide scoring influence while allowing progress. Keep selectors narrow and namespace scope deliberate; a broad selector can couple unrelated deployments and make scheduling behavior difficult to explain.

requiredDuringSchedulingIgnoredDuringExecution is evaluated when scheduling; it does not continuously evict pods if labels later change or topology becomes invalid. Anti-affinity therefore prevents new bad placements but is not a rebalancer. Required hostname anti-affinity is common for stateful replicas, yet the workload also needs enough eligible nodes for upgrades and failures. Include rolling-update surge, PodDisruptionBudget, volume zone, and node maintenance in the capacity calculation before calling the rule safe.

Govern labels, taints, and eligible domains

Placement policy is only as trustworthy as node metadata. Restrict who can set isolation labels and use protected label prefixes where security depends on them. Audit missing, unexpected, or changing zone, region, rack, accelerator, and node-pool labels. Taints filter candidates only when pods lack matching tolerations; they do not guarantee that tolerated pods select the intended pool. The taints and tolerations documentation recommends combining dedicated-node taints with affinity when exclusivity matters.

Autoscaled-to-zero domains are a subtle case. The scheduler discovers topology domains from existing eligible nodes and may not account for a zone with no nodes. A topology-aware node autoscaler can compensate, but support must be proven. Storage adds another hidden filter: a bound zonal volume may make only one domain eligible. Capture scheduler events and enable a controlled pending-pod test for each failure domain. The result should explain not merely that a pod is Pending, but which filter eliminated every node.

ScenarioExpected scheduler resultAvailability evidenceMisconfiguration signal
One node cordonedReplacement uses another nodeReady replicas stay above objectiveRequired rule leaves no candidate
One zone unavailableSurvivors run in remaining zones per policyService and quorum remain healthyminDomains or volume locality deadlock
Rolling update with surgeNew revision schedules before old removalNo availability dipHard anti-affinity blocks surge
Scale from two to many replicasSkew remains boundedCounts by domain convergeSelector omits new revision
Node pool scaled to zeroAutoscaler creates eligible capacityPending duration within objectiveDomain invisible to autoscaler

Observe placement and plan rebalancing

Export pod counts by workload revision, node, zone, and readiness. Alert on an invariant violation, not simply any skew. After scale-down or a repaired zone, Kubernetes does not automatically move healthy pods solely to improve topology spread. Decide whether natural rollout is sufficient or a descheduler and eviction policy is justified. Any rebalancing mechanism must respect disruption budgets and stateful recovery time; a cosmetically perfect distribution is not worth avoidable churn.

Use scheduler profiles cautiously. The scheduler configuration reference shows PodTopologySpread, InterPodAffinity, NodeAffinity, TaintToleration, and NodeResourcesFit as separate plugins in the scheduling path. Cluster defaults can provide a baseline, but workload-specific constraints should remain visible when they encode a service invariant. Document who owns global defaults and how application teams can detect that a default, rather than their manifest, changed placement.

Review placement changes with concrete arithmetic

For a six-replica web tier across three zones, a zone spread constraint with maxSkew: 1 should normally produce counts such as two, two, and two. If one zone disappears and only four replicas fit in the others, a hard minDomains: 3 policy can intentionally leave replacements Pending, while a softer policy may allow two and two to preserve service. The choice depends on whether running in fewer domains is safer than reduced capacity. Write that degraded decision in the workload record instead of discovering it during an outage.

For a three-member consensus system, required hostname anti-affinity prevents two members sharing one node, but zone policy needs different arithmetic. Three zones provide one member each; a temporary fourth member during replacement requires a fourth eligible node and may share a zone even though it must not share a hostname. If every rule requires unique zones, replacement cannot begin before old-member removal, increasing risk. Test the controller's actual membership and rollout sequence alongside scheduler constraints.

Make constraint review part of every replica, node-pool, and topology change. A scale decision can cross a satisfiability boundary even when the manifest is unchanged. Admission checks can catch selectors that do not match pod labels, unknown topology keys, and hard anti-affinity with replicas exceeding current domains. Runtime alerts should identify skew, but also the more urgent state: desired capacity that cannot schedule while a permitted relaxation or infrastructure repair is available.

Key takeaways

  • Translate availability objectives into replica and domain arithmetic before writing selectors.
  • Use topology spread for bounded distribution and anti-affinity for direct separation.
  • Reserve hard constraints for invariants that justify pending pods during shortage.
  • Treat node labels, taints, volume locality, and autoscaler awareness as part of the policy.
  • Test rollout, scale-out, node loss, zone loss, and recovery; placement does not automatically rebalance afterward.

Frequently asked questions

Can topology spread and anti-affinity be combined?

Yes. A stateful service might require members on different nodes while preferring even zone distribution. Model satisfiability because every additional hard filter shrinks the candidate set.

Does maxSkew one guarantee a pod in every zone?

Not by itself. Eligible domains, replica count, minDomains, node filters, taints, and unavailable zones all affect the calculation. Verify the actual domain set in the target cluster.

Will the scheduler rebalance existing pods?

No. These rules guide new scheduling. Rebalancing generally occurs through rollout, scaling, eviction, or a separately governed descheduler process.

Conclusion

Failure-domain placement is a service design expressed through scheduler constraints. Choose spread when the invariant concerns relative distribution and anti-affinity when it concerns direct separation. Ground either choice in accurate topology data, satisfiable degraded states, and scenario tests. The strongest manifest is the one that protects availability without turning a recoverable infrastructure shortage into a scheduling deadlock.

Continue with related articles

Kubernetes Deployments in Production: Safe Rollout

Kubernetes deployments in production need an explicit workload contract: readiness, resource requests, disruption behaviour, observability, and a rollout plan that protects live traffic.

Cloud & DevOps · 12 min read