Amazon EKS — HPA and VPA
HPA (Horizontal Pod Autoscaler) scales the number of pod replicas. VPA (Vertical Pod Autoscaler) adjusts the resource requests of individual pods. Both are essential for efficient scaling on EKS.
Metrics Server
Both HPA and VPA require the Metrics Server:
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
# Verify
kubectl get pods -n kube-system -l k8s-app=metrics-server
kubectl top nodes
kubectl top pods
Horizontal Pod Autoscaler (HPA)
Basic HPA (CPU-Based)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-app-hpa
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-app
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleUp:
stabilizationWindowSeconds: 60
policies:
- type: Pods
value: 4
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 10
periodSeconds: 60
HPA with Custom Metrics (Prometheus Adapter)
Install Prometheus Adapter:
helm install prometheus-adapter prometheus-community/prometheus-adapter \
--namespace monitoring \
--set prometheus.url=http://kube-prometheus-kube-prome-prometheus.monitoring.svc \
--set prometheus.port=9090
HPA using custom metric:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: queue-processor-hpa
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: queue-processor
minReplicas: 1
maxReplicas: 50
metrics:
- type: Pods
pods:
metric:
name: messages_in_queue
target:
type: AverageValue
averageValue: "10"
HPA Commands
# Create HPA imperatively
kubectl autoscale deployment web-app -n production --min=2 --max=20 --cpu-percent=70
# Check HPA status
kubectl get hpa -n production
kubectl describe hpa web-app-hpa -n production
# Watch scaling events
kubectl get hpa -w
Vertical Pod Autoscaler (VPA)
VPA analyzes pod resource usage and recommends (or auto-applies) optimal CPU and memory requests.
Install VPA
git clone https://github.com/kubernetes/autoscaler.git
cd autoscaler/vertical-pod-autoscaler
./hack/vpa-up.sh
VPA Configuration
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: web-app-vpa
namespace: production
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: web-app
updatePolicy:
updateMode: "Off" # Recommend only — don't auto-apply
resourcePolicy:
containerPolicies:
- containerName: app
minAllowed:
cpu: 50m
memory: 64Mi
maxAllowed:
cpu: 2
memory: 4Gi
VPA Update Modes
| Mode | Behavior | Use Case |
|---|---|---|
Off |
Recommendations only — no changes | Production review |
Initial |
Set requests at pod creation only | New deployments |
Auto |
Update requests on running pods (restarts pod) | Non-critical workloads |
Check Recommendations
kubectl describe vpa web-app-vpa -n production
Output:
Recommendation:
Container Recommendations:
Container Name: app
Lower Bound: Cpu: 50m, Memory: 128Mi
Target: Cpu: 250m, Memory: 512Mi # Use this
Upper Bound: Cpu: 1, Memory: 2Gi
Uncapped Target: Cpu: 250m, Memory: 512Mi
HPA + VPA Interaction
| Scenario | Works? | Notes |
|---|---|---|
| HPA on CPU + VPA on memory | Yes | Different metrics, no conflict |
| HPA on CPU + VPA on CPU | No | Both try to control CPU — conflicts |
| HPA on custom metric + VPA on CPU/memory | Yes | Different scopes |
VPA in Off mode + HPA |
Yes | VPA only recommends, doesn’t interfere |
Best practice: Use VPA in
Offmode for recommendations, then manually update Deployment resource requests. Use HPA for scaling replicas.
Scaling Behavior Tuning
Aggressive Scale-Up (Latency-Sensitive)
behavior:
scaleUp:
stabilizationWindowSeconds: 0 # Scale up immediately
policies:
- type: Percent
value: 100 # Double replicas per period
periodSeconds: 15
Conservative Scale-Down (Cost vs Stability)
behavior:
scaleDown:
stabilizationWindowSeconds: 600 # Wait 10 min before scale down
policies:
- type: Pods
value: 1 # Remove max 1 pod per period
periodSeconds: 120
Best Practices
- Always set resource requests — HPA uses requests for utilization calculation
- Use
behaviorto control flapping — stabilization windows prevent rapid scale up/down - Use VPA in
Offmode to right-size, then apply recommendations manually - Don’t use HPA and VPA on the same metric — they’ll fight each other
- Start conservative — scale down slowly, scale up aggressively
- Monitor HPA events —
kubectl describe hpashows scaling decisions