
Deploying WASM Applications to Kubernetes with SpinKube
Introduction
SpinKube is an open-source platform that enables native execution of WebAssembly (wasm) applications on Kubernetes.
Unlike traditional container-based approaches, SpinKube leverages Wasm's fast startup and sandbox environment characteristics to provide new workload options in k8s.
This article explains everything from SpinKube's basic concepts to actual deployment.
SpinKube?
SpinKube is a platform for running Fermyon's Spin framework in Kubernetes environments.
By the way, my previous article about the Spin framework is available here.
SpinKube combines k8s, wasm, and spin to integrate wasm apps as native functions of k8s.
SpinKube's Main Components
SpinKube consists of the following components:
-
Spin Operator
Uses the k8s operator pattern to manage the lifecycle of Spin applications.
An operator is a k8s extension program that automatically manages custom resources. -
SpinApp CRD
A custom resource definition for defining Spin applications.
CRD (Custom Resource Definition) is a mechanism for adding new resource types to k8s. -
SpinAppExecutor
Defines how Spin applications are executed.
There are two execution methods: containerd-shim-spin which executes WASM directly on the node.
It's high-performance but complex to configure.
Spintainer runs Spin in a container.
This has the advantage of simpler configuration.
SpinKube's Features
SpinKube offers lightweight and fast startup benefits.
Being WASM, images are smaller than traditional ones, saving resources.
Startup is fast with no scaling issues.
Security is also ensured by the Wasm sandbox model.
Environment
- MacBook Pro (14-inch, M3, 2023)
- OS : MacOS 14.5
- Node : 20.19.0
- Kubernetes: v1.26+ (containerd v1.6.26+/v1.7.7+)
Required Tools
You need to install the following tools:
# Kubernetes related
- kubectl (Kubernetes CLI)
- Helm v3 (Kubernetes package manager)
# Development tools
- Docker / Colima
- k3d or Kind (for local Kubernetes clusters)
# Spin tools
- spin CLI (for Spin application development)
- Rust toolchain (when developing Rust applications)
In this article, we will use k3d for local environment setup.
Setup
Let's begin setting up the SpinKube environment.### 1. Installing Required Tools
Install k8s-related tools.
Docker/colima are also required.
% brew install kubectl helm k3d
# Docker / Colima
% brew install --cask docker
# or
% brew install colima
Let's also install Spin and the Rust environment.
# Spin CLI
% curl -fsSL https://developer.fermyon.com/downloads/install.sh | bash
% sudo mv spin /usr/local/bin/
# Rust (for Spin app development)
% curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
2. Creating a k3d Cluster
Create a k3d cluster. To avoid DNS resolution issues,
set the K3D_FIX_DNS=0
environment variable:
% K3D_FIX_DNS=0 k3d cluster create spinkube-cluster \
--port "8081:80@loadbalancer" \
--agents 2
This command creates a standard k3d cluster.
3. Installing SpinKube
Set up the SpinKube environment.
cert-manager (Certificate Management)
cert-manager is a tool that automates certificate issuance and renewal within k8s.
It's necessary to ensure secure communication between SpinKube components.
# Install cert-manager
% kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.5/cert-manager.yaml
# Wait for cert-manager to start
% kubectl wait --for=condition=ready --timeout=300s -n cert-manager pod --all
RuntimeClass (Execution Environment Definition)
RuntimeClass specifies which container runtime a Pod should use.
This defines how WASM workloads will be executed.
# Apply RuntimeClass
# Specify containerd-shim-spin
% kubectl apply -f https://github.com/spinkube/containerd-shim-spin/releases/download/v0.19.0/runtime-class-manager.yaml
SpinApp CRD (Custom Resource Definition)
CRDs add new resource types to k8s.
This allows Spin apps to be treated as native k8s resources.
# Apply CRDs
% kubectl apply -f https://github.com/spinkube/spin-operator/releases/download/v0.5.0/spin-operator.crds.yaml
Spin Operator (Application Management)
Spin Operator automatically manages the lifecycle of Spin applications.
Install it using Helm.
# Install Spin Operator
% helm install spin-operator \
oci://ghcr.io/spinkube/charts/spin-operator \
--namespace spin-operator \
--create-namespace \
--version 0.5.0 \
--wait
```### 4. Setting up the Spintainer Executor
We will configure an Executor to run Spin applications.
Previously, we specified containerd-shim-spin in the RuntimeClass.
This defines the execution environment available across the entire cluster.
The Executor specifies "the actual execution method" for each application.
In this case, we'll use `spintainer`.
Let's create the spintainer-executor.yaml.
```yaml
apiVersion: core.spinkube.dev/v1alpha1
kind: SpinAppExecutor
metadata:
name: spintainer
spec:
createDeployment: true
deploymentConfig:
installDefaultCACerts: true
spinImage: ghcr.io/fermyon/spin:v3.0.0
Let's apply the Executor.
% kubectl apply -f spintainer-executor.yaml
5. Installing the spin kube plugin
Install the plugin needed for developing and deploying Spin applications.
% spin plugins install kube --yes
Try
Now, let's create and run an actual Spin application.
1. Creating a Spin application
Let's create a simple HTTP app.
% spin new -t http-rust hello-spinkube --accept-defaults
2. Implementation
Implement the API endpoint in src/lib.rs
.
This is a simple Hello World level example.
use spin_sdk::http::{IntoResponse, Request, Response};
use spin_sdk::http_component;
#[http_component]
fn handle_hello_spinkube(req: Request) -> anyhow::Result<impl IntoResponse> {
let path = req.uri().path();
let response = match path {
"/" => "Welcome to SpinKube!",
"/hello" => "Hello from WebAssembly running on Kubernetes!",
"/health" => "OK",
_ => "Not Found",
};
Ok(Response::builder()
.status(200)
.header("content-type", "text/plain")
.body(response)
.build())
}
3. Building & pushing the app
Add the WASM target if you haven't already done so.
After that, build and push to the OCI repository.
# Add WASM target (first time only)
% rustup target add wasm32-wasip1
# Build
% spin build
# Push to OCI registry (ttl.sh is a registry valid for 1h)
% export IMAGE_NAME=ttl.sh/hello-spinkube-$(uuidgen):1h
% spin registry push $IMAGE_NAME
```### 4. Generating k8s manifests
Let's generate the manifest (YAML describing k8s configuration).
```bash
% spin kube scaffold --from $IMAGE_NAME > spinapp.yaml
Edit the generated manifest as follows:
(Change executor
to spintainer
)
apiVersion: core.spinkube.dev/v1alpha1
kind: SpinApp
metadata:
name: hello-spinkube
spec:
image: "ttl.sh/hello-spinkube-xxx:1h" # Replace with your actual image name
executor: spintainer # Changed from containerd-shim-spin
replicas: 2
5. Testing functionality
Let's run it locally.
% spin up --listen 127.0.0.1:3000
Verify with curl. You should see something like this:
% curl http://127.0.0.1:3000/
Welcome to SpinKube!
% curl http://127.0.0.1:3000/hello
Hello from WebAssembly running on Kubernetes!
% curl http://127.0.0.1:3000/health
OK
6. Deploy to SpinKube
Now let's deploy the Spin app to k8s.
# Deploy SpinApp
% kubectl apply -f spinapp.yaml
% kubectl get spinapp
% kubectl get pods -l core.spinkube.dev/app-name=hello-spinkube
Wait for the Pod to start up.
% kubectl wait --for=condition=ready pod -l \
core.spinkube.dev/app-name=hello-spinkube --timeout=120s
7. Access
Let's create an ingress.yaml to access the application.
Ingress controls access from outside the cluster to Services within the cluster.
The following configuration sets up domains, paths, and forwarding information.
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-spinkube
annotations:
ingress.kubernetes.io/ssl-redirect: "false"
spec:
rules:
- host: hello-spinkube.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: hello-spinkube
port:
number: 80
The above configuration means that when there's an access to:
it will be forwarded to the hello-spinkube service within the cluster.Don't forget to apply:
% kubectl apply -f ingress.yaml
Let's verify with curl.
This confirms that the Spin app is running properly on k8s.
% curl -H "Host: hello-spinkube.local" http://localhost:8081/
Welcome to SpinKube! Your WebAssembly app is running on Kubernetes!
```## Summary
SpinKube is a platform for running WASM apps in k8s.
By combining WASM and k8s, you can build applications with excellent
performance and security.
As a new alternative to traditional container technology,
please consider SpinKube.
## References
- [SpinKube](https://www.spinkube.dev/)
- [Introducing Spin](https://developer.fermyon.com/spin/index)
- [WASI.dev](https://wasi.dev/)
- [SpinKube GitHub Repository](https://github.com/spinkube/spin-operator)
- [Kubernetes Documentation](https://kubernetes.io/docs/home/)
- [containerd-shim-spin](https://github.com/spinkube/containerd-shim-spin)
- [Fermyon Blog: Introducing SpinKube](https://www.fermyon.com/blog/introducing-spinkube-fermyon-platform-for-k8s)