Effortless Kubernetes Cluster Deployment with Kubeadm and Containerd
As Kubernetes continues to gain popularity, more and more people are looking to build their clusters for testing and development purposes. If you’re one of them, you’ve come to the right place! This article will show you how to create a Kubernetes cluster from scratch using Kubeadm.
TABLE OF CONTENTS
Introduction
- What is kubeadm
- Benefits of using Kubeadm
- Features of kubeadm
- How Kubeadm follows the Kubernetes release cycle
- Who maintains Kubeadm?
Prerequisites
- Creating the Ubuntu instances
- Specifying minimum specifications for instances
- Enabling networking between instances
- Allowing required ports between instances
- Disabling swap on instances
Installing kubeadm
- Updating the system
- Installing Containerd as the Container Runtime
- Installing kubeadm
- Configuring Kubernetes dependencies
Initializing the control plane
- Initializing the master node
- Configuring Kubectl on the control plane
- Installing Network Addon
- Verifying the control plane
Joining the worker nodes
- Creating a token
- Joining the worker nodes to the control plane
- Verifying the worker nodes
- Testing workload
Introduction
What is kubeadm
kubeadm is a command-line tool used to bootstrap a minimal, production-ready Kubernetes cluster. It automates the creation of a Kubernetes cluster by bootstrapping the control plane, joining the nodes, and managing the necessary Kubernetes objects. It is one of the official Kubernetes tools and supports various deployment scenarios.
Benefits of using Kubeadm
Using kubeadm has many benefits, including:
- Simplifies the process of setting up a Kubernetes cluster
- Supports various deployment scenarios, including single-node and multi-node clusters
- Ensures that Kubernetes components are configured correctly and compatible with each other
- Enables easy upgrades and management of Kubernetes clusters
- Supports integration with other Kubernetes tools like kubectl and kubeadm-dind-cluster.
Features of kubeadm
Some of the key features of kubeadm are:
- Automatic TLS bootstrapping
- Ability to configure various networking plugins
- Support for different Kubernetes versions and deployment scenarios
- Automatic detection and handling of different container runtimes like Docker, CRI-O and Containerd.
- Automatic handling of different OS distributions and package managers.
How Kubeadm follows the Kubernetes release cycle
kubeadm follows the Kubernetes release cycle by releasing new versions that are compatible with the latest Kubernetes releases. This ensures that Kubeadm is always up-to-date with the latest features and bug fixes. Additionally, kubeadm supports different Kubernetes versions, allowing users to deploy clusters with different versions of Kubernetes depending on their requirements.
Who maintains kubeadm
kubeadm is an open-source tool maintained by the Kubernetes community. It is one of the official Kubernetes tools and is actively developed and maintained by a team of contributors from various organizations. The codebase is hosted on GitHub and is available for anyone to contribute to and use.
Prerequisites
Creating the Ubuntu instances: To create a Kubernetes cluster using Kubeadm, you will need to create three Ubuntu instances. You can use a cloud provider such as AWS or Google Cloud Platform to create these instances.
Specifying minimum specifications for instances: Each instance should have a minimum specification of 2 CPU and 2 GB RAM to ensure that the Kubernetes cluster runs smoothly.
Enabling networking between instances: Networking must be enabled between the instances to communicate with each other.
Allowing required ports between instances: Certain ports must be allowed between the instances to ensure that the Kubernetes components can communicate with each other. For example, port 6443 is used by the Kubernetes API server.
Disabling swap on instances: Swap must be disabled on the instances to prevent performance issues. Kubernetes requires a lot of memory, and swap usage can significantly slow down the cluster.
Action Steps:
Step 1: Set Up Unique Hostnames on All Instances
To enable communication between the cluster nodes via hostnames, we’ll set up unique hostnames on each instance. Log in to each instance and run the following commands:
$ sudo hostnamectl set-hostname controller-plane
$ sudo hostnamectl set-hostname worker-node-1
$ sudo hostnamectl set-hostname worker-node-2
After running these commands, log out and log back into each instance to reflect the hostname changes.
Step 2: Update the Hosts File on All Instances
Next, we need to update the hosts file on each instance to enable communication via hostnames. Open the hosts file on each instance using the following command:
$ sudo vi /etc/hosts
Then add the following lines to the file, replacing the IP addresses with the private IP addresses of your instances:
controller-plane-ip controller-plane
worker-node-1-ip worker-node-1
worker-node-2-ip worker-node-2
Save and close the file.
Step 3: Disable Swap on All Instances
Kubernetes requires that swap be disabled on all cluster nodes. To disable swap on each instance, run the following commands:
$ sudo swapoff -a
$ sudo vi /etc/fstab
In the fstab file, comment out any lines that reference swap.
Installing kubeadm
Updating the system
Before installing any software on the system, it’s essential to ensure that the system is up to date with the latest patches and updates. This can be done by running the following command in the terminal:
sudo apt update && sudo apt upgrade -y
Installing Containerd as the Container Runtime
To set up containerd as the container runtime on all instances, we first need to load some Kernel modules and modify system settings.
Loading Kernel modules and modifying system settings
- The
overlay
the module provides the ability to overlay filesystems, which is necessary for Docker and containerd. - The
br_netfilter
module enables bridge netfilter, which is used by Kubernetes to implement network policies.
To load the required Kernel modules, run the following commands:
$ cat << EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
$ sudo modprobe overlay
$ sudo modprobe br_netfilter
Next, the settings in /etc/sysctl.d/99-kubernetes-cri.conf
enable IPv4 forwarding and IPv6 iptables filtering for container networking.
To modify the system settings by running the following commands:
$ cat << EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
$ sudo sysctl --system
Once the Kernel modules are loaded and system settings are modified, we can proceed to install containerd on all instances [controller-plane, worker-node-1, worker-node-2] by running:
$ sudo apt update
$ sudo apt install -y containerd
After Containerd is installed, generate a default configuration file for contained on all instances [controller-plane, worker-node-1, worker-node-2] and restart the service.
$ sudo mkdir -p /etc/containerd
$ sudo containerd config default | sudo tee /etc/containerd/config.toml
$ sudo systemctl restart containerd
Make sure to execute these commands on all the instances to ensure containerd is set up correctly.
Installing kubeadm
Kubeadm is a package that can be installed on the Ubuntu system and holds its version on all instances
$ sudo apt update
$ sudo apt install -y kubeadm=1.27.0-00$ sudo apt-mark hold kubeadm
Note: If you encounter any confusion during the installation process, refer to the official Kubernetes documentation.
Configuring Kubernetes dependencies
Kubeadm requires additional dependencies such as kubelet and kubectl to be installed on the system. These can be installed using the following commands:
Step 1: Install Kubelet and Kubectl
$ sudo apt install -y kubelet=1.27.0-00 kubectl=1.27.0-00
$ sudo apt-mark hold kubelet kubectl
Step 2: Install Prerequisite Packages
We need to install some prerequisite packages on each instance to configure the Kubernetes apt repository. Run the following commands on each instance:
$ sudo apt update
$ sudo apt install -y apt-transport-https ca-certificates curl
Step 3.: Configure the Kubernetes Apt Repository
Next, we’ll download the Google Cloud public signing key and configure the Kubernetes apt repository on each instance:
$ sudo mkdir /etc/apt/keyrings
$ curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/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.31/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
Additionally, it’s important to make sure that the firewall is configured to allow traffic on the required ports for Kubernetes to function properly. This can be done using the following command:
sudo ufw allow 6443/tcp
Initializing the control plane
Initializing the master node
After installing Kubeadm, the next step is to initialize the control plane. To do this, run the following command on the control plane node:
$ sudo kubeadm init --pod-network-cidr=<cidr> --kubernetes-version 1.27.0
This command will download the necessary images and create the initial configuration for the Kubernetes control plane. Make sure to replace <cidr>
it with the CIDR block for your pod network.
Configuring Kubectl on the control plane
To manage the Kubernetes cluster, you’ll need to add a configuration file. To do this, run the following command on the control plane node:
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
This command will create a directory for the kubectl
configuration and copy the Kubernetes configuration file to it. Finally, it sets the owner of the configuration file to the current user. Now you can use kubectl
to manage your Kubernetes cluster.
Installing Network Addon
Install a CNI plugin suitable for your use case. For this article, we are using Calico as an example.
$ kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.1/manifests/calico.yaml
Verifying the control plane
Once the control plane initialization is completed, you can verify its status by running the following command:
kubectl get nodes
The controller-plane should now be in the Ready state, indicating that the network addon is successfully installed and configured.
Joining the worker nodes
Creating a token
Before you can join worker nodes to the control plane, you need to create a token. Run the following command on the control plane to generate a token:
$ sudo kubeadm token create --print-join-command
This will output the token and the command to join a worker node to the cluster.
Joining the worker nodes to the control plane
On each worker node, run the command output by the previous command. This command will look something like this:
$ sudo kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>
Replace <control-plane-host>
and <control-plane-port>
with the IP address and port of the control plane node, <token>
with the token generated in the previous step, and <hash>
with the hash of the CA certificate.
The CA key hash has the format
sha256:<hex_encoded_hash>
. By default, the hash value is returned in thekubeadm join
command printed at the end ofkubeadm init
or in the output ofkubeadm token create --print-join-command
.
Verifying the worker nodes
To verify that the worker nodes have joined the cluster, run the following command on the control plane:
$ kubectl get nodes
This should list all the nodes in the cluster, including the worker nodes that were just added.
Testing workload
Deploy an Nginx pod, expose it as ClusterIP from the [controller-plane] instance, and verify its status
$ kubectl run nginx --image=nginx --port=80 --expose
$ kubectl get pod nginx -o wide
$ kubectl get svc nginx
Conclusion
In this blog post, we have walked through the process of installing Kubernetes with Kubeadm using Containerd as the container runtime. We started by loading the necessary kernel modules and modifying the system settings to prepare our cluster for the installation of Containerd. Then we installed Kubeadm, Kubelet, and Kubectl tools and held their versions on all instances. We initialized the cluster on the control-plane instance and set up our access to the cluster. After that, we installed the Calico network add-on to enable networking, and finally, we joined our workload nodes to the cluster.
By following the steps outlined in this blog post, you should be able to set up a Kubernetes cluster. This setup provides a robust platform for deploying and managing containerized applications at scale.
Thank you for reading this far! I hope you found this blog post informative and useful for your Kubernetes cluster deployment. I welcome any comments or feedback.
About The Author
Suraj Solanki
DevOps Engineer — II
LinkedIn: linkedin.com/in/suraj-solanki
Book your time with me at: topmate.io/suraj_solanki