Happy Dussehra! May good always win. Happy Diwali! Wishing you a bright year ahead. Merry Christmas! Warm wishes from Vizag. Happy New Year! Here’s to a great year ahead.

DevOps · CNCF daily

WasmEdge: A Lightweight WebAssembly Runtime That Runs Beside Containers

CNCF Sandbox. A small, fast WebAssembly runtime that Kubernetes can start through containerd, crun or youki, with an ahead-of-time compiler and plugins for networking and AI inference.

7 min read

CNCF Sandbox

  • WasmEdge
  • WebAssembly
  • containerd
  • runwasi
  • Kubernetes
CNCF project page

WasmEdge is a lightweight WebAssembly runtime for cloud native, edge and serverless workloads. WebAssembly modules start in milliseconds, are small, run in a sandbox that denies access by default and are portable across CPU architectures, so they suit short-lived functions, edge sites with limited hardware and plug-in style extensions. WasmEdge makes them usable on a Kubernetes cluster: through a containerd shim or an OCI runtime, a pod can run a Wasm module while neighbouring pods run ordinary Linux containers on the same node. It extends the standard WebAssembly System Interface (WASI) with sockets, an HTTP client and a plugin mechanism, including WASI-NN for machine learning inference. The project began at Second State and was accepted into the CNCF as a Sandbox project on 28 April 2021.

CNCF daily · Sprint 3, post 13 of 21 · Container Runtime

At a glance

Category Runtime › Container Runtime
CNCF status Sandbox. Accepted April 28, 2021
Written in C++ (runtime), with SDKs for Rust, Go, C, Java and others
License Apache 2.0
Execution modes Interpreter (default) and ahead-of-time (AOT) compiled native code
Kubernetes integration containerd shim from runwasi, or crun and youki with an embedded WasmEdge
Extensions Host plugins such as WASI-NN, networking and cryptography
Languages for modules Rust, C and C++, Go, JavaScript through an embedded engine, and others that compile to WebAssembly

Architecture

WasmEdge architecture: the kubelet calls containerd through CRI; containerd pulls the image from an OCI registry and, depending on the RuntimeClass and image, starts either the default runc shim for a Linux container or the WasmEdge shim from runwasi; the shim loads the Wasm module into a WasmEdge virtual machine that runs it with the interpreter or ahead-of-time compiled code and calls host plugins such as WASI-NN

Slate is Kubernetes, the registry and containerd, purple WasmEdge and grey the ordinary Linux container path. Both paths share the kubelet, the registry and containerd; only the shim and what it starts differ. Open the zoomable diagram, or download it as SVG or PNG.

Component Responsibility
kubelet Starts the pod and passes its runtimeClassName to the container runtime through CRI.
OCI registry Stores the Wasm image like any other image; the same registry and tooling work.
containerd Pulls the image and starts the shim named by the RuntimeClass handler.
runc shim The default path for ordinary Linux container images.
Linux container A normal container process that runs beside Wasm pods on the same node.
WasmEdge shim The runwasi shim that hosts WasmEdge for a pod; containerd starts one per pod.
WasmEdge VM Loads the module and runs it with the interpreter or AOT-compiled code inside a sandbox.
Host plugins Optional native extensions the module can call, such as WASI-NN for model inference.

Design principle. Reuse the container toolchain and replace only the execution layer. Images, registries, scheduling, networking and observability stay as they are; the pod just uses a different runtime handler.

Request flow

WasmEdge flow in five steps: the kubelet asks containerd to start a pod that uses the wasm RuntimeClass, containerd pulls the Wasm image from the registry, containerd starts the WasmEdge shim, the shim loads the module into a WasmEdge VM, and the module calls host plugins such as WASI-NN when it needs them

  1. CRI call. The kubelet asks containerd to create the pod. The pod’s runtimeClassName: wasm maps to the wasmedge handler configured on the node.
  2. Pull the image. containerd pulls the Wasm image from the registry, as for any other image.
  3. Start the shim. containerd starts the WasmEdge shim for this pod instead of runc.
  4. Load the module. The shim loads the module into a WasmEdge VM, which runs it in the interpreter or as AOT code inside the sandbox.
  5. Call host plugins. When the module needs a capability outside the sandbox, such as model inference, it calls a plugin the host has allowed.

Open the zoomable flow diagram, or download it as SVG or PNG.

Production reference design

A typical design adds a dedicated, labelled node pool for Wasm workloads to an existing cluster, so scheduling is explicit and Linux workloads are untouched.

  1. Prepare the nodes. Install WasmEdge and the containerd-shim-wasmedge binary from runwasi on the Wasm nodes, and register the shim in containerd (this uses the WasmEdge documentation’s configuration):
    sudo bash -c "containerd config default > /etc/containerd/config.toml"
    echo '[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.wasmedge] runtime_type = "io.containerd.wasmedge.v1"' | sudo tee -a /etc/containerd/config.toml
    sudo systemctl restart containerd
  2. Label the nodes and create the RuntimeClass:
    kubectl label nodes <node-name> runtime=wasm
    apiVersion: node.k8s.io/v1
    kind: RuntimeClass
    metadata:
      name: wasm
    scheduling:
      nodeSelector:
        runtime: wasm
    handler: wasmedge
  3. Build a Wasm image. Compile the application to WebAssembly (for example Rust to the wasm32-wasi target) and package the module as an OCI image, so the registry and CI stay unchanged. For AOT, run wasmedge compile to produce a native-code version.
  4. Run it with the runtime class, here with the WasmEdge example HTTP server:
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: http-server
    spec:
      replicas: 1
      selector:
        matchLabels: { app: http-server }
      template:
        metadata:
          labels: { app: http-server }
        spec:
          runtimeClassName: wasm
          containers:
            - name: http-server
              image: wasmedge/example-wasi-http:latest
              ports:
                - containerPort: 1234
  5. Observe and scale. Use the same metrics, logs and autoscalers as other pods; Wasm pods start fast enough to scale from zero with Knative or KEDA.

Typical uses include edge functions at sites with limited CPU and memory, serverless request handlers that must start in milliseconds, plug-ins that run untrusted code in a sandbox, and lightweight AI inference with the WASI-NN plugin.

Operational considerations

  • Not everything runs as Wasm. Programs need to compile to WebAssembly with WASI support. Threads, some system calls and many native libraries are limited, so check each dependency.
  • Interpreter versus AOT. The interpreter needs no extra step; AOT runs much faster after a compile step. The documentation shows one example about 15 times faster, so measure your own workload. AOT output from versions before 0.18.0 must be recompiled.
  • Runtime choice. The containerd shim, crun and youki all work, but they differ in how they detect Wasm images and which tools they support. Pick one per node pool and test upgrades together.
  • Isolation model. The sandbox denies access by default, but the host still shares a kernel. Grant plugins and file or network access deliberately, and keep Linux security controls on the shim process.
  • Ecosystem maturity. Debugging, profiling and library support are less developed than for Linux containers, and the WASI standard is still evolving.

Adoption

  • Docker and Microsoft back the containerd runwasi approach that WasmEdge uses, and the WasmEdge documentation describes it as the basis of Docker’s WebAssembly preview.
  • Red Hat backs crun, the OCI runtime that can embed WasmEdge.
  • Second State created WasmEdge and maintains it with the community. The repository keeps a list of other users and integrations; consult it for current named organisations, as public production references are fewer than for container runtimes.

Alternatives

Solution Model Best suited to
Linux containers (containerd, CRI-O) OCI containers on runc Almost all workloads; see the containerd brief and CRI-O brief
Wasmtime Bytecode Alliance WebAssembly runtime A standards-focused runtime with strong Rust support
Spin and SpinKube Wasm application framework for Kubernetes Developer-friendly serverless Wasm apps on Kubernetes
wasmCloud Distributed Wasm application platform Actor-style apps with a lattice network across sites
Firecracker and Kata Micro virtual machines Strong isolation for untrusted Linux code

Strengths and limitations

Strengths Limitations
Very small modules and millisecond startup Applications must compile to WebAssembly with WASI
Runs beside Linux containers in the same cluster Limited threads, system calls and native libraries
AOT compiler for near-native speed AOT adds a build step and version coupling
Plugins add networking, crypto and AI inference Smaller tooling and debugging ecosystem
Several integration paths: containerd, crun, youki Few public large-scale production references

Recommendation

Assess for most teams and Trial for edge, serverless and plug-in use cases where start time, size or sandboxing matters. Start with one dedicated node pool and a RuntimeClass, port a small stateless service and compare startup, memory and latency with its container version before widening. Keep containers as the default for applications that need full Linux libraries.

References: CNCF project page · WasmEdge website · Kubernetes with containerd and runwasi · WasmEdge repository · CNCF Landscape

Spotted something wrong or out of date?Suggest a correction. I review every suggestion before changing the page.