Kubernetes: Part 2: Install and Configure Ubuntu LTS 20.04 on Rasberry Pi 4 (updated for use containerd)


Update January 21st, 2021
In my original post the kubernetes cluster was setup with docker a container engine. Since docker won't be supported as a container engine for kubernetes in future versions (> 1.22) I have rewritten this blog, so containerd will be installed instead of docker. If you already have setup a kubernetes with docker as an a container engine, I written this blog on replacing docker with containerd.

- Let's Start

To start the installtion of Kubernetes on the Raspberry Pi's. You first need to prepare the Rasberry Pi's with Ubuntu LTS 20.04 as OS and install Container. I have made links to all required tools, and added videos if you don't know how to use them.

- Download and Flash Ubuntu LTS 20.04 on your SD Card
Download the image from  the  Ubuntu website (do NOT use an Ubuntu image from the Raspberry Pi Imager), since the Ubuntu can accessed via SSH out of the box. 

For the Raspberry Pi 4 the best version to use the  64-bits Ubuntu LTS 20.04.1
The Raspberry Pi Imager software to flash your SD can be found here

If you're unfamiliar on how-to flash your SD card with the Ubuntu server image check this video

- Find the IP of your Raspberry Pi
Boot your Raspberry and check your DHCP server (or router) for the IP . The client's name is ubuntu

SSH into the Raspberry (via Putty). If your unfamiliar on how the use SSH or Putty. You can watch the video below
You can download Putty for Windows here

In this tutorial we often use the linux nano to make adjustments to configuration files. You can watch the video here on same basic for nano, but in practically you will probably only use the key combinations Ctrl-O (save) and Ctrl-X (exit).

- Change computername
After you have been login via SSH (Putty) to your Raspberry Pi the first thing you want to is to change the computername. For a 3-node Raspberry Pi cluster, we use the name k8s-master, k8s-worker-01, k8s-worker-02, but you can choose whatever name you want. In the example below we will use the name k8s-master.

sudo nano /etc/hostname
The change the name "ubuntu" into "k8s-master" and save the file (Ctrl-O and Ctrl-X). All example values, which you need change with your own settings are marked in red.


- Change the network configuration from DHCP to a fixed ip.
To give the Raspberry Pi a fixed ip, run the following command.

sudo nano /etc/netplan/50-cloud-init.yaml
Change the file like the example below to give it a fixed ip address and dns servers. In the example below the fixed ip address is, the gateway is and the DNS servers are and, so change these in your own values and save the file

# This file is generated from information provided by the datasource.  Changes
# to it will not persist across an instance reboot.  To disable cloud-init's
# network configuration capabilities, write a file
# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
# network: {config: disabled}
            dhcp4: no
            addresses: []
            gateway4: ""
            optional: true
               addresses: [,]
    version: 2

Run the following command to apply the settings:
sudo netplan apply

After the setings have been applied you might lose you ssh session if you have changed the ip address. You then need to start you SSH session again with the new ip address.

- Change the hosts file
After you have change your hostname and ip address. You need to change the hosts file via the following command

sudo nano /etc/hosts
Add a 2nd line with the ip-address of your Raspberry Pi, the FQDN and the hostname like the example below. localhost k8s-master.mydomain.com k8s-master

# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts

- Configure boot options
The cmdline.txt contains the boot options of the Raspberry Pi. Similar to BIOS of a PC, so please doublecheck the adjustments you have made before rebooting the Pi.

sudo nano /boot/firmware/cmdline.txt
add the following text to the cmdline.txt

cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1 swapaccount=1

Note: Add that to the end of the first line, do not create a new line.

The cmdline.txt should like the text below

net.ifnames=0 dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=LABEL=writable rootfstype=ext4 elevator=deadline rootwait fixrtc cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1 swapaccount=1

Reboot the Raspberry Pi with the following command.

 sudo reboot
After the reboot login again via SSH.

- Create an additional account for yourself
In the example below I create a user named "erik". You can change this to the accountname of your choice. The second line will add the user to the "sudo" group, so it is allowed to use the "sudo" command.

sudo adduser erik
usermod -aG sudo erik

- Configure the prequisites for containerd
For containerd to run properly with kubernetes the modules overlay and br_netfilter need to be loaded. 

The following command will create the  containerd.conf which load these modules at startup.

cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf

You can verify if the file has been created properly via the command

cat /etc/modules-load.d/containerd.conf

The next command will load the required modules

sudo modprobe overlay
sudo modprobe br_netfilter

Add another file needs to be created for additional settings to be set on startup.

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

You can verify if the file has been created properly via the command

cat /etc/sysctl.d/99-kubernetes-cri.conf

Now, apply these settings without a reboot

sudo sysctl --system

Install the following packages to allow apt to use a repository over HTTPS. On my system these packages were already installed, but it wouldn't harm to run this command.

sudo apt-get update && sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common

The next step is to add Docker's official GPG key. Now you might think "Why do I need to do that ?". This is because containerd will (just like docker) also uses the docker container registry to retrieve it's images.

 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

The next step to add the docker repository.  Now before you that, check if the repository has not been added previously, otherwise you will see errors when you run "sudo apt update". You can check this by verifying if the file  /etc/apt/sources.list.d/docker.list exists, do not run the command below.

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/nulld.docker.com/linux/ubuntu 

 Install containerd

sudo apt-get update && sudo apt-get install -y containerd.io

Configure containerd

With commands below you will create a config folder and place the default containerd configuration in there.

sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml

Make containerd to use the systemd cgroup driver

You config this by modifing the /etc/containerd/config.toml, via the command

sudo nano /etc/containerd/config.toml

Now look for the following the line, and add the text in red, just like in the example below.

    SystemdCgroup = true

Start containerd

Now, enable and start containerd as a service, by entering the following commands.

sudo systemctl enable containerd
sudo systemctl start containerd
sudo systemctl status containerd

Test containerd (optional). 

It it not required, but if you want to test containerd, you can find the instruction 

sudo ctr image ls

You should see something like this (list of the download images)

If you want more examples to test. You can find them here

- Enable Routing
Enter the following command
sudo nano /etc/sysctl.conf
look in the sysctl.conf for the following line "#net.ipv4.ip_forward=1" and remove the "#" to uncomment it and active it.

You should something similar like this (partial file).

# Uncomment the next line to enable TCP/IP SYN cookies
# See http://lwn.net/Articles/277146/
# Note: This may impact IPv6 TCP sessions too

# Uncomment the next line to enable packet forwarding for IPv4

# Uncomment the next line to enable packet forwarding for IPv6
#  Enabling this option disables Stateless Address Autoconfiguration
#  based on Router Advertisements for this host

- Reboot again
 sudo reboot

- Install nfs client

Install nfs client for later use with persitent volumes in Kubernetes.
 sudo apt install nfs-common

Now you have prepared your Raspberry Pi for to install Kubernetes. Repeat the same steps to prepare the other Raspberry Pi's.

In the next blogpost I will install kubernetes on the prepared Raspberry Pi's.

The procedure above is based on the procedure in the follwing video  from  LearnLinuxTV.

The wiki for this video, with all the commands mentioned Wiki Kubernetes on Raspberry Pi. I have replaced the docker installation with a containerd.