This repository is a tutorial for setting up a WebAssembly demo application to be executed as a container using crun, podman, and MicroShift (OpenShift optimized for edge computing).
If you're not interested in trying out the MicroShift portion of this tutorial, you can optionally try a slightly older version of this tutorial using Fedora. If so please see the Fedora tutorial. Otherwise, the rest of this tutorial will focus on RHEL 8, as that's where MicroShift is currently supported.
Before proceeding with this tutorial, you'll need to install various dependencies listed below. We list out all of the steps but leave it up to the user if they want to separate their environments between a development environment and a deployment environment, or they could certainly be the same system.
Additionally, not all installation steps are required below. It really depends
on which deployment examples you're interested in e.g. wasmedge
, crun
,
podman
, cri-o
, MicroShift
or all of the above. So you may want to look at
the deployment options below in Run WASM App to determine
which dependencies you should install.
First you'll need a RHEL 8 installation on a VM or baremetal system. Here we focus on a VM installation using the libvirt virtualization platform.
- Download the Red Hat Enterprise Linux 8.X DVD ISO image for the x86-64
architecture from the Red Hat
Developer site and copy
the file to the
/var/lib/libvirt/images
directory. The latest RHEL 8 minor version at this time is 7. NOTE: This has only been tested on the x86-64 architecture. - Download the OpenShift pull secret from the
https://console.redhat.com/openshift/downloads#tool-pull-secret
page and save it into the
~/.pull-secret.json
file. - Run the following command to install the necessary components for the
libvirt virtualization platform and its QEMU
KVM hypervisor driver.
sudo dnf install -y libvirt virt-manager virt-install virt-viewer libvirt-client qemu-kvm qemu-img
- Run the following commands to create and run the virtual machine with the
minimum of 2 CPU cores, 2GB RAM and 20GB storage minimum. Feel free to increase the
resources if desired.
Watch the OS console of the virtual machine to see the progress of the installation, waiting until the machine is rebooted and the login prompt appears. The OS console is also accessible from the
VMNAME=microshift-starter DVDISO=/var/lib/libvirt/images/rhel-8.7-x86_64-dvd.iso KICKSTART=https://raw.githubusercontent.com/openshift/microshift/microshift-4.12.5/docs/config/microshift-starter.ks sudo -b bash -c " \ cd /var/lib/libvirt/images && \ virt-install \ --name ${VMNAME} \ --vcpus 2 \ --memory 2048 \ --disk path=./${VMNAME}.qcow2,size=20 \ --network network=default,model=virtio \ --events on_reboot=restart \ --location ${DVDISO} \ --extra-args \"inst.ks=${KICKSTART}\" \ --wait \ "
virt-manager
GUI by runningsudo virt-manager
. - Once the virtual machine installation is complete and boots to the login
prompt, you can now log into the machine either using the OS console, or
using SSH (preferred) and the user credentials
redhat:redhat
. To log in using SSH, get the IP address of the VM with the following command:sudo virsh domifaddr microshift-starter Name MAC address Protocol Address ------------------------------------------------------------------------------- vnet2 52:54:00:d6:ab:4b ipv4 192.168.122.111/24
- Set an environment variable with the IP address of the virtual machine.
RHEL_VM_IP_ADDR=192.168.122.111
- Copy over your SSH public key over to the virtual machine for passwordless
authentication.
ssh-copy-id redhat@${RHEL_VM_IP_ADDR}
- Copy your pull secret file to the MicroShift virtual machine using
redhat:redhat
credentials:scp ~/.pull-secret.json redhat@${RHEL_VM_IP_ADDR}:
- Log into the MicroShift virtual machine:
ssh redhat@${RHEL_VM_IP_ADDR} # when prompted, password is `redhat`
- Once you're logged in, register your RHEL machine and attach your
subscriptions. The credentials to use will be your username/password used
for your Red Hat account.
sudo subscription-manager register --auto-attach
Run these commands on your development machine:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup target add wasm32-wasi
The following steps should be executed on your RHEL 8 virtual machine installation.
- On RHEL 8 users should first disable the
container-tools
module in order to avoid conflicts with packages from the Copr repos:sudo dnf module disable container-tools -y
- You'll need to enable the following EPEL and Copr repos:
sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm sudo dnf copr enable -y copr.fedorainfracloud.org/rhcontainerbot/podman-next
- Then install
crun
to getcrun
built withwasmedge
support by relying on thelibwasmedge.so
shared library installed by thewasmedge
package. Here we install thecrun-wasm
RPM as it contains all the right dependencies i.e.crun
andwasmedge
. Note thatcrun-wasm
is just a symbolic link tocrun
.sudo dnf install -y crun-wasm
- Verify
crun
is installed that enables support forwasmedge
:crun --version | grep wasmedge
NOTE: Currently the way to do this is via EPEL and Copr repositories until we have official releases of these RPMs.
You'll still need crun
in order to execute the wasm app with podman
, so be
sure to install the crun
dependency in the previous step as well. Then run
the following command from your RHEL virtual machine:
sudo dnf install -y podman
On your development system or wherever you will be buildling the OCI container
image with buildah
, run the following command:
sudo dnf install -y buildah
From your RHEL virtual machine, follow the below instructions to install MicroShift and CRI-O.
-
Enable the MicroShift RPM repos and install MicroShift,
cri-o
, and theoc
andkubectl
clients:sudo subscription-manager repos \ --enable rhocp-4.12-for-rhel-8-x86_64-rpms \ --enable fast-datapath-for-rhel-8-x86_64-rpms sudo dnf install -y microshift-4.12.6 openshift-clients
-
Confgure the minimum required firewall rules:
sudo firewall-cmd --permanent --zone=trusted --add-source=10.42.0.0/16 sudo firewall-cmd --permanent --zone=trusted --add-source=169.254.169.1 sudo firewall-cmd --reload
-
Configure
cri-o
to use the pull secret:sudo cp ~redhat/.pull-secret.json /etc/crio/openshift-pull-secret
-
Configure
cri-o
to usecrun
:sudo sed -i 's/# default_runtime =.*/default_runtime = "crun"/' /etc/crio/crio.conf
-
Start the
microshift
service:sudo systemctl enable --now microshift.service
-
Enable MicroShift access for the
redhat
user account:mkdir ~/.kube sudo cat /var/lib/microshift/resources/kubeadmin/kubeconfig > ~/.kube/config
-
Finally, check if MicroShift is up and running by executing the below
oc
commands.When started for the first time, it may take a few minutes to download and initialize the container images used by MicroShift. On subsequent restarts, all the MicroShift services should take a few seconds to become available.
oc get cs oc get pods -A
This example uses rust
to compile a WebAssembly module but you can use any
supported language of choice. The following instructions are executed from your
host development system where your rust
toolchain is installed.
This example app was originally created by executing:
cargo new hello_wasm --bin
# Or if already in the root directory:
cargo init --bin
Compile the rust
app to the wasm32-wasi
target using cargo
:
cargo build --target wasm32-wasi
Use the Containerfile
provided in this repo to build a container image for
this wasm demo app workload using the below instructions.
buildah build --annotation "module.wasm.image/variant=compat" --platform wasi/wasm -t <registry>/<repo>/wasm-demo-app .
This step is only necessary if you're deploying to a different system than where you built the image.
buildah login <registry>
buildah push <registry>/<repo>/wasm-demo-app
There are several ways to run the wasm binary depending on what you're interested in and each one is documented below:
You can run the built wasm app directly with wasmedge
. This is ideal for
quick iterative development and testing.
First, copy over the built Wasm module from your host development system to the RHEL virtual machine:
scp ./target/wasm32-wasi/debug/wasm-demo-app.wasm redhat@${RHEL_VM_IP_ADDR}:
Then execute it with the following command:
wasmedge ~/wasm-demo-app.wasm
You can use crun
and a config.json
to execute your container manually.
First we need to create a directory that will house the container archive and extract the container image into it:
mkdir container-archive
cd ./container-archive/
mkdir rootfs
podman export $(podman create <registry>/<repo>/wasm-demo-app) | tar -C rootfs -xvf -
Then you'll need to generate and modify a config.json
container spec:
crun spec
sed -i 's|"sh"|"/wasm-demo-app.wasm"|' config.json
sed -i 's/"terminal": true/"terminal": false/' config.json
sed -i '/"linux": {/i \\t"annotations": {\n\t\t"module.wasm.image/variant": "compat"\n\t},' config.json
Then you can run the container with:
crun run wasm-demo-app
Additionally, you can use the container lifecycle operations:
crun create wasm-demo-app
# View the container is created and in the "created" state.
crun list
# Start the process inside the container.
crun start wasm-demo-app
# After 5 seconds view that the container has exited and is now in the stopped state.
crun list
# Now delete the container.
crun delete wasm-demo-app
You'll need to have crun
installed to execute the wasm app with podman
, so
be sure you install that first if you haven't already.
podman run --platform=wasi/wasm <registry>/<repo>/wasm-demo-app
Use the wasm-pod.yaml
Kubernetes manifest in this repository to deploy with
MicroShift. If you're using a single system for the development, building and
deployment of this example app, then skip the scp
command. Otherwise, execute
the following command from your development system to copy over the Kubernetes
manifest to your RHEL virtual machine:
scp ./wasm-pod.yaml redhat@${RHEL_VM_IP_ADDR}:
Then from your RHEL virtual machine execute the below commands:
oc apply -f ~/wasm-pod.yaml
oc get pods
oc logs -f pod-with-wasm-workload
If you're preferring to run oc
and kubectl
commands from your development
system to the system running your MicroShift cluster, then copy over the
kubeconfig
and either open up port 6443
to talk to the Kube API Server, or
use SSH port forwarding from your development system to your virtual machine
system. Both methods are documented below.
Copy over the kubeconfig
using the following commands:
mkdir ~/.kube
scp redhat@${RHEL_VM_IP_ADDR}:.kube/config ~/.kube/config
From your RHEL virtual machine, open the firewall port for the Kubernetes API
server (6443/tcp
) by running the following command:
sudo firewall-cmd --permanent --zone=public --add-port=6443/tcp && sudo firewall-cmd --reload
Then on your development system replace the server
field in your kubeconfig
file with the name or IP address of your RHEL virtual machine running
MicroShift by running the following command:
sed -i "s|server: https://127.0.0.1:6443|server: https://${RHEL_VM_IP_ADDR}:6443|" ~/.kube/config
If you don't want to open up the firewall port for the Kubernetes API server,
then forward port 6443
using SSH port forwarding by executing the following
command:
RHEL_VM_IP_ADDR=192.168.122.111
ssh -L 6443:${RHEL_VM_IP_ADDR}:6443 redhat@${RHEL_VM_IP_ADDR}
Run the following commands and verify communication is successful:
oc cluster-info
oc get pods -A