Effective pod scheduling is foundational to Kubernetes infrastructure performance, resilience, and cost efficiency. According to the 2025 Kubernetes Benchmark Report, the average CPU utilization is just 10% and memory utilization is 23% across Kubernetes clusters.
Improper pod distribution can decrease resilience beyond resource efficiency. The Kubernetes Failure Stories database documents numerous incidents in which the inadequate spread of workloads led to cascading failures.
This comprehensive guide focuses on three powerful pod scheduling mechanisms in Kubernetes:
- pod affinity,
- pod anti-affinity,
- topology spread constraints.
Each mechanism serves distinct purposes while sharing some overlapping functionality. Understanding their nuances, implementation patterns, and trade-offs is essential for designing high-performance, resilient, and cost-efficient Kubernetes architectures.
Core scheduling mechanisms in Kubernetes
Before diving into implementation specifics, let’s clarify the fundamental differences between these three scheduling mechanisms:
- Pod affinity – Attracts pods to nodes where other pods with specific labels are running
- Pod anti-affinity – Repels pods from nodes where other pods with specific labels are running
- Topology spread constraints – Distributes pods evenly across topology domains based on configurable parameters
While all three mechanisms influence pod placement, they operate on different principles and have distinct advantages in specific scenarios.
Pod affinity and anti-affinity are binary in nature—pods are either attracted to or repelled from specific nodes. In contrast, topology spread constraints work on distribution ratios across defined topology domains.
Pod affinity: attraction forces
Pod affinity enables you to attract pods to nodes based on existing pod placements, which is valuable for co-locating related services to minimize latency or maximize resource sharing.
Implementation
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
replicas: 3
template:
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- cache
topologyKey: kubernetes.io/hostnameThis configuration ensures that frontend pods are scheduled on nodes where cache pods are already running.
Hard vs. soft affinity
Kubernetes supports two types of affinity rules:
- Required (requiredDuringSchedulingIgnoredDuringExecution) – Hard constraint that must be satisfied for scheduling to succeed
- Preferred (preferredDuringSchedulingIgnoredDuringExecution) – Soft constraint with a weight factor indicating preference level
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- cache
topologyKey: kubernetes.io/hostnameBest practices for pod affinity
- Tightly-coupled microservices – Co-locate services with high inter-communication volume
- Data locality – Place compute pods near data pods to minimize data transfer
- Hardware acceleration sharing – Group pods that share specialized hardware
- License compliance – Some software licenses require specific application components to run on the same physical machine
When to avoid pod affinity
- Large-scale deployments – Pod affinity can significantly reduce scheduling options and increase scheduling latency
- Resilience-critical applications – Pod affinity can concentrate failure risks
- When resource sharing isn’t necessary – Unnecessary co-location can lead to resource contention
Pod anti-affinity: repulsion forces
Pod anti-affinity prevents pods from co-locating with specific other pods, which is essential for spreading workloads across failure domains and ensuring service availability during infrastructure disruptions.
Implementation
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
spec:
replicas: 3
template:
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web-server
topologyKey: kubernetes.io/hostnameThis deployment ensures no two web-server pods will run on the same node, maximizing availability during node failures.
Topology key significance
The topologyKey field defines the domain level for the anti-affinity rule:
- kubernetes.io/hostname – Node-level separation
- topology.kubernetes.io/zone – Availability zone-level separation
- topology.kubernetes.io/region – Region-level separation
For mission-critical applications, multi-level anti-affinity provides comprehensive resilience:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- critical-service
topologyKey: kubernetes.io/hostname
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- critical-service
topologyKey: topology.kubernetes.io/zoneBest practices for pod anti-affinity
- Stateful application replicas – Distribute database pods across nodes and zones
- Highly available services – Ensure replicas don’t share failure domains
- Resource-intensive applications – Prevent resource contention by spreading heavy workloads
- Services with shared-fate risks – Separate components that could cascade-fail together
When to avoid pod anti-affinity
- Small or constrained clusters – Hard anti-affinity can prevent scheduling if insufficient diverse nodes exist
- Applications with colocation benefits – Services that benefit from proximity will suffer
- When other spreading mechanisms are more appropriate – For large-scale distribution, topology spread constraints often offer more flexibility
Topology spread constraints: balanced distribution
Topology spread constraints represent Kubernetes’ most sophisticated pod distribution mechanism, enabling fine-grained control over pod distribution ratios across topology domains.
Implementation
apiVersion: apps/v1
kind: Deployment
metadata:
name: distributed-service
spec:
replicas: 9
template:
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: distributed-service
- maxSkew: 2
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app: distributed-serviceThis configuration achieves two goals:
- Even distribution across availability zones (maximum 1-pod difference between zones)
- Relatively even distribution across nodes (maximum 2-pod difference between nodes) with flexibility
Key parameters
- maxSkew – Defines the maximum difference between the number of pods in the topology domain
- topologyKey – Determines the topology domain for distribution (hostname, zone, region, etc.)
- whenUnsatisfiable – Specifies behavior when constraints cannot be satisfied:
- DoNotSchedule – Hard constraint that blocks scheduling
- ScheduleAnyway – Soft constraint that allows scheduling despite the imbalance
Multi-level constraints
Topology spread constraints shine in their ability to enforce distribution at multiple levels simultaneously:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/region
whenUnsatisfiable: DoNotSchedule
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
- maxSkew: 2
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnywayThis multi-tiered approach ensures balanced distribution across regions, zones, and nodes with appropriate strictness at each level.
Best practices for topology spread constraints
- Large-scale distributed applications – Services that benefit from balanced global distribution
- Global microservices – Ensure consistent response times across regions
- Multi-tenant services – Distribute tenant workloads evenly across the infrastructure
- Applications with flexible replica counts – Dynamically scaled applications maintain balance during scaling events
When to avoid topology spread constraints
- Simple distribution needs – For basic separation, pod anti-affinity may be simpler
- Very small deployments – For two or three replicas, spread constraints add unnecessary complexity
- Highly specialized workloads – When precise control over individual pod placement is needed
Comparative analysis: when to use each mechanism
These scheduling mechanisms can sometimes achieve similar outcomes, so knowing when to use each is crucial:

Key decision factors
- Scale of deployment:
- Small (2-3 replicas) – Pod anti-affinity often suffices
- Medium (4-20 replicas) – Mix of anti-affinity and spread constraints
- Large (20+ replicas) – Topology spread constraints provide better flexibility
- Criticality of service:
- Mission-critical – Multi-level anti-affinity or spread constraints with DoNotSchedule
- Important but flexible – Spread constraints with mixed satisfiability settings
- Non-critical – Soft affinity/anti-affinity rules
- Cluster characteristics:
- Small clusters – Careful with hard constraints that might prevent scheduling
- Large, diverse clusters – You can leverage stricter topology controls
- Multi-zone/region – Multi-level constraints are essential
Functional equivalence cases
In some scenarios, different mechanisms can achieve similar outcomes:
# Hard anti-affinity at hostname level
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web-server
topologyKey: kubernetes.io/hostnameIs functionally similar to
# Topology spread with maxSkew=1 at hostname level
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: web-serverHowever, as replicas increase, topology spread constraints provide more flexibility and controlled distribution.
Conclusion
Mastering Kubernetes pod affinity, anti-affinity, and topology spread constraints enables your organization to build resilient, efficient, and cost-effective infrastructure. When properly implemented, these mechanisms provide the foundation for high-performance applications that maintain availability through infrastructure disruptions while optimizing resource utilization.
The key takeaway from our exploration is to use the right tool for the job:
- Pod affinity for co-location and performance optimization
- Pod anti-affinity for basic separation and critical service resilience
- Topology spread constraints for flexible, multi-level distribution at scale
By applying the principles and patterns outlined in this guide, your Kubernetes infrastructure can join the ranks of these high-performing environments.



