Create a Multi-Architecture k0s Cluster
By: Luc Juggery
Tags: Containers, Raspberry Pi, Programming, DevOps, Kubernetes

Adding a Raspberry PI Worker Running Alpine Linux

Alpine is a well-known Linux distribution that’s commonly used as a base image in a Dockerfile. This is also a full Linux distribution that can be installed on a workstation and many devices. In the following section, we’ll install Alpine on an RPI and join this one as a new worker node in our cluster.

Installation of Alpine on an RPI

First, we need to get the Alpine Linux release. Among the releases we can find in the download section of the official Alpine Linux website, there are some dedicated to Raspberry Pi devices. In this article’s example, we’re using the aarch64 release, as it’ll be installed on an RPI 4 (this guy is a 64-bit device).

Alpine Linux is available for many devices

Note: At the time of this writing, the current release is Alpine 3.12. The archive is downloaded in a file named alpine-rpi-3.12.3-aarch64.tar .

Next, on an empty micro SD card, we create a FAT32 partition and extract the content of the previous TAR file into that one.

Then, we can then insert the SD card into an RPI 4 and boot it.

We then run the setup-alpine utility script, which will help define the main configuration of our Alpine distribution:

Keyboard layout

Host name

The setup of the network interfaces

Root password

Time zone

NTP client

Mirrors

SSH server

Next, we need to mount the cgroups virtual filesystem.

/etc/init.d/cgroups start && rc-update add cgroups boot

We also need to remount the /media/mmcblk0p1 partition’s read-write.

mount -o remount,rw /media/mmcblk0p1

This will allow us to add specific cgroup options at the beginning of the the /cmdline.txt file:

cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1

And to add a few dependencies:

apk add iptables coreutils findutils curl

The next step is to create a new partition with the free space of the SD card.

/dev/mmcblk0p2 ext4 partition created with the free space of the SD card (cfdisk is used in this example)

After this step, our RPI will see two partitions on the SD card:

/dev/mmcblk0p1 : Boot partition

: Boot partition /dev/mmcblk0p2 : Partition we’ll use to give additional storage to k0s

As we run Alpine in RAM (another installation method could be done with a proper disk install), we need to commit our changes (with the LBU utility) so they’re available after a reboot.

lbu commit -d

Then, we can reboot the device:

reboot

Join as a worker node

First, we mount the /dev/mmcblk0p2 partition into /var/lib/k0s so k0s will have enough space to run Pods (this isn’t linked to k0s requirements but to the way we installed Alpine).

mkdir /var/lib/k0s

mount /dev/mmcblk0p2 /var/lib/k0s

Next, we install the k0s binary as we’ve done for the previous nodes. Once again, the arm64 build is automatically selected.

$ curl -sSLf get.k0s.sh | sh

Downloading k0s from URL: Downloading k0s from URL: Downloading k0s from URL: Downloading k0s from URL: https://github.com/k0sproject/k0s/releases/download/v0.9.0/k0s-v0.9.0-arm64

Next, we use the join.token file generated previously to add the Raspberry device to your cluster.

Note: As specified in the previous steps, before running this command, we need to copy the join.token file to the /tmp/join.token on this RPI.

$ k0s worker --token-file /tmp/join.token

Next, we make sure it’s there and ready.

$ kubectl get no

NAME STATUS ROLES AGE VERSION

worker1 Ready <none> 50m v1.20.1-k0s1

worker2 Ready <none> 40m v1.20.1-k0s1

worker3 Ready <none> 85s v1.20.1-k0s1

Our three-worker-nodes cluster is now up and ready. In the next step, we’ll deploy a sample application and make sure it works fine.