ProdCraft
Subscribe
Kubernetes

Kubernetes Horizontal Pod Autoscaler: CPU Metrics and Scaling Tests

Configure Kubernetes HPA using CPU metrics, resource requests and metrics-server; test scaling and avoid common autoscaler mistakes.

ProdCraft5 min read
ProdCraft featured image — Kubernetes Horizontal Pod Autoscaler: CPU Metrics and Scaling Tests

This guide takes a practical look at Kubernetes HPA tutorial for engineers running or learning Kubernetes. Commands are examples for a cluster you administer; verify your current context, namespace, Kubernetes version and available controllers before applying configuration. The aim is to understand the system’s behavior well enough to diagnose a failure, not merely copy a manifest from a screenshot.

Understand what an HPA actually measures

A Horizontal Pod Autoscaler changes replica counts based on configured metrics and scaling behavior. It is not a substitute for increasing a Pod’s resource limit or solving a memory leak. CPU utilization targets are generally relative to resource requests, which means missing or unrealistic requests can make behavior confusing. For a clear demo, use a stateless HTTP workload that consumes predictable CPU and an environment with a compatible resource metrics pipeline, commonly metrics-server. Confirm your cluster supports the autoscaling API version you plan to use.

Prepare metrics-server and resource requests

Run kubectl top nodes and kubectl top pods to verify the resource metrics pipeline. If these fail, follow the metrics-server project’s installation instructions for your cluster; avoid disabling kubelet TLS verification casually just to get a lab screenshot. Define CPU requests on the target Deployment containers, such as a small, realistic millicore request measured from actual workload behavior. Resource limits and requests are related but distinct. A container without a suitable request can complicate utilization-based HPA behavior.

Create an autoscaling policy

For a demo Deployment called sample-api, kubectl autoscale deployment sample-api --cpu-percent=60 --min=2 --max=6 creates a CPU utilization target using kubectl. Check kubectl get hpa and kubectl describe hpa sample-api. Confirm the object points to the intended Deployment and the target shows real metrics rather than “unknown.” For production, store autoscaling/v2 manifests in version control and review scale-up and scale-down behavior settings. Never assume the default metric or replica maximum matches business traffic needs.

Run a controlled load test

Use a load generator you own against the internal test service and raise request volume gradually. Watch kubectl get hpa -w and kubectl get pods in separate terminals. Observe whether CPU utilization crosses the target and whether new replicas become Ready. Scaling is not immediate: monitoring windows, pending Pods and stabilization rules introduce delays. A load test that saturates a downstream database may show no useful application throughput gain even when more API Pods appear. Always interpret autoscaling alongside latency and error rates.

Investigate missing or misleading metrics

An HPA stuck at unknown utilization may indicate missing metrics-server access, resource requests or authorization issues. A scale-up that never completes may be constrained by cluster capacity, quotas, image pull errors or scheduling restrictions. Use kubectl describe hpa, Pod events and nodes’ allocatable resources to separate metric problems from scheduler problems. If the app shows high response latency with low CPU, investigate I/O waits, locks and downstream service saturation; CPU-based HPA alone cannot correct every bottleneck.

Choose policies for production risk

Define a maximum replica count that your database and external APIs can handle. Consider minimum capacity, warm-up time, Pod disruption budgets, rollout strategies and observability. For event-driven workloads, a queue-depth or custom metric can be more representative than CPU, but requires a credible metrics adapter or scaler. Avoid scaling aggressively down during brief quiet periods if startup is slow. Model the cost of replicas and performance goals using real traffic rather than tuning until a graph looks smooth.

Hands-on lab: make your verification repeatable

For a useful practice session, create one disposable namespace, record the current Kubernetes context, and define the initial healthy state. Apply one configuration change at a time and verify both resource status and a real application operation. Check events and controller conditions after each change. Recreate a failure deliberately in the lab, capture the same evidence an on-call engineer would need, and restore the last known-good version. This exercise matters because successful manifest application only proves API admission, not that the app is reachable, authorized, or correct.

Use resource labels and stable names so command output can be traced to the particular lab. Keep redacted logs or screenshots of the healthy and unhealthy states for comparison. When cleanup is complete, verify that no unexpected public load balancers, persistent volumes or privileged service accounts remain; a forgotten demo can still create expense or risk.

Production readiness checklist

Confirm namespace and RBAC ownership, immutable or carefully governed image references, sensible CPU and memory requests, availability probes, resource quotas and appropriate NetworkPolicies. Plan upgrades with a rollback procedure and separate database migration rules. Observe errors, tail latency, saturation and controller status, not only Pod count. Restrict who can alter cluster-wide resources and keep external certificates or credentials out of public Git history. Run a smoke test after every deployment and evaluate whether failures are immediately actionable from logs, metrics and events.

Frequently asked questions

Can I try this safely on kind or another local cluster?

Most concepts can be practiced on a disposable local cluster. Cloud load balancers, storage drivers and selected controllers may behave differently, so follow the deployment platform’s documentation before treating a local result as production proof.

Which command should I start with when it fails?

Check the active context, then inspect the affected resource’s status and events with kubectl. Narrow the failure to admission, scheduling, container startup, networking or application behavior before making a corrective change.

Official references

Read the upstream Kubernetes or project documentation for API compatibility and detailed options. For a complementary guide on production access boundaries, see our enterprise security patterns; authorization and traceability matter equally in Kubernetes and AI systems.

Scaling drill: distinguish application demand from cluster capacity

Create a disposable CPU-bound workload or a safe stress endpoint in staging, then configure an HPA with realistic CPU requests. Watch utilization through kubectl top pods and HPA status while you gradually increase traffic. If replicas scale up but remain Pending, the bottleneck may be node capacity rather than the autoscaler algorithm. If replicas are Ready but response times stay poor, inspect downstream saturation such as database connection limits. These outcomes require different fixes.

After traffic stops, note how stabilization and scale-down behavior work rather than expecting an instant return to minimum replicas. Keep your test within agreed load limits. For incident triage on the resulting Pods, consult our Kubernetes troubleshooting guide.

Share this article

Written by

ProdCraft

ProdCraft publishes practical engineering guides on DevOps, Kubernetes, Docker, Linux, databases, cloud and LLMs — written for engineers who ship.

227 articles View profile

The weekly ops & AI brief

One email a week with the best new guides, tools and incident write-ups. No spam, unsubscribe anytime.

Leave a Reply

Your email address will not be published. Required fields are marked *