In this lesson, you will learn how to optimize your cluster’s resource utilization by utilizing node affinity and pod topology spread constraints to prevent "Swiss cheese" fragmentation and improve bin packing efficiency.
Understanding Resource Fragmentation
Even with precise resource requests and a functioning Cluster Autoscaler, your cluster can suffer from resource fragmentation. This occurs when small, stranded chunks of CPU or memory remain on multiple nodes, but aren't large enough to accommodate new pods. Your cluster may appear to have sufficient aggregate capacity, but the scheduler cannot place a workload because the remaining resources are spread too thin across the infrastructure.
Optimizing with Bin Packing
To minimize wasted capacity, we use "bin packing"—the practice of filling nodes to capacity before spinning up new ones. However, aggressive bin packing can create reliability risks if all pods for a service land on a single failure domain. We balance these competing needs using two primary tools:
- Node Affinity: Use
requiredDuringSchedulingIgnoredDuringExecutionto force pods into specific node pools (e.g., high-memory instances) to ensure they are packed only where they are actually needed, preventing them from being scheduled onto mismatched hardware. - Pod Topology Spread Constraints: This is your primary mechanism for balancing bin packing with high availability. By setting
maxSkewandtopologyKey, you can tell Kubernetes how to distribute pods across zones or nodes.
Consider this configuration:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: "kubernetes.io/hostname"
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app: backend
By defining a low maxSkew, you prevent the scheduler from bunching pods onto a single node too aggressively, while still allowing the scheduler to pack them tightly across the available topology. When used alongside the Cluster Autoscaler, this forces the scheduler to exhaust existing node capacity before triggering new node provisions, effectively eliminating the "stranded resource" problem.
Key Takeaway: By carefully configuring topology spread constraints alongside node affinity, you can force the scheduler to pack nodes densely while maintaining the distribution requirements necessary for production reliability.