K3s on Raspberry Pi and ClusterHat
Tags: raspberrypi, k3s, kubernetes, clusterhat
Published: 2022-07-22 23:28:40

---
title: K3s on Raspberry Pi and ClusterHat
published: true
date: 2022-07-22 21:42:08 UTC
tags: ["raspberrypi","k3s","kubernetes","clusterhat"]
canonical_url: https://dashaun.com/posts/k3s-on-raspberry-pi-clusterhat/
cover_image: "https://dashaun.com/posts/k3s-on-raspberry-pi-clusterhat/devto.png"
series: Knative Raspberry Pi
---

## Learn how to deploy [k3s](https://k3s.io) to a Raspberry Pi cluster with [ClusterHat](https://clusterhat.com/) and [ClusterCTRL](https://clusterctrl.com/). 

### Hardware 

- 1 x 8GB Raspberry Pi 4
- 4 x Raspberry Pi Zero 2 W
- 1 x ClusterHat v2.5
- 5 x [SD Card](https://www.sdcard.org/)

### Custom OS Images 

Because you are using a ClusterHat, you will want to use [custom OS images](https://clusterctrl.com/setup-software). For this guide you will be using the 64-bit versions of each and the `CNAT Lite` version for the controller. Enable SSH for each of the images. The username does not have to be `pi` but the username needs to be the same, across each of the nodes, for this guide. As you burn each of the SD Cards, place each one into their respective device, to keep them organized. The P1 node is the slot that is on the same side as the ethernet controller. The nodes increase, in order, to P4, which is on the same side as the power and HDMI connectors. You can refer to [an earlier post](https://dev.to/dashaun/spring-native-edge-rpi-5c7), for detailed steps using [Raspberry Pi Imager](https://www.raspberrypi.org/software/) to create the SD Cards.

### First Boot 

With each SD card inserted into their respective nodes, you can turn on the control node. The ClusterHat will provide power and networking to the additional nodes. Power for each of the nodes can be controlled independently. You can connect to the device over SSH via WIFI, or via ethernet, depending on what you enabled in the previous step.

Connect to the control node and power on P1:

```
pi@control-node:~ $ clusterctrl on p1

```

> You will see the green LED light up and the node will begin booting up.

Power up the other nodes:

```
pi@control-node:~ $ clusterctrl on p2 && clusterctrl on P3 && clusterctrl on p4

```

### Update the OS Images 

Update each of the images, from the upstream repositories, to get any of the changes made since the OS image was released.

Start with the control node:

```
pi@control-node:~ $ sudo apt update && sudo apt dist-upgrade -y

```

Optionally, add the following lines to /etc/hosts, on the control node:

```
172.19.181.1	p1
172.19.181.2	p2
172.19.181.3	p3
172.19.181.4	p4

```

> You can also use the IP address directly.

Update each of the additional nodes via ssh:

```
pi@control-node:~ $ ssh p1 'sudo apt update && sudo apt dist-upgrade -y'
pi@control-node:~ $ ssh p2 'sudo apt update && sudo apt dist-upgrade -y'
pi@control-node:~ $ ssh p3 'sudo apt update && sudo apt dist-upgrade -y'
pi@control-node:~ $ ssh p4 'sudo apt update && sudo apt dist-upgrade -y'

```

At the time of writing this article, an additional change is required for the base OS on each node. This change is needed in order to run containers, as the defaults for cgroups has changed recently.

Add the following configuration to `/boot/cmdline.txt` on each node and then reboot:

```
cgroup_memory=1 cgroup_enable=memory

```

### Ready for k3s 

The documentation for [k3s](https://k3s.io/) is incredible. For this guide, you will use another tool called `k3sup` to deploy the k3s cluster.

First install k3sup:

```
pi@control-node:~ $ sudo curl -sLS https://get.k3sup.dev | sh

```

Install the control node of k3sup:

```
pi@control-node:~ $ k3sup install --ip 172.19.181.254 --user $(whoami)

```

That process will end with output similar to this:

```
...
Saving file to: /home/pi/kubeconfig

# Test your cluster with:
export KUBECONFIG=/home/pi/kubeconfig
kubectl config set-context default
kubectl get node -o wide
pi@control-node:~ $

```

After setting up your context and verifying your control node is ready, add the other nodes to the cluster.

```
pi@control-node:~ $ k3sup join --ip 172.19.181.1 --server-ip 172.19.181.254 --user $(whoami)
pi@control-node:~ $ k3sup join --ip 172.19.181.2 --server-ip 172.19.181.254 --user $(whoami)
pi@control-node:~ $ k3sup join --ip 172.19.181.3 --server-ip 172.19.181.254 --user $(whoami)
pi@control-node:~ $ k3sup join --ip 172.19.181.4 --server-ip 172.19.181.254 --user $(whoami)

```

You now have a kubernetes cluster, deployed to about $100 of hardware.

```
pi@control-node:~ $ kubectl get node
NAME STATUS ROLES AGE VERSION
control-node Ready control-plane,master 25m v1.24.3+k3s1
p1 Ready <none> 20m v1.24.3+k3s1
p2 Ready <none> 20m v1.24.3+k3s1
p3 Ready <none> 22m v1.24.3+k3s1
p4 Ready <none> 19m v1.24.3+k3s1
pi@control-node:~ $

```

### Test deployment 

Deploy [an ARM64 native Spring Boot application](https://dev.to/dashaun/spring-boot-263-arm64-image-afo) to the cluster:

Create a file, spring-boot-native-pi.yaml

```
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-boot-native-pi
spec:
  selector:
    matchLabels:
      app: springbootnativepi
  replicas: 4
  template:
    metadata:
      labels:
        app: springbootnativepi
    spec:
      containers:
      - name: springbootnativepi
        image: dashaun/spring-pi-native:focal-arm64
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  selector:
    app: springbootnativepi
  ports:
    - protocol: TCP
      port: 8080

```

Verify:

```
pi@control-node:~ $ kubectl get pods
NAME READY STATUS RESTARTS AGE
spring-boot-native-pi-59f7d7659c-hvlp8 1/1 Running 0 42m
spring-boot-native-pi-59f7d7659c-dp7nn 1/1 Running 0 42m
spring-boot-native-pi-59f7d7659c-sf899 1/1 Running 0 42m
spring-boot-native-pi-59f7d7659c-99vfq 1/1 Running 0 42m
pi@control-node:~ $
```

### Summary 

In this guide, you learned how to deploy k3s on top of the custom OS images provided by ClusterHat, with Raspberry Pi.