Kubernetes on Raspberry Pi

Build a portable Kubernetes cluster.

Hardware

Here's the hardware I used:

You don't have to buy the exact same hardware, but make sure the switch and charging station are small enough to fit in the case.

Provision Raspberry Pis

First, find the IP addresses for each of your Raspberry Pis. There are a handful of ways to do this, one of which being nmap:

$ sudo nmap -sn 192.168.1.0/24 | grep -B2 "Raspberry Pi"
Nmap scan report for 192.168.1.1
Host is up (0.0030s latency).
MAC Address: DC:A6:32:26:2E:A1 (Raspberry Pi Trading)
--
Nmap scan report for 192.168.1.2
Host is up (0.0026s latency).
MAC Address: DC:A6:32:26:2E:A2 (Raspberry Pi Trading)
--
Nmap scan report for 192.168.1.3
Host is up (0.022s latency).
MAC Address: DC:A6:32:26:2E:A3 (Raspberry Pi Trading)
--
Nmap scan report for 192.168.1.4
Host is up (0.0043s latency).
MAC Address: DC:A6:32:26:2E:A4 (Raspberry Pi Trading)

SSH into the first Raspberry Pi and do the following:

  1. In /etc/ssh/sshd_config, set PasswordAuthentication no.
  2. In ~/.ssh/authorized_keys, paste your public SSH key(s).
  3. Pick a memorable hostname that's unique to your cluster (e.g. pi-cluster-1).
  4. In /etc/hosts, change raspberrypi to the hostname you picked.
  5. Run hostnamectl set-hostname <new-hostname>, where <new-hostname> is the hostname you picked.
  6. Run sudo reboot to restart the server.

Repeat for the other Raspberry Pis.

Set env vars

Set some env vars we'll use during the K3s installation process. Make sure that the NODE_X_IP env vars match the real IPs of your Raspberry Pis.

$ K3S_VERSION=v1.24.4+k3s1
$ CLUSTER_NAME=k8s-pi
$ NODE_1_IP=192.168.1.1
$ NODE_2_IP=192.168.1.2
$ NODE_3_IP=192.168.1.3
$ NODE_4_IP=192.168.1.4

Create server node

Install K3s on the 1st node:

$ k3sup install \
    --cluster \
    --context=$CLUSTER_NAME \
    --ip=$NODE_1_IP \
    --no-extras \
    --k3s-version=$K3S_VERSION \
    --user=pi

You should now see it as a control plane node:

$ kubectl get node
NAME           STATUS   ROLES                       AGE   VERSION
pi-cluster-1   Ready    control-plane,etcd,master   1m    v1.24.4+k3s1

Create agent nodes

Join the 2nd node as an agent:

$ k3sup  \
    join \
    --ip=$NODE_2_IP \
    --k3s-version=$K3S_VERSION \
    --server-ip=$NODE_1_IP \
    --server-user=pi \
    --user=pi

Join the 3rd node as an agent:

$ k3sup  \
    join \
    --ip=$NODE_3_IP \
    --k3s-version=$K3S_VERSION \
    --server-ip=$NODE_1_IP \
    --server-user=pi \
    --user=pi

Join the 4th node as an agent:

$ k3sup  \
    join \
    --ip=$NODE_4_IP \
    --k3s-version=$K3S_VERSION \
    --server-ip=$NODE_1_IP \
    --server-user=pi \
    --user=pi

You should now see them as non control plane nodes:

$ kubectl get node
NAME           STATUS   ROLES                       AGE   VERSION
pi-cluster-1   Ready    control-plane,etcd,master   10m   v1.24.4+k3s1
pi-cluster-2   Ready    <none>                      7m    v1.24.4+k3s1
pi-cluster-3   Ready    <none>                      4m    v1.24.4+k3s1
pi-cluster-2   Ready    <none>                      1m    v1.24.4+k3s1