How to Join a Node to a Kubernetes Cluster

Written by: Bagus Facsi Aginsa
Published at: 09 Apr 2022


You have already deployed your Kubernetes cluster, and then later your application is growing rapidly and right now you must scale your Kubernetes deployment. You either add more master nodes or worker nodes for the cluster’s and application’s high availability.

The join command that was generated when you initialized the Kubernetes master is only valid for 24 hours. So, you cannot use it to scale your cluster right now. In this tutorial, we will guide you on how to join a node to an existing Kubernetes cluster.

Check Prerequisite

  1. Kubernetes Cluster that already running.
  2. The New Node that already has kubeadm, kubelet, and kubectl installed. If you still don’t have them, you can follow my other tutorial on How to Install Kubernetes in Ubuntu 20.04. Follow the tutorial until the kubeadm, kubelet, and kubectl are installed.

Join a Worker Node

To join a worker node to a Kubernetes cluster, you need to generate the join command on the master node, and then execute the join command on the new worker node.

Get Kubeadm Join Command for Worker Node

Note: Do this on the existing Master Node

To generate the join command, run this kubeadm command on the master node

kubeadm token create --print-join-command

You will get an output similar to this

kubeadm join 10.14.10.39:6443 --token 55ekme.0ahjmz09920bqsyt --discovery-token --ca-cert-hash sha256:636786a58df07625167bd7305d56c4cc75bcbedcc474313934aa08c09dc603af

The 10.14.10.39:6443 is the Control Plane Endpoint.

Joining Worker Node to Kubernetes CLuster

Note: Do this on the new Worker Node

After you get the join command, copy the join command above and execute the command on the new worker node that wants to join the cluster.

If the join command fails, please check:

  1. is kubeadm, kubectl, and kubelet already installed correctly?
  2. is the connection the 10.14.10.39:6443 blocked by a firewall?

The join command is only valid for 24 hours, so you must generate a new one if you want to add another worker node after the valid token period.

Join a Master Node

To join a master node to a Kubernetes cluster, you need more steps than to join a worker node. You need to get a cluster configuration file, upload control-plane certificates, generate a join command, and then combine the 2 of them to create a full join command and execute the command on the new master node.

Tips!

If in the past you initiate your cluster without defining the --control-plane-endpoint using domain name, this tutorial will not work. You must reset your cluster first and then define the control plane endpoint using DNS name pointing to your master or load balancer.

Additional Prerequisite

Make sure that you have a load balancer to load balance your master node.

Get Cluster Configuration File

Note: Do this on Existing Master Node

Before we can join a new master node, we must have the cluster configuration file first. If you initialized your cluster using a config file, then you can use that file. If you don’t, we can get the cluster configuration file by executing this command:

kubectl get cm kubeadm-config -n kube-system -o yaml

You will get a ConfigMap object like this

apiVersion: v1
data:
  ClusterConfiguration: |
    apiServer:
      extraArgs:
        authorization-mode: Node,RBAC
      timeoutForControlPlane: 4m0s
    apiVersion: kubeadm.k8s.io/v1beta3
    certificatesDir: /etc/kubernetes/pki
    clusterName: kubernetes
    controlPlaneEndpoint: k8s-endpoint:6443
    controllerManager: {}
    dns: {}
    etcd:
      local:
        dataDir: /var/lib/etcd
    imageRepository: k8s.gcr.io
    kind: ClusterConfiguration
    kubernetesVersion: v1.23.3
    networking:
      dnsDomain: cluster.local
      podSubnet: 10.2.0.0/16
      serviceSubnet: 10.1.0.0/16
    scheduler: {}
kind: ConfigMap
metadata:
  creationTimestamp: "2022-02-15T04:28:35Z"
  name: kubeadm-config
  namespace: kube-system
  resourceVersion: "217"
  uid: 383bcd3d-d1bd-4d46-b805-a8ea243a6bec

The marked text is the current k8s Cluster Configuration.

Copy the marked text under ClusterConfiguration:, create a new file to store the configuration

nano kubeadm-config.yaml

And then paste the marked text to this file. Please mind the indentation because it is very important in a yaml file. In this case, the file containing this script

apiServer:
  extraArgs:
    authorization-mode: Node,RBAC
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controlPlaneEndpoint: k8s-endpoint:6443
controllerManager: {}
dns: {}
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: k8s.gcr.io
kind: ClusterConfiguration
kubernetesVersion: v1.23.3
networking:
  dnsDomain: cluster.local
  podSubnet: 10.2.0.0/16
  serviceSubnet: 10.1.0.0/16
scheduler: {}

Get Kubeadm Join Command for Master Node

Note: Do this on Existing Master Node

Execute this command on the existing master node to upload control-plane certificates including the kubeadm configuration file.

kubeadm init phase upload-certs --upload-certs --config kubeadm-config.yaml

The kubeadm-config.yaml is the Cluster configuration file we created earlier.

After executing the command, you will get an output like this

[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[upload-certs] Using certificate key:
6a2f496e172b16584f3700da0427d6e87b3ff06a67383c1bb05cf504128e4465

The marked part above is the certificate key that we need to pass to the join command.

Still on the existing master node, print the join command

kubeadm token create --print-join-command

You will get an output like this

kubeadm join k8s-endpoint:6443 --token 4iegnp.x2tfqdd9gl93zz1o --discovery-token-ca-cert-hash sha256:636786a58df07625167bd7305d56c4cc75bcbedcc474313934aa08c09dc603af

Joining Master Node to Kubernetes CLuster

Note: Do this on the new Master Node

First, make sure that controlPlaneEndpoint is pointing to the load balancer and can be resolved on the new master node. In this case, k8s-endpoint is not resolvable by public DNS, so I will define the ip address on the host’s file.

Open the host file

nano /etc/hosts

Add this line

192.168.7.25 k8s-endpoint

Make sure that the control endpoint k8s-endpoint is pointing to your load balancer IP. In this case, the load balancer IP is 192.168.7.25.

Now, execute the join command with this format

<basic join command> --control-plane --certificate-key <ceritifcate-key>

In this case, I will execute this command to join my new master node:

kubeadm join k8s-endpoint:6443 --token 4iegnp.x2tfqdd9gl93zz1o \
--discovery-token-ca-cert-hash sha256:636786a58df07625167bd7305d56c4cc75bcbedcc474313934aa08c09dc603af \
--control-plane --certificate-key 6a2f496e172b16584f3700da0427d6e87b3ff06a67383c1bb05cf504128e4465

If the join command fails, please check:

  1. is kubeadm, kubectl, and kubelet already installed correctly?
  2. is the connection the k8s-endpoint:6443 blocked by a firewall?

That’s it, now you can scale your Kubernetes cluster to your heart’s content!