In this lesson, you will learn how to configure a Horizontal Pod Autoscaler (HPA) to scale your deployments based on both CPU and memory utilization concurrently, ensuring your application remains stable under different types of load.
Why Combine Metrics?
In production environments, a workload might be CPU-intensive during request processing but memory-intensive due to large data caching or batch jobs. If you only scale on CPU, your pod might crash due to an Out-of-Memory (OOM) error before the HPA has a chance to trigger a scale-out. Conversely, scaling only on memory might leave you with insufficient CPU headroom during traffic spikes. By defining multiple metrics, Kubernetes triggers scaling as soon as either threshold is breached.
Configuring the Multi-Metric HPA
To scale based on multiple metrics, we include them within the metrics array in our HPA manifest. The HPA controller evaluates all metrics and selects the one that suggests the highest number of replicas, prioritizing the most aggressive scaling requirement.
Here is an example of an HPA configured for both 50% CPU and 60% memory utilization:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: robust-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 60
Understanding the Behavior
When you apply this configuration, the Kubernetes HPA controller monitors the metrics provided by the Metrics Server. If your application spikes to 70% CPU usage, the HPA will increase the replica count even if memory usage is low. If, at another time, your memory usage climbs to 75% while CPU remains stable, the HPA will again trigger a scale-out. This provides a "safety net" that guards against both processing bottlenecks and memory pressure simultaneously.
Key Takeaway: Combining multiple metrics in an HPA allows you to create a proactive scaling strategy that protects your services from diverse resource bottlenecks, ensuring high availability regardless of whether your app is CPU-bound or memory-bound.