K3s Knative Ubuntu Raspberry Pi
Tags: knative, k3s, raspberrypi, ubuntu
Published: 2022-12-06 07:58:45



# K3s Knative Ubuntu Raspberry Pi

Knative is a super exciting solution for serverless and event driven applications.
Personally, I have been using it as a part of my `inner loop` development.
I can deploy dozens of workloads.
All scaled down to zero when they aren't being used.
All responding and starting up quickly when they are needed.

I ran into a couple of problems with Envoy on Raspberry Pi OS.
After investigating, it is a known issue in the Raspberry Pi OS kernel.
In order to keep going forward with my project I had to choose between fixing the kernel or trying Ubuntu.

This is an overview of how to get Knative Serving working on a Raspberry Pi device with K3s and Ubuntu.

## Install Ubuntu Server

Use RPI Imager.
Select `Ubuntu Server 22.10 64-bit` from the list of other distributions.
Boot the new image.

I was happy to see that SSH and the default user were configured as expected by using the advanced settings options.

## Upgrade the stuff

```bash
# Grab the latest repository info
sudo apt update 
# Install one prerequisite package that isn't installed by default
sudo apt install linux-modules-extra-raspi -y
# Upgrade everything that can be upgraded
sudo apt dist-upgrade -y
```

## Fix cgroup

```bash
# Add this to the beginning of /boot/firmware/cmdline.txt
# cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory
sudo nano -w /boot/firmware/cmdline.txt
```
> Reboot after making this change.
```bash
sudo shutdown -r now
```

## Install k3s via k3sup

From my laptop, not one of the Raspberry Pi nodes, run [k3sup](https://github.com/alexellis/k3sup), it's super easy.
If you haven't figured it out by now, I'm a big fan of [k3sup](https://github.com/alexellis/k3sup).

```bash
export CONTROL_NODE_IP=10.0.0.10
# Disable Traefik because we will use kourier for knative
k3sup install --ip $CONTROL_NODE_IP --user pi --k3s-extra-args '--disable traefik' --merge --local-path ~/.kube/config --context cluster00
# Knative-Serving with Kourier works on a single Raspberry Pi 4 with 8GB
# Optionally add other nodes
k3sup join --ip 10.0.0.11 --server-ip $CONTROL_NODE_IP --user pi
k3sup join --ip 10.0.0.12 --server-ip $CONTROL_NODE_IP --user pi
```

## Deep breath

This is where I struggled with how to deliver this example.
The [Knative install documentation](https://knative.dev/docs/install/yaml-install/serving/install-serving-with-yaml/) is awesome.
I've been through it dozens of times!

I tried to simplify this for you.
I want to give you the 'easy button' experience.
I created a [repository](https://github.com/dashaun/knative-serving-raspberry-pi) with all the YAML you need to deploy Knative Serving to this K3s cluster.

## Knative Serving with Kourier

```bash
git clone https://github.com/dashaun/knative-serving-raspberry-pi
cd knative-serving-raspberry-pi/operator-serving-kourier
# Use the `default` namespace in the Kubernetes cluster
kubectl config set-context --current --namespace=default
# Deploy the Knative operator
kubectl apply -f operator.yaml
# Check the deployment status
kubectl get deployment knative-operator
```
> Continue when `Ready` status is `1/1`
> ```
> NAME               READY   UP-TO-DATE   AVAILABLE   AGE
> knative-operator   1/1     1            1           19h
> ```
```bash
# Install Knative Serving custom resource and Kourier
kubectl apply -f knative-serving.yaml
# Check the custom resource status
kubectl get KnativeServing knative-serving -n knative-serving
```
> Continue when `READY` is `True`
> ```text
> NAME              VERSION   READY   REASON
> knative-serving   1.8.0     True
> ```
```bash
# Check the deployment status
kubectl get deployment -n knative-serving
```
> Continue when `READY` are all `1/1`
> ```text
> NAME                     READY   UP-TO-DATE   AVAILABLE   AGE
> activator                1/1     1            1           23m
> autoscaler               1/1     1            1           23m
> controller               1/1     1            1           23m
> domain-mapping           1/1     1            1           23m
> domainmapping-webhook    1/1     1            1           23m
> autoscaler-hpa           1/1     1            1           23m
> 3scale-kourier-gateway   1/1     1            1           23m
> webhook                  1/1     1            1           23m
> net-kourier-controller   1/1     1            1           23m
> ```

## SSLIP.IO and a Spring Boot 3 `native` application

```bash
# Install default domain
kubectl apply -f serving-default-domain.yaml
# Deploy a Spring Boot 3 `native` application
kubectl apply -f spring-boot-native-pi-service.yaml
# Get the address
kubectl get ksvc spring-boot-native-pi --output=custom-columns=NAME:.metadata.name,URL:.status.url
```
>```text
>NAME                    URL
>spring-boot-native-pi   http://spring-boot-native-pi.default.10.0.0.10.sslip.io
>```

```bash
# Curl the address provided by knative with `/actuator/health` at the end
curl http://spring-boot-native-pi.default.default.10.0.0.10.sslip.io/actuator/health
```
> Expected output:
>```text
>{"status":"UP"}
>```

## Summary

With the recent release of Spring Boot 3.0.0, my Raspberry Pi collection has become significantly more interesting.
Knative Serving allows me to deploy dozens of Spring Boot / Spring Cloud workloads to a tiny, low power device, with very exciting capabilities.

## Keep Learning

- [Knative](https://knative.dev)
- [Spring Boot](https://docs.spring.io/spring-boot/docs/current/reference/html/)
- [Knative Serving Raspberry Pi](https://github.com/dashaun/knative-serving-raspberry-pi)