Autoscaling Basics
This page is a hands-on intro to Kubernetes autoscaling: scaling pods out (horizontal), scaling pods up (vertical), and scaling nodes (cluster).
Search across all documentation pages
This page is a hands-on intro to Kubernetes autoscaling: scaling pods out (horizontal), scaling pods up (vertical), and scaling nodes (cluster).
Each example builds on realistic manifests and kubectl commands you can run against any conformant cluster.
kubectl configured against it.kubectl top).Quick check that metrics are flowing:
kubectl top nodes
kubectl top pods -AAutoscaling and scheduling both read requests, so set them on every container.
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
memory: 512Mirequests is what the scheduler reserves and what the HPA measures against.250m means a quarter of a CPU core.Before automating, scale by hand to confirm the workload spreads.
kubectl scale deployment web --replicas=4
kubectl get pods -l app=webscale sets the replica count directly on the Deployment.Let the HPA hold average CPU near a target.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60averageUtilization: 60 targets 60% of each pod's CPU request.minReplicas and maxReplicas.autoscaling/v2 is the stable API for multi-metric and custom metrics.Observe decisions rather than guessing.
kubectl get hpa web --watch
kubectl describe hpa webget hpa shows current versus target and the live replica count.describe prints events explaining each scale action.<unknown> metric usually means metrics-server is missing or requests are unset.Prove the loop end to end.
kubectl run load --rm -it --image=busybox:1.36 -- \
/bin/sh -c "while true; do wget -q -O- http://web; done"web Service to push CPU up.Cluster scaling reacts to pods that cannot be placed.
kubectl get pods -A --field-selector=status.phase=Pending
kubectl describe pod <pending-pod>Pending with an Insufficient cpu/memory event means the cluster is full.Let the VPA suggest better requests without changing anything yet.
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: web
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: web
updatePolicy:
updateMode: "Off"updateMode: "Off" produces recommendations only, applying nothing.kubectl describe vpa web.Move beyond CPU to requests-per-second or queue depth.
metrics:
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: "100"type: Pods averages a per-pod metric across replicas.AverageValue compares an absolute number, not a percentage.Stop flapping by slowing down scale-down.
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 50
periodSeconds: 60Guard against too many pods leaving at once.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: webminAvailable: 2 keeps at least two pods serving during consolidation.Make sure the HPA maximum is something your cluster can actually place.
kubectl describe hpa web | grep -i replicas
kubectl get nodes -o custom-columns=NAME:.metadata.name,CPU:.status.allocatable.cpumaxReplicas times the per-pod request against total allocatable CPU.Pending during a spike.Once an HPA manages a Deployment, stop scaling it by hand.
kubectl get deployment web -o jsonpath='{.spec.replicas}{"\n"}'
kubectl get hpa web -o jsonpath='{.status.desiredReplicas}{"\n"}'kubectl scale changes.minReplicas and maxReplicas instead.Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).
Reviewed by Chris St. John·Last updated Jul 19, 2026