Calvin Hartwell
on 27 February 2019
Single-Node Kubernetes on Raspberry Pi with MicroK8s and Ubuntu
Introduction
The goal of this blog post is to explain how to setup and run Ubuntu Server on a Raspberry Pi with MicroK8s on-top to provide a single-node Kubernetes host for development and testing. In the last few months Ubuntu Server 18.04 has been ported to run the Raspberry Pi 2/3 which means we can now run snaps and other Ubuntu applications on these devices with ease.
Hardware
This deployment uses the following components:
- 1 x Raspberry Pi Version 3 Model B+
- 1 x 256gb Integral MicroSD Card (though smaller models will suffice)
- 1 x USB Keyboard
- 1 x MicroUSB PSU 5v (official PSU recommended, not phone charger)
- 1 x HDMI Cable
- 1 x MicroSD Card Reader
- 1 x Monitor/TV (preferably with HDMI Input or an adapter for HDMI)
- 1 x Raspberry Pi Case (Optional)
- 1 x USB Stick (Optional)
- 1 x Cat5/6 Network Cable (Optional)
The hardware for this setup is pretty standard: we have a regular Raspberry Pi Version 3 Model B+ with the official PSU, a USB keyboard, HDMI Cable and Network Cable for internet connectivity and remote access.
To provide persistent storage to the machine, we will use a MicroSD card. For this setup, I used an Integral 256GB MicroSD card, but a smaller one can be used. As a minimum, an 8GB or 16GB card can be used, but remember it is also used to store the Docker images which run on-top of Kubernetes.
For the initial configuration, we will need to plug the Raspberry Pi into a monitor (or a TV) to do some initial configuration, especially if you are using WiFi. It is possible to modify the Ubuntu installation on the SD card by mounting it and modifying the files directly to save time, but that is out of the scope of this article.
Getting Ubuntu & Flashing the MicroSD Card
First we need to download the Ubuntu image which is specific to your Raspberry Pi, both Model 2+3 are supported. The image used as part of this blog post is ubuntu-18.04.2-preinstalled-server-arm64-raspi3.img.xz and it can be downloaded from here: http://cdimage.ubuntu.com/releases/18.04.2/release/.
Once you’ve downloaded the image, you need to put this onto the MicroSD Card. Depending on your operating system, different tools can be used to do this. Be careful when writing the Ubuntu image to the MicroSD Card: make sure you backup the contents (if you want to keep them) and that you select the correct drive/disk:
- Windows Users (full tutorial here):
- If you’re on Windows, there are several tools you can use to write the image to the SD card. Download and install one of these tools:
- Rufus (https://rufus.ie/)
- Win32 Disk Imager (https://sourceforge.net/projects/win32diskimager/)
- Etcher (https://www.balena.io/etcher/)
- UNetbootin (https://unetbootin.github.io/)
- Once you have downloaded the image, run your tool of choice and write the image to your MicroSD Card. Some of these tools need to be run in administrator mode.
- Ubuntu/Linux Users (full tutorial here):
- If you’re on Ubuntu or another Linux distribution, most of them include tools for writing images to SD cards. On Ubuntu, the startup disk creator tool can be used, but it is also possible to use Etcher and UNetbootin if you prefer.
- Mac/OSX Users (full tutorial here):
- If you’re on Mac/OSX, you can use Etcher or UNetbootin to write the disk image to the MicroSD Card.
Once your SD card is ready, pop it into the Raspberry Pi and plug in the power supply. If your case has a built in power button, press it now. You should be greeted by an Ubuntu/Raspberry Pi boot screen like the one seen below.
Initial Configuration
Once powered up, the machine should eventually come to a login prompt. The default credentials are username Ubuntu and password Ubuntu. You should be prompted to change your password after you login, set it to something memorable.
Now it’s time to connect to the internet to download MicroK8s and any other packages or containers we want to use. The easiest way is to plug the Raspberry Pi using an ethernet cable into your router/switch. However, the Raspberry Pi 3 comes with integrated WiFi and it is possible to use this to access your machine but it is optional. In order to do this, create a config file in /etc/netplan ending in .yaml or modify the existing 50-cloud-init.yaml and add a section for wifi devices. Note: netplan is the new utility to do network configuration in Ubuntu since 16.04.
An example is given below, but make sure you replace the wifi SSID and password:
sudo vi /etc/netplan/50-cloud-init.yaml
The file contents should then be modifying using Vim (or another editor or your choice):
network:
version: 2
ethernets:
eth0:
dhcp4: true
match:
macaddress: b8:27:eb:43:07:44
set-name: eth0
wifis:
wlan0:
access-points:
<WIFI-SSID-NAME>: { password: <WIFI-PASSWORD-REPLACE-ME> }
addresses: []
dhcp4: true
nameservers: {}
Once you’ve edited the config, you can apply it using the command:
sudo netplan apply
ip a
This will enable WiFi on your Raspberry Pi. Note that any errors in your config will be reported when running this command. You can check that the interface is up by using the ip a command.
The default hostname for this release of server is Ubuntu, so I’m going to change it to something more meaningful. This step is optional:
sudo hostnamectl --static set-hostname microk8s.<yourdomain>
Unfortunately by default the memory cgroup is not enabled so the kubelet/docker will not work out of the box and we need to enable it. In order to do this, you need to modify the configuration file /boot/firmware/cmdline.txt and add the following options:
sudo vi /boot/firmware/cmdline.txt
cgroup_enable=memory cgroup_memory=1
The full line for my particular raspberry pi looks like this:
cgroup_enable=memory cgroup_memory=1 net.ifnames=0 dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
Save the file in your editor and then reboot the system using the command:
sudo reboot
Snaps are universal Linux packaging format and MicroK8s ships as a snap, so once logged in as the Ubuntu user, we first need to install the snap daemon which will allow us to run and install snap packages:
sudo apt-get install snapd
Once snapd is installed, we can now install the microk8s snap using the following command:
sudo snap install microk8s --classic
Eventually MicroK8s will be installed and ready to use. We can now deploy workloads and interact with kubernetes.
MicroK8s Basics & Deploying a Workload
In order to deploy a workload, we are going to use kubectl which is installed as part of the microk8s snap. The MicroK8s application comes with a set of pre-built commands, including a wrapper for kubectl. Kubectl is the opensource command-line tool for interacting with the API of a kubernetes cluster.
Before using the microk8s.kubectl command, first try running a couple of additional MicroK8s commands:
# The stop command will terminate microk8s services microk8s.stop
# The inspect command will give you the status of microk8s services microk8s.inspect
# The start command will start the microk8s services micok8s.start microk8s.inspect
# Enable kubednsmicrok8s.enable dns
The following command will give you the status of the cluster:
microk8s.kubectl cluster-info
Let’s deploy a test workload and then try to access it in on our command line and remotely from another machine. Run the command to deploy the cats container:
microk8s.kubectl run --image=nginx nginx --port=80 microk8s.kubectl expose deployment nginx --port 80 --target-port 80 --type ClusterIP --selector=run=nginx --name nginx-svc
# from this command, we can get the clusterIP for our container watch microk8s.kubectl get all
# you should see a line like this: service/nginx-svc ClusterIP 10.152.183.9180/TCP 82s # You can now access the container on this IP and port:wget 10.152.183.91:80 # … you should be greeted with the nginx welcome page!
You can clean-up MicroK8s installation by running the following command:
sudo microk8s.reset
Remote Access
Now your Raspberry Pi is setup, you can either interact with it directly through the monitor & keyboard you attached to it, or you can set it up for remote access to use the device from another machine. In order to access the device, it will need to be connected to your LAN so we can utilise the SSH protocol. SSH can use either a username/password combination or you can setup an SSH key which is the preferred method as it provides some added security.
If you want to access the machine using SSH, you will need to generate a public and private SSH key irrespective if you’re on Windows or Linux/OSX. If you’re on OSX/Linux, this can be generated using the command ssh-keygen command. If you’re on Windows, there is a full tutorial for using Putty to generate your SSH key available on the ubuntu tutorials website.
Once you have generated your keys, you will need to copy your public SSH key to the Raspberry Pi and add it to the authorized_keys file in /home/ubuntu/.ssh/authorized_keys. You can do this using the optional usb stick. Another method is to add your key to your github account or launchpad account and use commands like ssh-import-id-gh or ssh-import-id-lp which import your public SSH keys automatically based on your user account name on those websites.
Once setup, you should be able to remotely connect to the raspberry pi using the SSH command:
# the IP address can be found by running the IP command on the RPI
# or by logging into your home router. ssh ubuntu@<raspberrypi-ip-address>
Conclusion
In this short post, we covered setting up Ubuntu Server 18.04 with MicroK8s on a Raspberry Pi to provide a single node kubernetes cluster for development and testing purposes. This configuration should work for future releases of Ubuntu Server and Kubernetes.
As a follow-up to this blog post, we plan to deploy the Charmed Kubernetes (CK) on-top of several Raspberry Pi machines to build a bigger, n-node development cluster.
We strongly recommend reviewing the documentation (https://microk8s.io/docs/) to get better acquainted with MicroK8s. We also have an IRC channel on Freenode called #cdk8s where you can ask us questions and get support. We really appreciate users logging bugs and issues on github (https://github.com/ubuntu/microk8s/issues) as this helps us improve the project for others.