Back to Blog

Kubernetes Autoscaling for the KubeAstronaut Path: HPA, VPA & Cluster Autoscaler (CKA, CKAD & KCNA)

A practitioner's guide to Kubernetes autoscaling for the CNCF exams on the KubeAstronaut path. Understand the Horizontal Pod Autoscaler, Vertical Pod Autoscaler, and Cluster Autoscaler — how they work, how they interact, why they depend on metrics-server and resource requests — with kubectl commands, manifests, and exam-style scenarios.

By Sailor Team , July 29, 2026

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.

AutoscalerScalesTriggerExam relevance
Horizontal Pod Autoscaler (HPA)Number of Pod replicasMetrics (CPU, memory, custom)CKA, CKAD, KCNA
Vertical Pod Autoscaler (VPA)CPU/memory requests of PodsHistorical usageKCNA concept, add-on
Cluster Autoscaler (CA)Number of nodesUnschedulable PodsKCNA, 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:

ModeBehavior
OffOnly produces recommendations; makes no changes
InitialSets requests only at Pod creation
Auto / RecreateEvicts 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 Pending due 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:

  1. Load rises → Pods’ CPU utilization exceeds the HPA target.
  2. HPA increases replica count.
  3. New replicas can’t be scheduled (no room) → they go Pending.
  4. Cluster Autoscaler sees unschedulable Pods and adds a node.
  5. The Pending Pods schedule onto the new node.
  6. 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
SymptomLikely causeFix
TARGETS shows <unknown>metrics-server missing or Pods have no requestsInstall metrics-server; add CPU/memory requests
HPA never scales upTarget too high, or metric never exceeds itLower target, verify load reaches the Pods
Scales up but Pods stay PendingNo node capacityCluster Autoscaler / add nodes
Rapid up/down flappingNo stabilization windowTune behavior.scaleDown.stabilizationWindowSeconds
HPA and VPA both changing CPUThey conflict on the same metricSplit 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 autoscale a Deployment, set sensible requests, verify with kubectl 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.

Limited Time Offer: Get 80% off all Mock Exam Bundles | Sale ends in 7 days. Start learning today.

Claim Now