Skip to main content

Scale a workload to zero

Inspect 1.36

On your own hardware, scaling to zero is the difference between paying for a node all night and letting the cluster drop it. Elsewhere idle work is merely wasteful; on metal it is physical, a machine spinning and drawing power for a service nobody is calling at 3 a.m. Scaling to zero holds no pods while nothing is calling, then wakes the workload on the first request. For anything idle much of the day, a staging environment, an internal tool, a low-traffic service, that is real money back.

Why the HPA cannot get there#

A HorizontalPodAutoscaler has a floor of one replica, and it scales on the usage of running pods, so at zero there is nothing left to measure. Reaching zero needs something sitting in front of the workload to catch the first request and start a pod from cold. The HPA is not that thing.

Wake on a request with Knative#

If the workload serves HTTP, put Knative Serving in front of it. When traffic stops, Knative scales the workload to zero; when a request arrives, its activator holds the connection open, starts a pod from zero, and serves it the moment the pod is ready. Knative is not part of the platform, so install it and run the workload as a Knative Service.

Note

The cost of zero is the cold start. The first request after an idle stretch waits for a pod to be pulled and started, which can be a few seconds. Fine for an internal tool; wrong for a latency-sensitive public endpoint. Keep a warm floor of one replica for anything a user waits on directly.

Drop the node too#

Freeing the pods is only half the saving; the bill stops when the node itself goes away. Pair scale-to-zero with the : once the last pod leaves a burst node, the autoscaler removes it.

Picture a bare-metal base doing the steady daytime work, with a cloud burst pool bolted on for peaks. As evening traffic drains, the last Knative pods sleep, the burst nodes empty, and the autoscaler deletes them one by one. Overnight the burst pool sits at zero nodes and zero cost. When work returns in the morning, the nodes come back with it. The base metal never moved.

Verify it sleeps and wakes#

Stop sending traffic and watch kubectl get deploy <name> -w. After the scale-down grace period the replicas fall to 0/0. Send one request and keep watching: the count climbs back to 1/1, and the delay you feel is the cold start. If it never reaches zero, the grace period is still holding a pod open.