58 Dispatches · 5 Desks · 68 Topics · 3 Series

Unofficial Azure Club

“IaaS, PaaS, Cloud Native, Kubernetes, Everything is possible in this website :)”



Cloud Native C15

Run WASM applications from Kubernetes

Run WASM applications from Kubernetes
  • Interested in running WASM workloads from Kubernetes?
  • Interested in enabling your Kubernetes cluster to support multiple container shims?
  • Even better, interested in WASM with Dapr support?

The steps documented here help run WASM workloads from a Kubernetes cluster, based on great work from:

Sample applications and deployment manifests are located in this repo.

The prerequisites are below:

  • A Kubernetes cluster whose nodes can be accessed directly to install shims and configure containerd. For managed Kubernetes clusters, a potential workaround is to use a DaemonSet to install the shim and configure containerd. Some Kubernetes distributions, such as AKS, already provide a preview feature to enable WASM support.

WasmEdge Containerd Crun Shims

The WasmEdge containerd shim is based on the crun project. To bake the WasmEdge runtime into crun, we need to add WasmEdge to the Kubernetes cluster and build crun with WasmEdge support manually.

Install WasmEdge

Install WasmEdge on a Kubernetes node.

curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | sudo bash -s -- -p /usr/local

Build crun with WasmEdge support

Install building tools and libraries

sudo apt update
sudo apt install -y make git gcc build-essential pkgconf libtool \
    libsystemd-dev libprotobuf-c-dev libcap-dev libseccomp-dev libyajl-dev \
    go-md2man libtool autoconf python3 automake

Next, configure, build, and install a crun binary with WasmEdge support.

git clone https://github.com/containers/crun
cd crun
./autogen.sh
./configure --with-wasmedge
make
sudo make install

Map the runtime type to the shim binary.

vi /etc/containerd/config.toml
        [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.crun]
          runtime_type = "io.containerd.runc.v2"
          privileged_without_host_devices = false
          pod_annotations = ["*.wasm.*", "wasm.*", "module.wasm.image/*", "*.module.wasm.image", "module.wasm.image/variant.*"]
          [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.crun.options]
            BinaryName = "crun"
systemctl restart containerd
systemctl status containerd

Add a RuntimeClass to support the WasmEdge crun containerd shim from the Kubernetes cluster.

# wasmedge-crun-v2.yaml
apiVersion: node.k8s.io/v1
handler: crun
kind: RuntimeClass
metadata:
  name: wasmedge-crun
scheduling:
  nodeSelector:
    kubernetes.azure.com/wasmedge-crun: "true"

Add labels to Kubernetes nodes to mark them as supporting WasmEdge workloads.

kubectl apply -f wasmedge-crun.yaml
kubectl label nodes <NODE> kubernetes.azure.com/wasmedge-crun=true

Deploy sample WASM application

kubectl apply -f https://raw.githubusercontent.com/huangyingting/wasm/main/deploy/rust-wasmedge.yaml

To test the WASM application, open two terminal windows. In the first terminal window, run:

kubectl port-forward svc/rust-wasmedge 8080:80

In the second terminal window, run the following command and notice that the request is echoed back:

curl http://localhost:8080

# HTTP response by WASM echo application
:method: GET
Host: localhost:8080
User-Agent: curl/7.81.0
Accept: */*

Deis Labs Containerd Wasm Shims

Deis Labs provides two great containerd shims:

Install Deis Labs Containerd Wasm Shims

Using a shim in Kubernetes has brief steps to install Deis Labs containerd WASM shims.

Here are more detailed steps.

Install containerd shims on a Kubernetes node.

RELEASE=v0.9.1
wget -qO- https://github.com/deislabs/containerd-wasm-shims/releases/download/$RELEASE/containerd-wasm-shims-v1-slight-linux-x86_64.tar.gz | sudo tar -xvz -C /usr/local/bin
wget -qO- https://github.com/deislabs/containerd-wasm-shims/releases/download/$RELEASE/containerd-wasm-shims-v1-spin-linux-x86_64.tar.gz | sudo tar -xvz -C /usr/local/bin

Add the following to the containerd /etc/containerd/config.toml (The default configuration can be generated by running containerd config default) that maps the runtime type to the shim binary,

vi /etc/containerd/config.toml
        [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.spin]
          runtime_type = "io.containerd.spin.v1"
        [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.slight]
          runtime_type = "io.containerd.slight.v1"
systemctl restart containerd
systemctl status containerd

Add RuntimeClass resources to support Spin and Slight from the Kubernetes cluster.

# runtimeclass.yaml
apiVersion: node.k8s.io/v1
handler: slight
kind: RuntimeClass
metadata:
  name: wasmtime-slight
scheduling:
  nodeSelector:
    kubernetes.azure.com/wasmtime-slight: "true"
---
apiVersion: node.k8s.io/v1
handler: spin
kind: RuntimeClass
metadata:
  name: wasmtime-spin
scheduling:
  nodeSelector:
    kubernetes.azure.com/wasmtime-spin: "true"

Label Kubernetes nodes to support Spin and Slight workloads.

kubectl apply -f runtimeclass.yaml
kubectl label nodes <NODE> kubernetes.azure.com/wasmtime-slight=true
kubectl label nodes <NODE> kubernetes.azure.com/wasmtime-spin=true

Deploy sample WASM application

kubectl apply -f https://raw.githubusercontent.com/huangyingting/wasm/main/deploy/go-spin.yaml

To test the WASM application, open two terminal windows. In the first terminal window, run:

kubectl port-forward svc/go-spin 8080:80

In the second terminal window, run the following command and notice that the request is echoed back:

curl http://localhost:8080

# HTTP response by WASM echo application
GET / HTTP/1.1
Host: localhost:8080
Accept: */*
Spin-Base-Path: /
Spin-Component-Route: 
Spin-Full-Url: http://localhost:8080/
Spin-Matched-Route: /...
Spin-Path-Info: /
Spin-Raw-Component-Route: /...
User-Agent: curl/7.81.0

arch: wasm
os: linux
version: v0.1.0

Sample applications

This repo also provides a few sample applications for running WASM applications from a Kubernetes cluster.

  • dotnet-spin, a simple WASM http echo server written on c# language
  • go-spin, a simple WASM http echo server written on golang language
  • rust-wasmedge, a simple WASM http echo server written on rust language

Build and deploy

This repo has GitHub Actions workflows to build and push images to ghcr.io. Check .github/workflows/build-spin-images.yaml and .github/workflows/build-wasmedge-images.yaml to see how those WASM container images are built.

deploy directory has all the Kubernetes manifests to deploy sample applications.

To run applications locally, you need:

  • Rust
  • .NET 7.0 SDK
  • Go
  • TinyGo
  • spin
  • WasmEdge
    To run spin application, change directory to go-spin or dotnet-spin, run spin build and spin up
    To run WasmEdge application, change directory to rust-wasmedge, run
rustup target add wasm32-wasi
cargo build --release --target wasm32-wasi
wasmedge target/wasm32-wasi/release/rust-wasmedge.wasm

rust-wasmedge also supports Dapr. To add a Dapr sidecar, add the following annotations to deploy/rust-wasmedge.yaml:

...
      annotations:
        module.wasm.image/variant: compat-smart
        # Dapr support
        dapr.io/enabled: "true"
        dapr.io/app-id: "rust-wasmedge"
        dapr.io/app-port: "80"