Kubernetes on Raspberry Pi
Build a portable Kubernetes cluster.
Hardware
Here's the hardware I used:
- Raspberry Pi 4 Model B (x4)
- Cluster case
- USB charging station
- USB C charging cable (x4)
- UniFi Switch Flex Mini
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:
- In
/etc/ssh/sshd_config, setPasswordAuthentication no. - In
~/.ssh/authorized_keys, paste your public SSH key(s). - Pick a memorable hostname that's unique to your cluster (e.g.
pi-cluster-1). - In
/etc/hosts, changeraspberrypito the hostname you picked. - Run
hostnamectl set-hostname <new-hostname>, where<new-hostname>is the hostname you picked. - Run
sudo rebootto 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