Definition
- HPA (Horizontal Pod Autoscaler) – changes the number of pod replicas based on observed load like CPU or custom metrics, scaling out and in.
- VPA (Vertical Pod Autoscaler) – adjusts the CPU and memory requests of individual pods by recreating them, scaling the size up and down.
- Cluster Autoscaler – adds or removes whole nodes from the cluster when pods cannot be scheduled or nodes sit idle.
- KEDA – an event-driven add-on that lets the HPA scale on external signals such as queue depth or Kafka lag rather than CPU.
- Layering – HPA/KEDA decide how many pods, VPA decides how big each pod is, and the Cluster Autoscaler decides how many machines exist to hold them.
Imagine the National Bank of India's processing floor. HPA is the policy of opening more identical counters when the queue grows and closing them when it shrinks. VPA is the policy of giving each individual clerk a bigger desk because the work needs more space than first allotted. The Cluster Autoscaler is the facilities team that leases another floor when there is no room for new counters. KEDA is the special rule for the back office: instead of watching how hard the clerks are sweating, it watches the height of the pending-forms pile and pulls in workers the instant the pile grows, even from zero.
Understanding the Concepts
What is the Horizontal Pod Autoscaler (HPA)?
The HPA operates on replica count. It watches a metric, classically average CPU utilization, and compares it to a target. If the current value exceeds the target, it scales out; if it falls below, it scales in.
# hpa.yaml for National Bank of India's Payment Service
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: payment-service-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: payment-service
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
Expected behavior:
Pods running at 90% CPU -> HPA scales to more replicas until avg drops to 60%
Pods running at 30% CPU -> HPA scales in to minReplicas (2)
Bound: never fewer than 2, never more than 20
What is the Vertical Pod Autoscaler (VPA)?
The VPA adjusts the CPU and memory requests of a single pod. It observes actual usage over time and recommends or automatically sets more appropriate requests.
# vpa.yaml for batch settlement service
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: settlement-vpa
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: settlement-service
updatePolicy:
updateMode: "Auto" # Recreates pods to apply new sizes
resourcePolicy:
containerPolicies:
- containerName: settlement
minAllowed:
cpu: "250m"
memory: "256Mi"
maxAllowed:
cpu: "2"
memory: "4Gi"
Expected behavior:
Settlement pod requests 500m CPU but only uses 200m -> VPA recommends 250m
Settlement pod requests 256Mi memory but uses 1Gi -> VPA recreates with 1Gi
Catch: pod is RESTARTED to apply new sizes (disruptive for latency-sensitive)
What is the Cluster Autoscaler?
The Cluster Autoscaler adds or removes whole nodes. When pods are pending because no node has room, it provisions more nodes. When nodes sit idle, it removes them.
Scenario at National Bank of India during festival season:
1. HPA wants 30 payment-service replicas
2. Current 5 nodes can only fit 20 pods
3. 10 pods are PENDING (unschedulable)
4. Cluster Autoscaler provisions 2 more nodes
5. Pending pods get scheduled on new nodes
6. After festival: traffic drops, HPA scales to 5 pods
7. 4 nodes are underutilized
8. Cluster Autoscaler removes 2 nodes, reschedules remaining pods
Can HPA and VPA be used together safely?
You must not have both HPA and VPA act on the same resource metric. If both target CPU, they fight: HPA adds replicas while VPA enlarges each pod, and the two oscillate.
package com.bank.scaling;
/**
* WRONG: Both HPA and VPA target CPU.
* HPA sees high CPU -> adds replicas
* VPA sees high CPU -> enlarges pods (restarts them)
* Both fight each other, pods restart constantly.
*
* CORRECT: Separate their concerns.
* HPA targets CPU (or custom request-rate metric)
* VPA targets memory (in recommendation-only mode)
* No overlap, no oscillation.
*/
public class AutoscalerDecisionGuide {
// This is a documentation class showing the safe pattern.
}
Safe pattern:
HPA -> scales on CPU or request-rate (horizontal)
VPA -> manages memory in recommendation-only mode (vertical)
Never point both at CPU.
Unsafe pattern:
HPA -> CPU target 60%
VPA -> CPU target auto
Result: oscillation, constant pod restarts, thrashing
When do you use KEDA?
KEDA addresses workloads where CPU is a poor proxy for how much work is waiting. A Kafka consumer can sit at low CPU while a huge backlog builds.
# keda-scaledobject.yaml for settlement worker
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: settlement-worker-scaler
spec:
scaleTargetRef:
name: settlement-worker
pollingInterval: 10
cooldownPeriod: 300
minReplicaCount: 0 # Scale to zero when idle
maxReplicaCount: 50
triggers:
- type: kafka
metadata:
bootstrapServers: kafka:9092
consumerGroup: settlement-group
topic: settlement-events
lagThreshold: "100"
Expected behavior:
No messages in settlement-events -> 0 pods (cost savings)
500 messages arrive at market close -> KEDA scales to 5 pods instantly
Backlog drained -> cool down -> scale back to 0
CPU-based HPA would not react because idle consumer has low CPU.
KEDA watches the actual queue depth.
How is HPA different from VPA and KEDA? (comparison table)
| Aspect | HPA | VPA | KEDA |
|---|---|---|---|
| What it changes | Number of pods | Size of each pod | Number of pods (event-driven) |
| Scaling axis | Horizontal (out/in) | Vertical (up/down) | Horizontal (out/in) |
| Default metric | CPU, memory | CPU, memory usage | Queue depth, Kafka lag |
| Scale to zero | No (minReplicas >= 1) | No | Yes |
| Pod disruption | None (adds/removes pods) | Restarts pods | None (adds/removes pods) |
| Best for | Stateless request-serving | Batch, background jobs | Bursty, queue-based workloads |
How do these tools layer together?
These tools are complementary, not competing. HPA and KEDA decide how many pods, VPA decides how big each pod is, and the Cluster Autoscaler decides how many machines exist to hold them.
┌─────────────────────────────────────────────┐
│ Application Layer (Pods) │
│ │
│ HPA: "I need 10 payment-service pods" │
│ KEDA: "I need 5 settlement-worker pods" │
│ VPA: "Each pod needs 512Mi memory" │
└──────────────────────┬──────────────────────┘
│
┌──────────────────────┴──────────────────────┐
│ Infrastructure Layer (Nodes) │
│ │
│ Cluster Autoscaler: "I need 7 nodes to │
│ fit all 15 pods at their requested sizes" │
└─────────────────────────────────────────────┘
What should a senior engineer know?
Aggregate size is a direct throughput lever. Use HPA for synchronous request-serving services, KEDA for bursty queue-based workloads, VPA for right-sizing background jobs, and the Cluster Autoscaler to ensure nodes exist for all of them. Never point HPA and VPA at the same metric.
Visual Overview
Kubernetes Autoscaling Layers:
┌──────────────────────────────────────────┐
│ HPA / KEDA │
│ "How many pods?" │
│ HPA: CPU/memory/custom metrics │
│ KEDA: Kafka lag, queue depth, events │
└────────────────────┬─────────────────────┘
│
┌────────────────────┴─────────────────────┐
│ VPA │
│ "How big is each pod?" │
│ Adjusts CPU/memory requests │
│ Restarts pods to apply │
└────────────────────┬─────────────────────┘
│
┌────────────────────┴─────────────────────┐
│ CLUSTER AUTOSCALER │
│ "How many nodes?" │
│ Adds nodes when pods are pending │
│ Removes idle nodes to save cost │
└──────────────────────────────────────────┘
Key Takeaway
These are three complementary Kubernetes autoscalers that operate on completely different axes, plus an event-driven add-on. The Horizontal Pod Autoscaler changes the number of pod replicas based on a load metric like CPU. The Vertical Pod Autoscaler adjusts the CPU and memory requests of each individual pod. The Cluster Autoscaler adds or removes whole nodes when pods cannot be scheduled or nodes sit idle.
On the key question of whether HPA and VPA can be used together, the answer is yes but only if they do not act on the same resource metric. If both target CPU, they fight: the HPA tries to fix high CPU by adding replicas while the VPA tries to fix the same high CPU by enlarging each pod, and the two oscillate. The safe pattern is to let the HPA own CPU and let the VPA manage memory in recommendation-only mode.
KEDA is what you reach for when CPU is a poor proxy for how much work is waiting. At National Bank of India, the settlement worker sits idle most of the day and is flooded at market close. Switching from CPU-based scaling to KEDA on queue depth means it sits at zero pods when quiet and shoots up instantly when the backlog appears.
Remember one sentence: HPA and KEDA decide how many pods, VPA decides how big each pod is, Cluster Autoscaler decides how many nodes exist to hold them, and never point HPA and VPA at the same metric.
---