Autoscaling Down to Zero Nodes
Automatic scaling of a node group down to zero helps save resources when they are not being used. This is convenient for one-off tasks (for example, Jobs) or staging environments that remain inactive at night.
Requirements Copy link
For scaling down to zero to work, the cluster must have at least two additional nodes that remain permanently active. These nodes may belong to different groups. They are used to run Kubernetes system components.
Pod Configuration Copy link
For the autoscaler to launch nodes in the desired group, specify the ID of that group in your manifest using nodeSelector or nodeAffinity.
You can use either the worker node group ID or a custom label assigned to the group as a condition. Labels provide flexible pod placement and avoid tight coupling to specific IDs.
How to Find the Group ID
- Go to the Kubernetes section and click on the cluster.
- Open the Resources tab.
- Click the three dots next to the group and select Edit group.
- The group ID will be shown in the URL, for example:
https://my.hostman.com/kubernetes/1048329/54289/editHere:
1048329: cluster ID54289: node group ID
Example with nodeSelector:
nodeSelector:
k8s.hostman.com/cluster-node-group-id: "54289"Example with nodeAffinity:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: k8s.hostman.com/cluster-node-group-id
operator: In
values:
- "54289"
When Scaling Down to Zero Won’t Work Copy link
The autoscaler will not be able to remove the last node in a group in the following cases:
- The pod has the annotation:
cluster-autoscaler.kubernetes.io/safe-to-evict: "false" - Pods cannot be moved to other nodes due to scheduler restrictions.
- A
PodDisruptionBudgetprevents pods from being deleted without exceeding the limit. - The pod is not managed by a controller (
Deployment,StatefulSet,Job,ReplicaSet).
Practical Example Copy link
In this example, we’ll create a node group with autoscaling down to zero enabled, run a Job in it, and see how the cluster automatically creates a node to run the task and deletes it once the task is complete.
When creating a worker node group, you can define custom labels and use them for pod placement. In this example, the group ID is used for simplicity.
Prerequisites Copy link
An existing Kubernetes cluster with at least one node group.
Creating a Node Group with Zero Autoscaling Copy link
- Go to the Kubernetes section and click on the cluster.
- Open the Resources tab.
- Click Add group.
- Select the worker node configuration.
- Enable the Autoscaling toggle and set the minimum number of nodes to 0.
After the group is created, one node will appear and will be automatically deleted if no user pods are running on it.
Now the cluster has two groups:
- A group with active nodes that do not scale down to zero.
- A group with autoscaling down to zero enabled. In this example, its ID is 54289.
Checking Existing Nodes Copy link
Run the command:
kubectl get nodesExample output:
NAME STATUS ROLES AGE VERSION
worker-192.168.0.25 Ready <none> 21h v1.33.3+k0s
worker-192.168.0.8 Ready <none> 22h v1.33.3+k0sCreating a Job Copy link
Create a file named job.yaml with the following content:
apiVersion: batch/v1
kind: Job
metadata:
name: hello-job
spec:
ttlSecondsAfterFinished: 30
template:
metadata:
name: hello-job
spec:
restartPolicy: Never
nodeSelector:
k8s.hostman.com/cluster-node-group-id: "54289"
containers:
- name: hello
image: busybox
command:
- sh
- -c
- 'i=0; while [ $i -lt 10 ]; do echo "Hello from job"; sleep 30; i=$((i+1)); done'
resources:
requests:
cpu: "50m"
memory: "32Mi"
limits:
cpu: "100m"
memory: "64Mi"
This Job runs a container using the busybox image that writes a message to the log 10 times at 30-second intervals.
Note: In the nodeSelector section, we specify the node group ID (54289).
Apply the manifest:
kubectl apply -f job.yamlCheck the list of pods:
kubectl get podExample output:
NAME READY STATUS RESTARTS AGE
hello-job-s7ktd 0/1 Pending 0 4sThe pod is in Pending status because there are no nodes in the group yet. Go to the Resources section in the management panel; you’ll see that a new node is being created in the autoscaling group.
After the node is created, check the nodes again:
kubectl get nodesExample output:
NAME STATUS ROLES AGE VERSION
worker-192.168.0.25 Ready <none> 21h v1.33.3+k0s
worker-192.168.0.6 Ready <none> 7m v1.33.3+k0s
worker-192.168.0.8 Ready <none> 22h v1.33.3+k0sworker-192.168.0.6 is the new node created for the Job.
Check the pod again:
kubectl get podExample output:
NAME READY STATUS RESTARTS AGE
hello-job-s7ktd 1/1 Running 0 5m30sNow the pod is running.
Job Completion and Node Deletion Copy link
After the Job completes, the node where it was running will be tainted. View the taint with:
kubectl describe node worker-192.168.0.6Look for the line:
Taints: DeletionCandidateOfClusterAutoscaler=1755679271:PreferNoScheduleThis means the node is marked for deletion. Two minutes after the taint is applied, the node will be removed.
Check it with:
kubectl get nodes