Skip to main content
Version: v2.0.0-rc

Deploy a Wasm Workload

In our previous tutorials, we started a developer loop and added two interfaces (wasi:logging and wasi:keyvalue) to our application. The wash dev process satisfied our application's capability requirements automatically, so we could move quickly and focus on code.

Now we'll learn how to:

  • Compile your application to a WebAssembly component binary
  • Publish your Wasm binary to an OCI registry
  • Set up a wasmCloud environment on Kubernetes and deploy your Wasm workload
Prerequisites

This tutorial assumes you're following directly from the previous steps. Make sure to complete Quickstart and Develop a WebAssembly Component first.

Build Wasm binary

Use the wash build command from the root of a project directory to compile the component into a .wasm binary:

shell
wash build

By default, the compiled .wasm binary for a Rust project is generated at /target/wasm32-wasip2/debug/. The output path for the compiled .wasm binary can be configured via wash's config.json file.

Publish image

Now we can publish a Wasm binary image to any OCI compliant registry that supports OCI artifacts.

What is this image?

The wasmCloud ecosystem uses the OCI image specification to package Wasm components—these images are not container images, but conform to OCI standards and may be stored on any OCI-compatible registry. You can learn more about wasmCloud packaging on the Packaging page.

Authenticate to registry

wash supports the usage of Docker credentials for authentication to registries. There are multiple ways to authenticate with Docker credentials, including the docker login command with the docker CLI:

shell
docker login <registry> -u <username> -p <password-or-token> 

Push image to registry

Now we'll push a Wasm component image to a registry. The example below uses GitHub Packages, but you can use any OCI compliant registry that supports OCI artifacts.

If you're following along using GitHub packages, make sure to replace <namespace> in the command below with your own GitHub namespace.

shell
wash oci push ghcr.io/<namespace>/http-hello-world:0.1.0 ./target/wasm32-wasip2/debug/http_hello_world.wasm
  • The registry address (including name and tag) is specified for the first option with wash oci push.
  • The second option defines the target path for the component binary to push.
warning

If you're using GitHub Packages, remember to make the image public in order to follow the steps below.

Install wasmCloud on Kubernetes

Installation requires the following tools:

You'll also need a Kubernetes environment. We recommend kind for the best local Kubernetes experience. (For more information on running wasmCloud on Kubernetes, see Kubernetes Operator.)

You can use the one-liner below to start a kind cluster with a configuration from the wasmcloud/wash repository.

shell
curl -fLO https://raw.githubusercontent.com/wasmCloud/wash/refs/heads/main/kind-config.yaml && kind create cluster --config=kind-config.yaml && rm kind-config.yaml

Use Helm to install the wasmCloud operator from an OCI chart image, using the values for local installation:

shell
helm install wasmcloud --version v2-canary oci://ghcr.io/wasmcloud/charts/runtime-operator -f https://raw.githubusercontent.com/wasmCloud/wash/refs/heads/main/charts/runtime-operator/values.local.yaml

Deploy Wasm workload

Now we'll deploy our Wasm application using a WorkloadDeploment manifest.

Run the following script in your terminal to create a file called deployment.yaml containing a manifest.

shell
cat > deployment.yaml << 'EOF'
  apiVersion: runtime.wasmcloud.dev/v1alpha1
  kind: WorkloadDeployment
  metadata:
    name: http-hello-world
  spec:
    replicas: 1
    template:
      spec:
        hostSelector:
          hostgroup: default
        components:
          - name: http-hello-world
            image: ghcr.io/<namespace>/http-hello-world:0.1.0
        hostInterfaces:
          - namespace: wasi
            package: http
            interfaces:
              - incoming-handler
            config:
              host: localhost
          - namespace: wasi
            package: keyvalue
            interfaces:
              - atomics
              - store
EOF

This is a deploymenty manifest for a Kubernetes custom resource. For the purposes of this quickstart, the most important fields to highlight in the specification are:

  • components.image: This defines the registry address we will use to fetch our Wasm image.
  • hostInterfaces: These are the interfaces that the host will allow the Wasm component to utilize. Without an explicit capability grant, the component will not have access to those interfaces. Since the WASI HTTP and Key-Value interfaces are well-known interfaces built in to the host, all we have to do is enable them.

Open the file and update the image name with the correct registry address. If you're using GitHub Packages, that means replacing <namespace> with your GitHub namespace.

yaml
apiVersion: runtime.wasmcloud.dev/v1alpha1
kind: WorkloadDeployment
metadata:
  name: hello-world
spec:
  replicas: 1
  template:
    spec:
      hostSelector:
        hostgroup: public-ingress
      components:
        - name: http-hello-world
          image: ghcr.io/<namespace>/http-hello-world:0.1.0
      hostInterfaces:
        - namespace: wasi
          package: http
          interfaces:
            - incoming-handler
          config:
            host: localhost

Now use kubectl to apply the manifest:

shell
kubectl apply -f deployment.yaml

Verify that the Wasm component is successfully deployed:

shell
kubectl get workloaddeployments

Use curl to invoke the Wasm workload with an HTTP request:

shell
curl localhost
text
Hello, World! x1

What's next?

Ready to take the next steps on your wasmCloud journey?

  • If you're a developer, check out the Developer Guide for more detail on the steps we explored in this quickstart.
  • If you're a platform operator, learn more about the Kubernetes Operator.