In this tutorial we’ll get a Lightweight kubernetes running on Raspberry Pi 4B/3B/3B+ as ARM64 and set up OpenFaaS with MongoDB.
Raspberry Pi OS (64 bit) vs Raspbian 64bit:
To avoid confusion, this article will NOT talk about Raspberry Pi 64bit OS that is currently in beta. Instead, we will focus on Raspbian which is a 32bit but is capable of ALSO running 64bit applications. I assume there are plenty of people who still run Raspbian and will keep running in the foreseeable future.
We’ll use the following software:
-
raspbian-nspawn-64
package -
k3sup
tool -
arkade
tool - OpenFaaS Platform
- MongoDB
And my hardware setup includes: A cluster of 10 x Raspberry Pi 4B with 4GB each.
Step #1: Enabling ARM64 & 64bit Userland (aka. 64bit Shell):
The default OS of Raspberry Pi (aka. Raspbian) as of now is completely 32bit, this is often abbreviated as armv7l or armhf. However, Raspberry Pi’s CPU starting from model 3B supports 64bit. In this step we will enable the 64bit kernel and setup a 64bit shell.
Thanks to the great work of sakaki's this is as easy as:
sudo apt-get update && sudo apt-get install -y raspbian-nspawn-64
You can read more about it here:
https://github.com/sakaki-/raspbian-nspawn-64.
Make sure you select ‘Yes’ in the dialog and reboot your Pi before proceeding to the next step.
Step #2: Using Docker/Containers Inside The 64bit Userland:
Since we’re use containers, we need to make some adjustments in our 64bit Userland:
In the Wiki page of the raspbian-nspawn-64 project there’s an article with a tutorial that explains how to get there:
https://github.com/sakaki-/raspbian-nspawn-64/wiki/Using-Docker-Inside-the-Container
Please follow all the instructions until the ‘Installing Docker in the 64-bit Debian Buster Container’ chapter. You can go ahead and install Docker if you want, that’s optional and can be handy but it won't be used by k3s.
Step 3#: Installing k3s (i.e., Lightweight Kubernetes) using k3sup and OpenFaaS using arakde:
Instead of getting Kubernetes (i.e., k8s) installed on our IoT edge, we’ll use k3s. k3s is a lightweight Kubernetes distribution, which is easy to install. To automate and simplify our workflow we’ll use k3sup and arkade.
Alex Ellis who wrote those great tools also wrote an excellent tutorial on how to use ‘em to bootstrap your Kubernetes (with OpenFaaS):
To avoid confusion, in our current situation you should start from the ‘Get your CLI tools’ chapter. DO NOT flash the OS image otherwise you would lose all the progress from the previous steps.
At the end of this you should have a working k3s cluster with OpenFaaS deployed and you can verify it’s indeed ARM64 by running the following command:
kubectl describe nodes
Or in short:
kubectl describe nodes | grep "Architecture"
And confirm it’s indeed:
Architecture: arm64
Step #4: Installing MongoDB:
Unfortunately arkade doesn't support installing MongoDB on ARM64, and as of now the helm charts are also not supporting ARM64. This means we’ll have to do some hacking.
We’re going to use MongoDB from Docker’s Official Images library:
https://hub.docker.com/_/mongo
That supports ARM64. We’ll base our deployment on bitnami's helm chart but make the necessary modifications as the container image is different. Copy and paste below into a mongodb.yaml
file:
# Source: mongodb/templates/svc-standalone.yaml
apiVersion: v1
kind: Service
metadata:
name: db-mongodb
namespace: default
labels:
app: mongodb
release: "db"
spec:
type: ClusterIP
ports:
- name: mongodb
port: 27017
targetPort: mongodb
selector:
app: mongodb
release: "db"
---
# Source: mongodb/templates/deployment-standalone.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: db-mongodb
namespace: default
labels:
app: mongodb
release: "db"
spec:
strategy:
type: RollingUpdate
selector:
matchLabels:
app: mongodb
release: "db"
template:
metadata:
labels:
app: mongodb
release: "db"
spec:
containers:
- name: db-mongodb
image: docker.io/library/mongo:latest
imagePullPolicy: "IfNotPresent"
env:
- name: MONGO_INITDB_ROOT_USERNAME
value: "root"
- name: MONGO_INITDB_ROOT_PASSWORD
value: "example"
- name: MONGODB_ENABLE_IPV6
value: "no"
- name: MONGODB_ENABLE_DIRECTORY_PER_DB
value: "no"
ports:
- name: mongodb
containerPort: 27017
livenessProbe:
exec:
command:
- mongo
- --eval
- "db.adminCommand('ping')"
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 6
readinessProbe:
exec:
command:
- mongo
- --eval
- "db.adminCommand('ping')"
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 6
volumeMounts:
- name: data
mountPath: /data/db
subPath:
resources:
{}
volumes:
- name: data
emptyDir: {}
The mongodb.yaml
above is not designed for production deployment. It doesn’t include persistent storage settings and has a hardcoded login and password to name a few caveats. However, it’s good enough for our proof-of-concept.
Deploying it is as easy as:
kubectl apply -f mongodb.yaml
And testing it (i.e., connecting to to MongoDB) is as easy as:
kubectl run --namespace default db-mongodb-client --rm --tty -i --restart='Never' --image docker.io/library/mongo:latest --command -- mongo admin --host db-mongodb --authenticationDatabase admin -u root -p example
The latter adopted from the NOTES.txt of bitnami’s MongoDB helm chart.
End-to-end Project:
We have taken all the steps above in order to finally be able to have storage for our OpenFaaS functions. Alex wrote an awesome tutorial on this topic here:
https://www.openfaas.com/blog/get-started-with-python-mongo/
Again, to avoid confusion, you should follow the tutorial from the ‘Create the hello-python3 function’ chapter.
Conclusions:
In this tutorial we’ve taken multiple steps to upgrade our cluster from 32bit to 64bit, quickly setup k3s with OpenFaaS, hack a MongoDB helm chart and get to a situation where we’ve got storage for our functions.
Big thanks to Alex Ellis for reviewing & contributing to this article!
Top comments (1)
Unfortunately this isn't working as is, I'll try to find an ARM64 build