Scale out with the Horizontal Pod Autoscaler
Every cluster created with Syself Autopilot runs the metrics-server , so a Horizontal Pod Autoscaler that scales on CPU or memory works the moment you apply it, with no need to install additional tools. It watches live usage, compares it to a target you set, and moves the replica count until the two line up.
How it decides
The math is a ratio. If your pods average 80% CPU against a 50% target, the HPA calculates it needs roughly 80/50 (that is, 1.6) times the replicas it has now, and it adds them. When load drops, it works the same ratio in reverse.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web
spec:
scaleTargetRef: # the workload whose replica count the HPA owns
apiVersion: apps/v1
kind: Deployment
name: web
minReplicas: 2 # floor: 2+ so a node drain never leaves you at zero
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60 # target is a % of the CPU request, not the node
Important
A CPU or memory target is a percentage of the request, not of the node. If a container has no CPU request, "60% of CPU" has no denominator and the HPA simply cannot scale it. Set requests before you use resource-based HPAs.
Min, max, and stabilization
minReplicas and maxReplicas set the range the HPA moves within. Between them sits stabilization, which keeps the replica count from flapping: the HPA scales up fast, but by default waits 5 minutes of sustained low load before scaling down, so a short drop in usage does not shed capacity you will want back a minute later. Tune behavior.scaleUp and behavior.scaleDown when the defaults do not fit your traffic shape.
Your HPA during a node roll
When setting minReplicas, ensure you do not set them to 1. Nodes tend to get get drained and replaced constantly. Every Kubernetes upgrade rolls them out, and self-healing replaces any node that goes unhealthy. When a node drains, its pods are evicted with up to the 180-second default drain window to reschedule elsewhere. A single-replica workload has no second copy to carry traffic across that gap, so it can sit at zero running pods mid-drain even though the HPA is behaving exactly as configured. Keep minReplicas at 2 or higher for anything that has to stay reachable.
Beyond CPU and memory
CPU and memory are not the only signals an autoscaling/v2 HPA can read. Point it at a custom metric from your own application, or an external one like queue depth: install an adapter that publishes the value to the Kubernetes metrics API, then reference it under metrics the same way you would CPU. One limit stays fixed, though: the HPA only changes pod count, never node count. When it scales past what the current nodes hold, pair it with the cluster autoscaler .
Verify
kubectl get hpa web shows current usage against your target under TARGETS: 35%/60% means it is reading metrics and has headroom. If you see <unknown>/60%, the HPA cannot read usage at all, almost always a missing CPU request or metrics-server not reaching the pod. Fix that first; a blind HPA will not scale.
Then prove the important case: cordon and drain the node running your workload by hand, and watch it. If minReplicas is 2 or more, traffic is not interrupted. If it is 1, you will see the gap the next real upgrade would have shown you in production.
Keep databases available
How a database behaves when its node is replaced, why a single instance has a short gap, and how a replicated database with failover stays available.
Right-size with the Vertical Pod Autoscaler
Let the VPA recommend or apply the CPU and memory requests a workload actually needs instead of guessing.