kubectl autoscale: Create an HPA From the CLI
kubectl autoscale creates a HorizontalPodAutoscaler that scales a workload between --min and --max based on CPU utilization.
For a quick CPU-based autoscaler without writing YAML, autoscale generates the HPA. For richer metrics you still need a manifest.
What it does
kubectl autoscale creates an HPA targeting a Deployment, ReplicaSet, or StatefulSet. --cpu-percent sets the target average CPU utilization; the controller adjusts replicas between --min and --max to hold that target, reading usage from the metrics API.
Common usage
kubectl autoscale deployment api --min=2 --max=10 --cpu-percent=70
# render YAML to commit instead of creating live
kubectl autoscale deploy api --min=2 --max=10 --cpu-percent=70 \
--dry-run=client -o yaml > hpa.yaml
# inspect the resulting HPA
kubectl get hpa apiOptions
| Flag | What it does |
|---|---|
| --min=<n> | Minimum replica count |
| --max=<n> | Maximum replica count (required) |
| --cpu-percent=<n> | Target average CPU utilization percent |
| --name=<name> | Name of the HPA (defaults to the target) |
| --dry-run=client -o yaml | Emit YAML without creating |
In CI
autoscale only emits a CPU-based v1-style HPA; for memory or custom/external metrics, generate a v2 HPA manifest instead. The target workload must set CPU requests, or the HPA cannot compute a utilization percentage and never scales.
Common errors in CI
"the HPA was unable to compute the replica count: failed to get cpu utilization: ... missing request for cpu" means the pods have no CPU request; add one. "unable to fetch metrics from resource metrics API" means metrics-server is missing or unhealthy. "Error from server (NotFound): ... not found" means the target workload name or namespace is wrong.
Using this in CI
A runner has no kubeconfig, no cached context, and no interactive auth. Every kubectl invocation in CI needs the context supplied explicitly, and most confusing CI failures here are the command running against the wrong cluster or no cluster at all.
# never rely on the ambient context on a runner
kubectl --context "$KUBE_CONTEXT" -n "$NAMESPACE" get pods
# confirm what you are actually connected to before mutating anything
kubectl config current-context
kubectl cluster-info
# fail fast instead of hanging on an unreachable API server
kubectl --request-timeout=30s get nodes