Setting up a highly available Kubernetes cluster with Raspberry Pis
For anyone that wants to experiment with a highly available kubernetes cluster without shelling out a significant amount of money to a cloud provider, there’s no better way to get started than K3s. This small kubernetes distro is meant for resource-constrained devices, making it the perfect fit for a Pi. I was able to successfully run a K3s cluster on 3 x Raspberry Pi 4s with 4GB of RAM each.
There is another kubernetes distro I tried called (Microk8s) which is equally easy to setup and cluster. However, MicroK8s has greater resource requirements and recommend at least 4GB of RAM compared to K3s’ 1GB recommendation.
Setup
I started by installing Ubuntu Server 20.10 on each on each Pi. You can use the Raspberry Pi imager tool to flash a SD card/USB drive.
You will also need to enable cgroups which aren’t enabled by default. To enable this on Ubuntu, add the following snippet
cgroup_enable=memory cgroup_memory=1
to the end of the file /boot/firmware/cmdline.txt
.
Optional:
I also added all my hosts into the /etc/hosts
file. I refer to my hosts by hostname rather than IP when adding subsequent nodes. This is not necessary and you could use the node’s IP address instead.
Network Setup
I also recommend that you assign a static IP to each of your nodes to ensure they are always reachable at the same IP address on your network. I did this by configuring my router to assign a fixed IP based on the device MAC address.
Bootstrapping the first node
Run the following command on the first host to start a K3s node in server mode and to init a cluster.
curl -sfL https://get.k3s.io | sh -s - server --cluster-init
K3s ships with a built in copy of kubectl
. To use this version of kubectl
without sudo
, you can make the kubectl config readable by all users.
sudo chmod a+r /etc/rancher/k3s/k3s.yaml
You can now check the status of your cluster using kubectl
.
ubuntu@pi0:~$ k3s kubectl cluster-info
Kubernetes master is running at https://127.0.0.1:6443
CoreDNS is running at https://127.0.0.1:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
Metrics-server is running at https://127.0.0.1:6443/api/v1/namespaces/kube-system/services/https:metrics-server:/proxy
Adding additional nodes
Adding more nodes is trivial. From each additional node, run the following command replacing pi0
with the hostname for your first node.
curl -sfL https://get.k3s.io | sh -s - server --server https://pi0:6443
sudo chmod a+r /etc/rancher/k3s/k3s.yaml
And that’s it! If you now run get nodes
, you should see all your nodes listed.
ubuntu@pi0:~$ k3s kubectl get nodes
NAME STATUS ROLES AGE VERSION
pi0 Ready etcd,master 45h v1.19.4+k3s1
pi1 Ready etcd,master 45h v1.19.4+k3s1
pi2 Ready etcd,master 45h v1.19.4+k3s1
Testing the cluster
To simulate a node going offline, you can reboot one of your node. The node that’s offline will be marked as NotReady
.
ubuntu@pi0:~$ k3s kubectl get nodes
NAME STATUS ROLES AGE VERSION
pi0 Ready etcd,master 46h v1.19.4+k3s1
pi1 NotReady etcd,master 46h v1.19.4+k3s1
pi2 Ready etcd,master 46h v1.19.4+k3s1
After a while though when your node has rebooted, you should see all nodes listed as Ready once again.
Future Work
I’ll soon be posting about I use K3s’ local path provisioner for creating persistent volumes.
In the meanwhile, happy experimentation with your kubernetes cluster!