Deploy a Wasm FaaS on a Pi3 a+
Small reminder: What is Simplism?
Simplism is a highly lightweight application server that can serve WebAssembly plug-ins via HTTP as microservices speedily and straightforwardly. Simplism is cloud provider-agnostic, allowing you to deploy it anywhere, from a simple Raspberry Pi Zero to Kubernetes.
Then, it's effortless to run Simplism on a Pi, but you can do even more...
Simplism can spawn Simplism!
Simplism brings additional features: a Simplism process can serve as a service discovery, a wasm files registry, and a launcher for other Simplism processes (it's the "spawn mode"). Suppose you combine these three functionalities (along with the system for executing a plugin remotely). In that case, you get a small and simple (yet powerful) Function-as-a-service (FaaS) system that allows serving functions written in different languages. 🎉😲🤩
So, let's do that on a Pi!
This is a Pi3 A+
Pi3 A+ setup
I am not going to detail point by point how to install the OS and configure the Pi, but here are the main steps:
OS Install
First: install Pi Imager:
Run Pi Imager and choose:
Raspberry Pi device:
Raspberry Pi 3
Operating system:
Raspberry Pi OS (legacy 64-bit) lite
Edit settings and accept to prefill the wifi password
Set the hostname: for example
starfleet.local
Set username (for example:
k33g
) and passwordGo to the Services tab and enable SSH (with password)
Write data on the SD Card
Update the Pi hosts file
Edit /etc/hosts
:
sudo pico /etc/hosts
Change the first line by adding the local domain of the Pi:
127.0.0.1 localhost starfleet.local
Remote installation of Simplism on the Pi
Now you can connect to the Pi with SSH:
ssh k33g@starfleet.local
Installation of Simplism
In a terminal from the host, run the following command:
ssh k33g@starfleet.local '
SIMPLISM_DISTRO="Linux_arm64"
VERSION="0.1.2"
wget https://github.com/bots-garden/simplism/releases/download/v${VERSION}/simplism_${SIMPLISM_DISTRO}.tar.gz -O simplism.tar.gz
sudo tar -xf simplism.tar.gz -C /usr/bin
rm simplism.tar.gz
simplism version
mkdir -p wasm-files
mkdir -p tmp
'
In the end, you should see this message: simplism v0.1.2 🌍 [earth]
Start Simplism as a FaaS
When you run Simplism as a FaaS, every Simplism process instance will download the Wasm plug-ins remotely. That means you have published the WASM files somewhere, for example, as an asset of a GitHub release, as an item of a GitLab generic package registry, etc...
So, we need to serve the WASM files; for that, we can use the "registry mode" of Simplism.
Start the Registry (always first)
Type the following command:
ssh k33g@starfleet.local -f '
simplism listen ? ? \
--http-port 9000 \
--log-level info \
--information "📦 registry service" \
--registry-mode true \
--registry-path ./wasm-files
'
You should get this message:
🐳 small wasm registry activated
🌍 http server is listening on: 9000
You can check the registry install with this request:
curl http://starfleet.local:9000
# you should get this message
🖖 Live long and prosper 🤗
Start the Spawner
We will start a Simplism instance in "spawn mode". That means we can send requests to this instance to spawn a new Simplism process.
Type the following command:
ssh k33g@starfleet.local -f '
simplism listen ? ? \
--http-port 7000 \
--log-level info \
--service-discovery true \
--information "🚀 spawner service" \
--spawn-mode true \
--http-port-auto true
'
You should get something like this:
😡 Error deleting the db file: remove scratch.wasm.processes.db: no such file or directory
🔎 discovery mode activated: /discovery ( 7000 )
🚀 this service can spawn other services
🛟 recovery mode activated recovery.yaml
😡 reading the recovery file: open recovery.yaml: no such file or directory
🌍 http server is listening on: 7000
The error messages are "normal": Simplism has a recovery mode to relaunch the WASM services in case of crash or stop/restart. As it's the first launch, there is nothing to re-start.
You can check if the Simplism Spawner is running:
curl http://starfleet.local:7000
# you should get: 🖖 Live long and prosper 🤗
Create and build the WASM plug-ins to deploy
To create and build WASM plug-ins for Simplism, read this blog post: Getting started simple with Simplism.
Then, create some plugins, or you can download these ones:
wget https://github.com/simplism-registry/hello-world/releases/download/v0.0.1/hello-world.wasm
wget https://github.com/simplism-registry/small-cow/releases/download/v0.0.0/small-cow.wasm
wget https://github.com/simplism-registry/small-ant/releases/download/v0.0.0/small_ant.wasm
Download links:
Publish the wasm files to the Simplism registry
To upload hello-world.wasm
to the registry, use the following command:
curl http://starfleet.local:9000/registry/push \
-F 'file=@hello-world.wasm'
You should get this output:
📝 uploaded file: ./wasm-files/hello-world.wasm
📐 file size: 194646
📙 MIME header: map[Content-Disposition:[form-data; name="file"; filename="hello-world.wasm"] Content-Type:[application/octet-stream]]
🎉 hello-world.wasm successfully uploaded!
Publish the two other files:
curl http://starfleet.local:9000/registry/push \
-F 'file=@small-cow.wasm'
curl http://starfleet.local:9000/registry/push \
-F 'file=@small_ant.wasm'
The Simplism registry exposes an API to get the list of the published WASM files:
curl http://starfleet.local:9000/registry/discover \
-H 'content-type:text/plain; charset=UTF-8'
If you prefer a JSON output, you need to change the content type header of the request:
curl http://starfleet.local:9000/registry/discover \
-H 'content-type:application/json; charset=UTF-8'
If you want to upload a WASM file with another name (it's helpful to publish several versions of the same plug-in), use this request:
curl http://starfleet.local:9000/registry/push \
-F 'file=@hello.wasm;filename=hello.0.0.1.wasm'
You can delete files and even protect the registry with a token (see the documentation 📝 Use the registry mode).
Now, it's time to deploy and serve the plug-ins.
Deploy WASM functions (plug-ins)
To deploy the hello-world.wasm
plug-in and serve it as an HTTP function, use the following command:
curl -X POST \
http://starfleet.local:7000/spawn \
--data-binary @- << EOF
{
"wasm-file":"./tmp/hello-world.wasm",
"wasm-function":"handle",
"wasm-url": "http://starfleet.local:9000/registry/pull/hello-world.wasm",
"discovery-endpoint":"http://starfleet.local:7000/discovery",
"service-name": "hello-world"
}
EOF
You should get the following output:
🚀 process spawned: hello-world 🚀 hello-world spawned [ 125972 ]
🌍 downloading http://starfleet.local:9000/registry/pull/hello-world.wasm ...
2024/01/21 15:52:43 📝 wasm file written : 194646
👋 this service is discoverable
🌍 http server is listening on: 33989
The WASM file has been downloaded from the registry to the tmp
directory, and then a Simplism server (serving the WASM file) has been started listening on 33989
.
Now, deploy the two other wasm files:
curl -X POST \
http://starfleet.local:7000/spawn \
--data-binary @- << EOF
{
"wasm-file":"./tmp/small-cow.wasm",
"wasm-function":"handle",
"wasm-url": "http://starfleet.local:9000/registry/pull/small-cow.wasm",
"discovery-endpoint":"http://starfleet.local:7000/discovery",
"service-name": "small-cow"
}
EOF
curl -X POST \
http://starfleet.local:7000/spawn \
--data-binary @- << EOF
{
"wasm-file":"./tmp/small-ant.wasm",
"wasm-function":"handle",
"wasm-url": "http://starfleet.local:9000/registry/pull/small_ant.wasm",
"discovery-endpoint":"http://starfleet.local:7000/discovery",
"service-name": "small_ant"
}
EOF
It's possible to protect the spawner and discovery service with tokens, see the documentation 📝 Spawn mode and Discovery Mode (the spawner can act at the service discovery).
Discovering the services
To get the list of the running services, use the following request:
curl http://starfleet.local:7000/discovery \
-H 'content-type:text/plain; charset=UTF-8'
You should get the following output:
Change the value of the content type header if you want a JSON output:
curl http://starfleet.local:7000/discovery \
-H 'content-type:application/json; charset=UTF-8'
Call the services
Call the hello-world
service with this request:
curl http://starfleet.local:7000/service/hello-world \
-H 'content-type: application/json; charset=utf-8' \
-d '{"firstName":"Bob","lastName":"Morane"}'
Call the small-cow service with the following request:
curl http://starfleet.local:7000/service/small-cow \
-d '👋 Hello World 🌍'
Call the small-ant service with the following request:
curl http://starfleet.local:7000/service/small_ant \
-d '✋ Hey people 🤗'
And, of course, you can delete (un-deploy) a service with this command:
curl -X DELETE http://starfleet.local:7000/spawn/name/hello-world
In production, you can protect this with an authentication token
That is all for today. Simplism brings a lot of other features. Right now, I'm working on improving the documentation, the structure of the samples and a set of scripts to ease the use of the spawn mode.
Have fun with your Raspberry PI.😊
The FaaS is running on bare metal here:
Subscribe to my newsletter
Read articles from Philippe Charrière directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by