In a world where containerization is becoming increasingly central, having a solid understanding of how to configure Kubernetes is essential. In this article, I’ll guide you step by step through installing a Kubernetes cluster using containerd as the runtime.
And if you’re wondering, “Why containerd?”, the answer is simple: it’s lightweight, efficient, and perfectly integrated with Kubernetes.
Recently, I received the ZimaBoard. Motivated by the excitement of experimenting, I immediately installed Proxmox and created a Kubernetes cluster with containerd as the runtime. And that’s how the idea for this article was born.
I started by creating two virtual machines. Here are the specifications:
- Operating system: Ubuntu 20.04
- CPU: 2 vCPU
- Memory: 4GB
- Disk space: 20GB
Before proceeding, let’s make sure our virtual machines can communicate with each other. Once verified, we’re ready to begin.
Installing containerd#
Containerd is the backbone of our cluster—the foundation on which all our containers will run. Let’s install it on our machines:
Prepare for installation:
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
Add Docker’s official GPG key:
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
Add the official Docker repository to our sources list:
echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Finally, install containerd:
sudo apt-get update
sudo apt-get install containerd.io -y
Installing kubeadm, kubelet, and kubectl#
These three components are the beating heart of Kubernetes. kubeadm helps us set up the cluster, kubelet ensures that all containers run correctly, and kubectl is our command-line interface for managing the cluster.
curl -fsSL https://dl.k8s.io/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
Disabling Swap#
Kubernetes prefers swap to be disabled, as it can interfere with pod scheduling, especially in low-memory scenarios.
sudo swapoff -a
sudo nano /etc/fstab
(In the editor, comment out the line referring to swap by adding a # at the beginning of the line.)
Configuring Kernel Modules#
We need to enable some Linux kernel modules to make everything work correctly.
sudo modprobe overlay
sudo modprobe br_netfilter
cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
sudo sysctl --system
Configure containerd#
Let’s make sure containerd is properly configured to interact with Kubernetes:
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd
Configuring the Control Plane#
Here comes the most exciting moment! We are about to initialize our Kubernetes cluster.
sudo systemctl enable kubelet
sudo kubeadm init --pod-network-cidr=192.168.0.0/16
(Don’t forget to write down the join command shown in the output! We’ll use it to add other nodes to the cluster.)
Installing Calico as CNI#
Calico is one of the most popular Network Interfaces for Kubernetes. It helps manage communication between pods.
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/tigera-operator.yaml
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/custom-resources.yaml
If you’ve made it this far, you now have a fully functional Kubernetes cluster with containerd as the runtime.
I hope this article has been helpful, and if you have any questions or suggestions, don’t hesitate to contact me.

