🇧🇷 Leia a versão em português aqui.
Once an on-premise Kubernetes cluster is up and running, it's common, sooner or later, to need more available capacity — whether to support more load, or to improve resilience by spreading applications across more workers. In this article, I show the process of adding a new node to a cluster that's already in operation.
This flow is similar to joining workers for the first time, but with some extra care — mainly around machine identity (hostname, SSH keys) — since, in virtualized environments, it's common to clone an existing template machine to speed up provisioning.
Starting from a template
If your environment uses virtualization (VMware, Proxmox, etc.), the fastest path is usually to keep a node template already prepared — with the operating system, containerd, and the Kubernetes packages (kubelet, kubeadm) already installed, following the same steps used on the cluster's original nodes.
To provision a new machine, just clone that template. However, a machine cloned from a template carries certain identities that need to be regenerated before it joins the cluster — otherwise, the new node might conflict with the original node the template was created from.
Regenerating SSH keys
Machines cloned from a template share the same SSH keys as the source host, which poses a security risk (the same SSH identity "exists" on two different machines). Regenerate the keys from scratch:
ssh-keygen -t rsa -f ssh_host_rsa_key
ssh-keygen -t ecdsa -f ssh_host_ecdsa_key
ssh-keygen -t ed25519 -f ssh_host_ed25519_key
These commands should be run in the /etc/ssh/ directory, overwriting the keys inherited from the template.
Adjusting the hostname
Still carrying over the template's identity, the new machine's hostname is likely duplicated from the source. Set a new, unique hostname for this node:
hostnamectl set-hostname <new-name>
Then, add the new node to the /etc/hosts file on all machines in the cluster (master and other workers) — just as we did during the cluster's initial setup —, ensuring every node can resolve the new server's name.
Updating system packages
Before joining the new node to the cluster, it's good practice to make sure it has up-to-date OS packages:
apt update
apt upgrade
Joining the new node to the cluster
With the machine's identity fixed and the system updated, the joining process is the same used to add any worker: generate a valid join command on the master and run it on the new node.
On the master server, generate a new token and the full join command:
kubeadm token create --print-join-command
On the new node, run the returned command (the token and hash values below are just illustrative):
kubeadm join 192.168.121.100:6443 --token r5jtqh.pek7... --discovery-token-ca-cert-hash sha256:518233918ee0353672...
Confirming the integration
Back on the master, check whether the new node shows up in the list and has Ready status:
kubectl get nodes
If the new worker stays NotReady for more than a few minutes, it's worth investigating whether the pod network (CNI) was propagated correctly to it and whether containerd is running without errors on the new machine.
Final thoughts
Adding nodes to an already-running cluster is, in essence, the same process used in the initial setup — the difference lies in the extra care needed when the machine is provisioned from a template or clone, ensuring it has its own identity (SSH and hostname) before joining the cluster's network. Keeping an up-to-date template with containerd and Kubernetes already installed is a practical way to speed up this horizontal scaling process over time.
Top comments (0)