Kubernetes cluster installation guide
This is an installation guide for a Kubernetes cluster; this tutorial was tested using Ubuntu 24.04. operating system.
The process documents the configuration of the main node (Control Plane or Master) using containerd as the container runtime and Calico as the network provider (CNI). Upon completing this guide, the cluster will be operational and ready to receive workloads or to join additional worker nodes.
The guide must be followed and execute points 1-4 in all nodes. Points 5, 6 and 8 must be followed only in the master node.
1 - Getting the server ready - All nodes
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.32/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.32/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt update
sudo apt install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
2 - Disable swap memory - All nodes
sudo swapoff -a
sudo sed -i '/swap.img/ s/^\(.*\)$/#\1/g' /etc/fstab
sudo sed -i '/swap/ s/^\(.*\)$/#\1/g' /etc/fstab
3 - Configure network and modules - All nodes
3.1 Configure persistent loading of modules
sudo tee /etc/modules-load.d/containerd.conf <<EOF
overlay
br_netfilter
EOF
3.2 Load at runtime
sudo modprobe overlay
sudo modprobe br_netfilter
3.3 Ensure sysctl params are set
sudo tee /etc/sysctl.d/kubernetes.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
3.4 Reload configs
sudo sysctl --system
4 - Install and configure Containerd - All nodes
4.1 Add docker repository
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
4.2 Install containerd
sudo apt update
sudo apt install -y containerd.io
4.3 Configure containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
4.4 Start/restart containerd
sudo systemctl restart containerd
sudo systemctl enable containerd
4.5 Enable kubelet
sudo systemctl enable kubelet
5 - Master node configuration - Only master
5.1 Enable and start kubelet
sudo systemctl enable kubelet
sudo kubeadm config images pull
sudo kubeadm init --pod-network-cidr=192.168.0.0/16 --control-plane-endpoint=<IP or DNSNAME> --upload-certs
Take in mind that if you use the DNSNAME option, you have to configure a DNS or /etc/hosts
sudo kubeadm init --pod-network-cidr=192.168.0.0/16 --control-plane-endpoint=<192.168.122.40/16> --upload-certs
sudo kubeadm init --pod-network-cidr=192.168.0.0/16 --control-plane-endpoint=<soffid-Ubuntu-24-04-PC-Q35-ICH9-2009> --upload-certs
Note: If 192.168.0.0/16 is already in use within your network you must select a different pod network CIDR, replacing 192.168.0.0/16 in the above command.
Other options of the init command, but we are not going to use right now are:
--cri-socket ==> Use if have more than one container runtime to set runtime socket path
--apiserver-advertise-address ==> Set advertise address for this particular control-plane node's API server
If everything is ok, you will able to read a message saying "Your Kubernetes control-plane has initialized successfully!". If so, you need to run the following:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
6 - Installing Calico - Only master
6.1 Installing Calico
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/calico.yaml
6.2 Check kubernetes nodes
kubectl get nodes
7 - Joining other nodes
7.1 For joining other nodes execute the following command - Only MASTER
sudo kubeadm token create --print-join-command
7.2 Example of join token - Only SLAVE
kubeadm join 192.168.122.40:6443 --token r705ed.7d47ya6a6f3eecr4 --discovery-token-ca-cert-hash sha256:0c740869ea8a0e833a0163c5246fb74daed12baf7207e8a4a7f37dda40aaee4e
Once joined a message like:
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
Will appear.
7.3 Check if the node was added - ONLY MASTER
kubectl get nodes
NAME STATUS ROLES AGE VERSION
soffid-ubuntu-24-04-pc-q35-ich9-2009 Ready control-plane 67m v1.32.13
soffidslave-ubuntu-24-04-pc-q35-ich9-2009 Ready <none> 71s v1.32.13
8 - Untaint master node - Only master
8.1 Check node name
kubectl get nodes
NAME STATUS ROLES AGE VERSION
soffid-ubuntu-24-04-pc-q35-ich9-2009 Ready control-plane 15m v1.32.13
8.2 Enable the master node to execute pods
kubectl taint node NODE_NAME node-role.kubernetes.io/master:NoSchedule-
-Example-
kubectl taint node soffid-ubuntu-24-04-pc-q35-ich9-2009 node-role.kubernetes.io/control-plane:NoSchedule-
8.3 Check master node taints
kubectl describe node NODE_NAME | grep Taints
-Example-
kubectl describe node soffid-ubuntu-24-04-pc-q35-ich9-2009 | grep Taints
9 - Joining other MASTER nodes
Take in mind to have and odd number of master nodes.
sudo kubeadm init phase upload-certs --upload-certs
This will return a TOKEN: 2a74cf543fcbe46e8e0c9938d65e990f401573df2815945e320946fbe0b638a6
sudo kubeadm token create --print-join-command --certificate-key TOKEN
sudo kubeadm token create --print-join-command --certificate-key 2a74cf543fcbe46e8e0c9938d65e990f401573df2815945e320946fbe0b638a6
This will return a command like:
kubeadm join 192.168.122.40:6443 --token bdvw7e.pceldjy93tb42ggu --discovery-token-ca-cert-hash sha256:6f4528b9625a9291d286b1525e37e45a9394c9ee98e4e035a7319ac356cebb1b --control-plane --certificate-key 2a74cf543fcbe46e8e0c9938d65e990f401573df2815945e320946fbe0b638a6
Execute it on the new NODE to connect it as a MASTER node
Once done get the authorizations
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Check the nodes
kubectl get nodes
NAME STATUS ROLES AGE VERSION
soffid-ubuntu-24-04-pc-q35-ich9-2009 Ready control-plane 10m v1.32.13
soffidslave-ubuntu-24-04-pc-q35-ich9-2009 Ready control-plane 38s v1.32.13