Autoscaling is one of the few Kubernetes topics that appears, in some form, across almost every certification on the KubeAstronaut path — the KCNA tests it as a concept, the CKAD expects you to scale applications, and the CKA expects you to configure and troubleshoot a Horizontal Pod Autoscaler under time pressure. It’s also one of the most misunderstood: candidates conflate the three autoscalers, forget that they depend on the metrics pipeline, or don’t realize that a Horizontal Pod Autoscaler is useless without CPU/memory requests set on the Pods it targets.
This guide untangles the three layers of Kubernetes autoscaling — Horizontal Pod Autoscaler (HPA), Vertical Pod Autoscaler (VPA), and Cluster Autoscaler (CA) — and shows how they fit together. It’s written for the practitioner working toward the five CNCF exams that make up the KubeAstronaut title, so every concept is grounded in the kubectl commands and manifests you’ll be graded on. If you’re mapping your overall study plan, the KubeAstronaut curriculum map shows exactly where scaling sits in each exam’s domains.
The Three Layers of Autoscaling
Kubernetes solves “not enough capacity” at three different levels, and the exam expects you to know which tool operates at which layer.
| Autoscaler | Scales | Trigger | Exam relevance |
|---|---|---|---|
| Horizontal Pod Autoscaler (HPA) | Number of Pod replicas | Metrics (CPU, memory, custom) | CKA, CKAD, KCNA |
| Vertical Pod Autoscaler (VPA) | CPU/memory requests of Pods | Historical usage | KCNA concept, add-on |
| Cluster Autoscaler (CA) | Number of nodes | Unschedulable Pods | KCNA, CKA concept |
The mental model: the HPA adds more Pods when your existing Pods are busy, the VPA makes each Pod bigger or smaller, and the Cluster Autoscaler adds more nodes when Pods can’t be scheduled anywhere. They operate on different objects and solve different problems, and — with one important caveat — they compose.
Prerequisite: The Metrics Pipeline and Resource Requests
Before any autoscaler can act, two things must be true. This is the single most common source of “my HPA shows <unknown>” confusion, and the exam tests it directly.
1. metrics-server must be installed
The HPA reads CPU and memory usage from the Metrics API (metrics.k8s.io), which is served by metrics-server. On a fresh cluster it isn’t installed, so kubectl top and the HPA both fail:
kubectl top nodes # error if metrics-server is missing
kubectl top pods
kubectl get apiservices | grep metrics # v1beta1.metrics.k8s.io should be Available
Installing it is a one-liner, and on kubeadm/lab clusters you often need the --kubelet-insecure-tls flag because the kubelet’s serving cert isn’t signed by the cluster CA:
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
The relationship between metrics-server and the HPA is covered further in the cluster and application monitoring guide; for autoscaling, just remember: no metrics-server, no HPA.
2. Pods must declare resource requests
The HPA calculates utilization as a percentage of the Pod’s request, not its limit and not the node capacity. A Deployment with no CPU requests gives the HPA nothing to divide by, so it reports <unknown> and never scales:
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
If you take one thing from this section: requests are the denominator of the HPA formula. The resource management guide goes deeper on requests, limits, and quotas — all of which underpin autoscaling.
The Horizontal Pod Autoscaler in Depth
The HPA is a control-loop controller that periodically (every 15 seconds by default) compares observed metrics against a target and adjusts the replica count of a scalable workload — a Deployment, ReplicaSet, or StatefulSet.
The scaling formula
The core calculation is simple and worth memorizing:
desiredReplicas = ceil( currentReplicas × ( currentMetricValue / desiredMetricValue ) )
If 4 replicas are averaging 80% CPU and your target is 50%, the HPA wants ceil(4 × 80/50) = ceil(6.4) = 7 replicas. Understanding this formula lets you answer “how many replicas will it scale to?” questions instantly.
Creating an HPA
The fastest way — the one to use in the exam — is the imperative kubectl autoscale:
kubectl autoscale deployment web --cpu-percent=50 --min=2 --max=10
kubectl get hpa web --watch
Under the hood that produces an autoscaling/v2 object. The declarative form gives you multiple metrics and scaling behavior:
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: 50
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 70
When multiple metrics are specified, the HPA computes a desired replica count for each and picks the highest — it scales to satisfy the most demanding metric.
Scaling behavior and stabilization
A frequent real-world (and exam) concern is flapping — the HPA scaling up and down rapidly as metrics oscillate. The autoscaling/v2 API exposes a behavior block to control this. By default there’s a 300-second stabilization window on scale-down (so it waits before removing Pods) and none on scale-up (so it reacts quickly to load):
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 50
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Pods
value: 4
periodSeconds: 60
Custom and external metrics
Beyond CPU and memory, the HPA can scale on custom metrics (application metrics exposed via the custom.metrics.k8s.io API, e.g. requests per second) and external metrics (from outside the cluster, e.g. queue depth). These require an adapter such as Prometheus Adapter. For KCNA you should recognize that this is possible; for hands-on exams, CPU/memory utilization is what you’ll configure.
The Vertical Pod Autoscaler
The VPA takes the opposite approach: instead of adding replicas, it right-sizes the CPU and memory requests of your Pods based on observed usage. It’s an add-on (not built into core Kubernetes) with three components — a Recommender, an Updater, and an Admission Controller.
The VPA runs in one of several modes:
| Mode | Behavior |
|---|---|
Off | Only produces recommendations; makes no changes |
Initial | Sets requests only at Pod creation |
Auto / Recreate | Evicts and recreates Pods to apply new requests |
The exam-critical caveat: classic VPA in Auto mode must evict and recreate Pods to change their requests, because a Pod’s resources were traditionally immutable while running. (In-place resource resize is a newer capability, but for exam purposes assume VPA restarts Pods.) This is why VPA suits workloads that tolerate restarts — batch jobs, stateless services — and why the next rule matters so much.
Do not run the VPA and the HPA on the same CPU/memory metric for the same workload. They fight: the HPA wants to add replicas when CPU is high, while the VPA wants to raise the CPU request, changing the very denominator the HPA divides by. The supported pattern is HPA on custom/external metrics with VPA on CPU/memory, or simply pick one. When a scenario describes both operating on CPU, the correct answer is that they conflict.
The Cluster Autoscaler
The HPA and VPA both assume there’s somewhere to put Pods. When a new Pod can’t be scheduled because no node has room, it sits in Pending — and that’s the signal the Cluster Autoscaler watches for.
The Cluster Autoscaler:
- Scales up by adding nodes when Pods are
Pendingdue to insufficient resources (it talks to the cloud provider’s node group / autoscaling group). - Scales down by draining and removing nodes that have been underutilized for a sustained period and whose Pods can be rescheduled elsewhere.
Two facts the exam checks. First, the Cluster Autoscaler reacts to unschedulable Pods, not to raw CPU metrics — so it depends on Pods having realistic requests (a Pod requesting more than any node offers will stay Pending forever and can’t trigger a useful scale-up). Second, it respects scheduling constraints: PodDisruptionBudgets can block a scale-down that would violate availability, and Pods without a controller (bare Pods) or with local storage may prevent a node from being removed.
On modern managed platforms you’ll also hear about Karpenter, which provisions right-sized nodes directly rather than scaling fixed node groups. For the CNCF exams, the Cluster Autoscaler is the reference implementation to know.
How the Three Compose
Put together, autoscaling is a cascade:
- Load rises → Pods’ CPU utilization exceeds the HPA target.
- HPA increases replica count.
- New replicas can’t be scheduled (no room) → they go
Pending. - Cluster Autoscaler sees unschedulable Pods and adds a node.
- The
PendingPods schedule onto the new node. - Load falls → HPA scales replicas down, Cluster Autoscaler later removes the now-idle node.
The VPA operates orthogonally, tuning the size of individual Pods over time. This cascade is a favourite KCNA conceptual question: “A Deployment is scaled up by its HPA but new Pods stay Pending — what’s missing?” The answer is node capacity, provided by the Cluster Autoscaler. See the KCNA scheduling and resource management guide and Kubernetes architecture fundamentals for how the scheduler and control loops make this work.
Troubleshooting Autoscaling
When an HPA isn’t behaving, work through it methodically — this is exactly the kind of task a CKA question sets up:
kubectl get hpa
kubectl describe hpa web # read the Conditions and Events
kubectl top pods # confirm metrics are flowing
kubectl get deployment web # confirm requests are set
| Symptom | Likely cause | Fix |
|---|---|---|
TARGETS shows <unknown> | metrics-server missing or Pods have no requests | Install metrics-server; add CPU/memory requests |
| HPA never scales up | Target too high, or metric never exceeds it | Lower target, verify load reaches the Pods |
Scales up but Pods stay Pending | No node capacity | Cluster Autoscaler / add nodes |
| Rapid up/down flapping | No stabilization window | Tune behavior.scaleDown.stabilizationWindowSeconds |
| HPA and VPA both changing CPU | They conflict on the same metric | Split metrics or disable one |
The kubectl describe hpa output is your best friend — its Conditions (AbleToScale, ScalingActive, ScalingLimited) tell you precisely why it did or didn’t act.
Autoscaling Across the KubeAstronaut Exams
Because the same concept is graded differently on each exam, tailor your practice:
- KCNA — conceptual: know what each autoscaler does, that the HPA needs metrics-server, and how the HPA/CA cascade produces new nodes. Multiple-choice recall.
- CKAD — hands-on:
kubectl autoscalea Deployment, set sensible requests, verify withkubectl get hpa. Application-focused. Pair with the Deployments and rolling updates guide. - CKA — hands-on and troubleshooting: configure an HPA, diagnose why it isn’t scaling, understand the interaction with scheduling and node capacity.
- CKS / KCSA — autoscaling is not a primary topic, but resource requests/limits (which autoscaling depends on) matter for denial-of-service protection.
Knowing which depth an exam wants stops you from over-studying custom-metrics adapters for a KCNA question or under-practicing the imperative command for the CKAD.
Practice Autoscaling Under Exam Conditions
Autoscaling is a topic where reading the docs feels sufficient but the hands-on tasks expose the gaps — a forgotten requests block, an uninstalled metrics-server, a target that never triggers. The only cure is doing it under timed, exam-style conditions until the workflow (install metrics-server → set requests → kubectl autoscale → verify → troubleshoot) becomes reflex.
The KubeAstronaut Mock Exam Bundle covers all five CNCF exams — KCNA, KCSA, CKA, CKAD, and CKS — with realistic, explained questions, so you can drill autoscaling in the exact form each certification tests it. If you’re focused on a single exam first, the CKA mock exams and CKAD mock exams target the hands-on scaling tasks, while the KCNA mock exams reinforce the concepts. Still deciding whether to chase the full title? The is KubeAstronaut worth it breakdown lays out the cost and career math.
Frequently Asked Questions
Why does my HPA show <unknown> for the current metric?
Two causes cover almost every case: metrics-server isn’t installed (so kubectl top also fails), or the target Pods don’t declare CPU/memory requests, which the HPA needs as the denominator for utilization. Install metrics-server and add requests, and the value will populate within a minute.
What’s the difference between the HPA and the VPA?
The Horizontal Pod Autoscaler changes the number of Pod replicas based on live metrics; the Vertical Pod Autoscaler changes the size (CPU/memory requests) of individual Pods based on historical usage. HPA is built into Kubernetes; VPA is an add-on. Avoid running both on the same CPU/memory metric for one workload — they conflict.
Does the Horizontal Pod Autoscaler add nodes?
No. The HPA only adds Pod replicas. If those replicas can’t be scheduled because nodes are full, they stay Pending — adding nodes is the Cluster Autoscaler’s job. The two work together: HPA adds Pods, Cluster Autoscaler adds capacity for them.
How do I create an HPA quickly in the exam?
Use the imperative command: kubectl autoscale deployment <name> --cpu-percent=50 --min=2 --max=10. It’s faster than writing a manifest and produces a valid autoscaling/v2 HPA. Verify with kubectl get hpa and kubectl describe hpa <name>.
Can the HPA scale on memory or custom metrics?
Yes. The autoscaling/v2 API supports CPU, memory, custom metrics (via the custom.metrics.k8s.io API), and external metrics. With multiple metrics, the HPA computes the desired replicas for each and uses the highest. Custom/external metrics require an adapter such as the Prometheus Adapter.
Why won’t the Cluster Autoscaler remove a node?
Common blockers include PodDisruptionBudgets that would be violated, Pods not backed by a controller (bare Pods), Pods using local storage, or nodes that aren’t underutilized long enough. The Cluster Autoscaler only removes a node when its Pods can be safely rescheduled elsewhere.
Autoscaling ties together metrics, requests, scheduling, and capacity — master it once and it pays off on every exam in the KubeAstronaut path. Drill the hands-on workflow with realistic mock exams, then use kubectl describe hpa as your default debugging move.