Skip to content
Documentation Background

Scaling & HPA

Kubernetes provides a layered approach to scaling: you can scale manually when you know your capacity needs, or let autoscalers respond to real-time demand. The two dimensions of scaling — Pods and nodes — can be combined for fully elastic infrastructure.


You can adjust the number of running Pods at any time using two methods. Unlike rolling updates, manual scaling is near-instantaneous.

Terminal window
kubectl scale deployment <name> --replicas=5

Edit spec.replicas in the manifest and re-apply:

spec:
replicas: 5 # updated from 3
Terminal window
kubectl apply -f deployment.yaml

This keeps your source YAML as the single source of truth, ensuring the live cluster never drifts from your declared state.

Terminal window
kubectl scale deployment <name> --replicas=0

All Pods are terminated but the Deployment and ReplicaSet objects remain. Scale back up at any time — useful for temporarily suspending a workload without losing its configuration.


For dynamic workloads, manually adjusting replicas is impractical. Kubernetes provides three autoscalers that react to real-time signals:

AutoscalerWhat it scalesDefault installedDisruption
HPANumber of Pods✅ YesNone — adds/removes Pods smoothly
Cluster Autoscaler (CA)Number of nodes✅ Yes (cloud)None for running Pods
VPACPU/memory per Pod❌ NoDisruptive — deletes and recreates Pods

The HPA automatically adds or removes Pods in a Deployment (or StatefulSet/ReplicaSet) based on observed metrics. It is the primary autoscaler for handling traffic fluctuations.

The HPA controller polls metrics at a configurable interval and computes the target replica count:

desired replicas = ceil(current replicas × (current metric / target metric))
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-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: 70 # scale out when average CPU > 70%
Terminal window
kubectl apply -f hpa.yaml
# Check HPA status and current metrics
kubectl get hpa
kubectl describe hpa my-app-hpa
Metric typeWhat it measuresExample use case
Resource (CPU/memory)Average utilisation across PodsWeb servers, APIs
PodsCustom per-pod metricRequests per second
ObjectMetric from another K8s objectQueue depth on a Service
ExternalMetric from outside the clusterMessage queue depth (SQS, Pub/Sub)
Terminal window
# Create an HPA targeting 70% CPU utilisation, scaling between 2–10 replicas
kubectl autoscale deployment <name> --cpu-percent=70 --min=2 --max=10
# Check current state
kubectl get hpa

The Cluster Autoscaler operates at the infrastructure level — it adds or removes nodes rather than Pods. It works in tandem with the HPA.

When the HPA requests more Pods than the current nodes can accommodate:

  1. HPA instructs the scheduler to add Pods
  2. Scheduler cannot place Pods — marks them as Pending
  3. CA detects Pending Pods and provisions a new node from the cloud provider
  4. Once the node joins the cluster, the scheduler assigns the Pending Pods to it

When demand drops:

  1. HPA scales down Pods
  2. Nodes become underutilised
  3. CA safely evicts any remaining Pods from the underutilised node, rescheduling them elsewhere
  4. CA terminates the now-empty node

The VPA adjusts the CPU and memory requests/limits on existing Pods rather than changing their count. It is less common in production for these reasons:

  • Not installed by default — requires manual installation
  • Disruptive — currently scales by deleting the existing Pod and replacing it with one that has updated resource settings. In-place resource updates are under active development upstream
  • Conflicts with HPA — running both on CPU/memory metrics simultaneously is not recommended without careful configuration
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: my-app-vpa
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
updatePolicy:
updateMode: Auto # Off | Initial | Recreate | Auto
Update modeBehaviour
OffRecommendations only — no automatic changes
InitialApply recommendations only at Pod creation
RecreateEvict and recreate Pods when adjustments are needed
AutoCurrently equivalent to Recreate (in-place update is not yet stable)

Combining the HPA and CA gives you fully elastic infrastructure — Pods scale horizontally with demand, and nodes scale to accommodate the Pods.

Traffic spike → HPA adds Pods → Nodes fill up → CA adds nodes → Pods schedule
Traffic drops → HPA removes Pods → Nodes underutilised → CA removes nodes

This is sometimes called multi-dimensional autoscaling and is the standard pattern for production cloud-native applications.


For workloads driven by external event sources (message queues, databases, HTTP request rate), the Kubernetes Event-Driven Autoscaler (KEDA) extends the HPA with custom scalers. It can scale from zero (no Pods when idle) to many, based on signals like:

  • Queue depth (RabbitMQ, Kafka, SQS, Azure Service Bus)
  • Cron schedule
  • Prometheus query result
  • HTTP request rate

KEDA is a CNCF project and a common complement to the built-in HPA in event-driven architectures. For multi-cluster scaling at enterprise scale, community projects like Karmada extend these capabilities across multiple Kubernetes clusters.