Deploy a Kubernetes Cluster on Ubuntu Server Using Containerd
Ever since Docker support was removed from Kubernetes, deploying a cluster on Ubuntu Server has been, shall we say, somewhat of a challenge. I’ve had many a session where I wasn’t certain if my hair would make it through the deployment or not… that’s how convoluted and problematic it can be.
But it’s not impossible.
To get Kubernetes successfully deployed on Ubuntu, you have to go with the containerd runtime engine (where you once would have depended on Docker). And that’s what I’m going to show you today.
To deploy the cluster, you’ll need at least two instances of Ubuntu Server (I’m demonstrating on Ubuntu Server 22.04) and a user with sudo privileges. That’s it. Let’s get busy.
Note: Unless otherwise indicated, the following steps will be taken on all servers.
Configure Hostnames and Host Files
The first thing we’ll do is configure the hostnames and host files for our servers. You’ll want to do this on each machine.
To change the hostname of the machine, log in and issue the command:
sudo hostnamectl set-hostname HOSTNAME
Where HOSTNAME is the name of the host (such as kubecontroller, kubenode1, kubenode2, etc.). After making this change, log out and log back in and you should see the hostname reflected in the terminal window.
Next, we’ll map hostnames to IP addresses in the host file. Open the file for editing with the command:
sudo nano /etc/hosts
At the bottom of the file, you’ll add something like this (editing it to reflect your hostnames and IP addresses):
Save and close the file.
Install the Required Software
First, we’ll install two dependencies with the command:
sudo apt-get install curl apt-transport-https -y
Next, we add the required GPG key with:
curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg|sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/k8s.gpg
We can now add the repository with the command:
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.lis
Update apt with:
sudo apt update
Install the required pieces for Kubernetes with:
sudo apt-get install wget curl vim git kubelet kubeadm kubectl -y
Finally, mark kublet, kubeadm, and kubectl so they will not be upgraded by apt in the future with:
sudo apt-mark hold kubelet kubeadm kubectl
Kubernetes requires that swap be disabled on all servers. For that, you will first temporarily disable swap with;
sudo swapoff -a
Next, disable it permanently by commenting out (adding a leading # character) the swap line in fstab. Open the file for editing with:
sudo nano /etc/fstab
Locate the swap line, add a # to the beginning of it, and save/close the file.
Enable the Necessary Kernel Modules and Adjust sysctl
For our next trick, we’ll enable the necessary kernel modules with the following commands:
sudo modprobe overlay
sudo modprobe br_netfilter
Next, we change sysctl with the command :
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
Finally, reload sysctl with:
sudo sysctl --system
It’s now time to install our runtime engine. Before we do that, we must first configure the persistent loading of the kernel modules with:
sudo tee /etc/modules-load.d/k8s.conf <<EOF
We then install a few dependencies with:
sudo apt install -y curl gnupg2 software-properties-common apt-transport-https ca-certificates
Containerd is installed from within the official Docker repo. Add the required GPG key with:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
Add the Docker repository with:
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
It’s now time to install containerd with:
sudo apt update
sudo apt-get install containerd.io -y
We’ll now configure containerd with the following commands:
sudo su -
mkdir -p /etc/containerd
containerd config default>/etc/containerd/config.toml
Restart and enable containerd with:
sudo systemctl restart containerd
sudo systemctl enable containerd
Initialize the Control Plane and the Cluster
To initialize the control plane, we must first enable kublet to start at boot with:
sudo systemctl enable kubelet
Pull down the required container images with the command:
sudo kubeadm config images pull
Finally, we can initialize the cluster with (which is done only on the controller):
sudo kubeadm init --pod-network-cidr=10.244.0.0/16
Once the cluster is initialized, it will report back the join command for you to run on each node. Before you join your nodes, however, you must first take care of a quick configuration before you join the nodes. For this, issue the following commands:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
With those configurations taken care of, copy and paste the join command to your nodes and — viola! — you have a Kubernetes cluster running on Ubuntu Server.