DEV Community

The Cyber Sidekick
The Cyber Sidekick

Posted on

Autoscale a Deployment with an HPA, including the field kubectl autoscale can't set (CKA Workloads)

Autoscale a Deployment with an HPA

A Deployment named apache-server is running, and the exam wants it autoscaled on CPU: a 50 percent target, between one and four pods, and a 30 second scaleDown stabilization window. Let's build the HorizontalPodAutoscaler, and see why the obvious one-line command can't finish it.

🎥 Watch the video: https://www.youtube.com/watch?v=G4ZFpOXMJD8

This is a CKA Workloads & Scheduling walkthrough. Every command below is real output from a live cluster, and you can reproduce the whole thing yourself (scripts at the end).

The scenario

Here is the task. In the autoscale namespace, create a HorizontalPodAutoscaler named apache-server that targets the existing apache-server Deployment. Set the CPU target to 50 percent average utilization per pod, allow a minimum of one pod and a maximum of four, and set the scaleDown stabilization window to 30 seconds.

  • Namespace autoscale, HPA named apache-server
  • Target the existing apache-server Deployment
  • CPU target: 50% average utilization per pod
  • minReplicas 1, maxReplicas 4, scaleDown window 30s

How a HorizontalPodAutoscaler works

Two things have to be true before an HPA can do anything. The Pod needs a CPU request, because a 50 percent target is a percentage of that request; with no request the HPA can't compute utilization. And metrics-server has to be running, because that's where the HPA reads live CPU. Given both, the HPA watches CPU and adjusts replicas between your min and max. The scaleDown stabilization window tells it how long to wait on falling load before removing pods, which damps flapping.

Where the YAML comes from (official docs)

Before you apply anything, know that there is no kubectl create that emits a behavior block, so part of this is copy-paste from the official docs, which you are allowed to use in the exam. Two pages on kubernetes dot io cover it. Search HPA and open the HorizontalPodAutoscaler Walkthrough; it shows the autoscaling v2 object with the metrics array, the shape for the CPU target. Then open the Horizontal Pod Autoscaling concept page and find the section called Configurable scaling behavior, with its Stabilization window example; lift the scaleDown block straight from there. In practice: generate the skeleton with kubectl autoscale dry-run, paste the behavior block from that section, and set the window to 30.

Inspect the Deployment

Start by reading what's there. The apache-server Deployment and its Service are running in the autoscale namespace. Open the Deployment manifest and look at the container's resources. Crucially, the Pod template sets a CPU request of 200 millicores. That request is what makes a percentage target meaningful: 50 percent of 200 millicores is 100 millicores per pod.

$ kubectl -n autoscale get deploy,svc
NAME                            READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/apache-server   1/1     1            1           125m

NAME                    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/apache-server   ClusterIP   10.96.182.94   <none>        80/TCP    125m

$ cat apache-app.yaml
...
      labels:
        app: apache-server
    spec:
      containers:
        - name: php-apache
          image: registry.k8s.io/hpa-example
          ports:
            - containerPort: 80
          resources:
            requests:
              cpu: 200m
            limits:
              cpu: 500m
Enter fullscreen mode Exit fullscreen mode

Metrics are flowing

Confirm the HPA will have data to read. kubectl top pods returns live CPU and memory from metrics-server. If this command errored or showed nothing, the HPA would sit at TARGETS unknown and never scale, so verifying metrics first saves you a confusing debug later.

$ kubectl -n autoscale top pods
NAME                             CPU(cores)   MEMORY(bytes)   
apache-server-748dd94f84-2h56f   1m           9Mi
Enter fullscreen mode Exit fullscreen mode

Where kubectl autoscale stops

Now the fast path: kubectl autoscale. Pass the target, min, and max, and it builds an HPA in one line. On a current cluster the dry-run even emits apiVersion autoscaling slash v2, with the CPU target already inside a metrics array, so it looks like you're done. But scan the whole object: there is no behavior section anywhere. The scaleDown stabilization window has no flag on this command, so the imperative path gets you three of the four requirements and stops.

$ kubectl -n autoscale autoscale deployment apache-server --cpu-percent=50 --min=1 --max=4 --dry-run=client -o yaml
...
      name: cpu
      target:
        averageUtilization: 50
        type: Utilization
    type: Resource
  minReplicas: 1
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: apache-server
status:
  currentMetrics: null
  desiredReplicas: 0
Enter fullscreen mode Exit fullscreen mode

Author the v2 HPA

So finish it in YAML. Take the skeleton and add the one piece the command can't give you: a behavior block where scaleDown stabilizationWindowSeconds is 30. Watch the trap the walkthrough hit: in autoscaling slash v2 the CPU target belongs inside the metrics array as averageUtilization, so don't paste an old v1 targetCPUUtilizationPercentage field next to behavior, or the apiserver rejects it as an unknown field. Apply it, then list the HPA: it shows the target against 50 percent, with min 1 and max 4.

$ kubectl apply -f hpa.yaml
horizontalpodautoscaler.autoscaling/apache-server created

$ kubectl -n autoscale get hpa apache-server
NAME            REFERENCE                  TARGETS       MINPODS   MAXPODS   REPLICAS   AGE
apache-server   Deployment/apache-server   cpu: 0%/50%   1         4         1          5s
Enter fullscreen mode Exit fullscreen mode

Verify the HPA

Verify every field, because each is a separate mark. describe confirms the reference to the Deployment, the 50 percent CPU target, and the one-to-four range. Then read the stabilization window straight from the spec: 30 seconds, exactly as asked. With the CPU target reading a real percentage, the autoscaler is live and complete.

$ kubectl -n autoscale describe hpa apache-server
...
  Scale Down:
    Stabilization Window: 30 seconds
    Select Policy: Max
    Policies:
      - Type: Percent  Value: 100  Period: 15 seconds
Deployment pods:       1 current / 1 desired
Conditions:
  Type            Status  Reason            Message
  ----            ------  ------            -------
  AbleToScale     True    ReadyForNewScale  recommended size matches current size
  ScalingActive   True    ValidMetricFound  the HPA was able to successfully calculate a replica count from cpu resource utilization (percentage of request)
  ScalingLimited  True    TooFewReplicas    the desired replica count is less than the minimum replica count
Events:           <none>

$ kubectl -n autoscale get hpa apache-server -o jsonpath='{.spec.behavior.scaleDown.stabilizationWindowSeconds}'
scaleDown stabilizationWindowSeconds = 30
Enter fullscreen mode Exit fullscreen mode

Exam tips

A few traps to remember. kubectl autoscale is fine for min, max, and the CPU target, but it has no flag for a stabilization window, so when behavior is required you finish the HPA in YAML. In autoscaling v2 the CPU target lives inside the metrics array, not as targetCPUUtilizationPercentage; mixing the two is the unknown field error. The Pod needs a CPU request or the percentage target is meaningless. And if TARGETS shows unknown, suspect metrics-server before the HPA itself.

  • kubectl autoscale has no flag for a scaleDown stabilization window; add it in YAML
  • v2: CPU target goes in metrics[], not targetCPUUtilizationPercentage
  • No CPU request on the Pod means no usable utilization target
  • TARGETS ? Check metrics-server before blaming the HPA

Recap

  • Prereqs: a CPU request on the Pod + a running metrics-server
  • v2 manifest: metrics[] for the CPU target, behavior for scaleDown
  • stabilizationWindowSeconds 30 is the field kubectl autoscale can't set
  • Subscribe + dev.to writeup

Reproduce this yourself

The entire scenario is scripted on a throwaway kind cluster: https://github.com/The-Cyber-Sidekick/TCS_CKA_2026_Exam_Scenarios

git clone https://github.com/The-Cyber-Sidekick/TCS_CKA_2026_Exam_Scenarios.git
cd TCS_CKA_2026_Exam_Scenarios/learning/scenarios/scenario7-hpa-cpu-autoscale
./setup.sh        # creates the cluster AND arms the scenario
# solve it by hand, or:
./solution.sh     # apply the answer key and verify
Enter fullscreen mode Exit fullscreen mode

If this helped, subscribe to The Cyber SideKick on YouTube for more CKA drills, and grab the newsletter at https://thecybersidekick.beehiiv.com.

Top comments (0)