Deploy with Google Kubernetes Engine
Overview
This deployment guide demonstrates how to deploy wasmCloud to a Kubernetes cluster using Google Cloud's Google Kubernetes Engine (GKE) service, and then run wasmCloud applications built from WebAssembly components.
To follow the guide, you will need an account for Google Cloud. In this example, we will use the gcloud
CLI and GKE Autopilot.
To follow this guide, you should have Persistent Disk SSD (GB) quota of around 750 GB (which will require a quota increase for new Google Cloud accounts).
Set up your CLI tools
This guide uses the Google Cloud CLI tool, kubectl
, Helm, and the wasmCloud Shell (wash
) CLI.
Install kubectl
Install the kubectl
CLI for Kubernetes cluster management.
On macOS, you can use Homebrew:
brew install kubernetes-cli
On Linux systems, you can use curl
to download the latest release:
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
Use chmod
to make the kubectl
binary executable:
chmod +x ./kubectl
Add the binary to your PATH:
sudo mv ./kubectl /usr/local/bin/kubectl
Install Helm
Helm serves as a package manager for Kubernetes. Follow the instructions on the Helm install page or use the project's install script:
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh
Install wash
Once wasmCloud is deployed to your EKS cluster, you can use the wasmCloud Shell (wash
) CLI to manage wasmCloud applications. If you do not have wash
installed locally, follow the instructions on the install page.
Install Google Cloud CLI tooling
Follow the instructions in Google Cloud's documentations to install and authenticate the gcloud
CLI.
Once you have set up the gcloud
CLI, install the beta
and gke-gcloud-auth-plugin
tools.
gcloud components install beta
gcloud components install gke-gcloud-auth-plugin
Set up your GKE cluster
It can be convenient to assign your preferred project, cluster name, and region to environment variables.
To get the identifier for your current Google Cloud project:
gcloud config get-value project
WASMCLOUD_GKE_CLUSTER_NAME=wasmcloud-cluster
WASMCLOUD_GKE_CLUSTER_REGION=us-east1
WASMCLOUD_GKE_PROJECT=project-identifier-012345-a1
Use the gcloud
CLI to create a GKE Autopilot cluster.
gcloud beta container --project "$WASMCLOUD_GKE_PROJECT" clusters create-auto "$WASMCLOUD_GKE_CLUSTER_NAME" --region "$WASMCLOUD_GKE_CLUSTER_REGION" --release-channel "regular" --tier "standard" --enable-ip-access --no-enable-google-cloud-access --network "projects/$WASMCLOUD_GKE_PROJECT/global/networks/default" --subnetwork "projects/$WASMCLOUD_GKE_PROJECT/regions/$WASMCLOUD_GKE_CLUSTER_REGION/subnetworks/default" --cluster-ipv4-cidr "/17" --binauthz-evaluation-mode=DISABLED
Deploying wasmCloud
In order to deploy wasmCloud, we will install the wasmcloud-platform
Helm chart. By default, the chart installs NATS, wadm
, and the wasmCloud operator subchart.
We'll need to use some custom values for an EKS deployment. The most important change is to set the storage class. Use the values below in a values.yaml
file:
# values.yaml
fullnameOverride: "wasmcloud-platform"
nameOverride: "wasmcloud-platform"
nats:
# Whether to install the nats chart (https://nats-io.github.io/k8s/helm/charts/nats)
enabled: true
fullnameOverride: "nats"
nameOverride: "nats"
container:
image:
repository: nats
tag: 2.10.16-alpine
reloader:
image:
repository: natsio/nats-server-config-reloader
tag: 0.14.3
# Source: https://github.com/wasmCloud/wasmcloud-operator/blob/main/examples/quickstart/nats-values.yaml
config:
cluster:
enabled: true
replicas: 3
leafnodes:
enabled: true
websocket:
enabled: true
port: 4223
jetstream:
enabled: true
fileStore:
enabled: true
pvc:
enabled: true
size: 1Gi
storageClassName: standard-rwo
merge:
domain: default
wadm:
# Whether to install the wadm chart (oci://ghcr.io/wasmcloud/charts/wadm)
enabled: true
fullnameOverride: "wadm"
nameOverride: "wadm"
# Source: https://github.com/wasmCloud/wasmcloud-operator/blob/main/examples/quickstart/wadm-values.yaml
wadm:
image:
repository: ghcr.io/wasmcloud/wadm
tag: v0.15.0
config:
nats:
server: "nats://nats-headless.default.svc.cluster.local"
# creds:
# jwt: ""
# seed: ""
# # If you're using the wasmCloud Operator, the secret could be created by the chart using the '.hostConfig.natsCredentialsFile' setting.
# secretName: ""
# key: "nats.creds"
resources: {}
operator:
# Whether to install the wasmcloud-operator chart (oci://ghcr.io/wasmcloud/charts/wasmcloud-operator)
# Make sure to either install wasmCloud Operator or wasmCloud Host, not both
enabled: true
fullnameOverride: "wasmcloud-operator"
nameOverride: "wasmcloud-operator"
# image:
# tag: 0.3.2
host:
# Whether to install the wasmcloud-host chart (oci://ghcr.io/wasmcloud/charts/wasmcloud-host)
# Make sure to either install wasmCloud Operator or wasmCloud Host, not both
enabled: false
fullnameOverride: "wasmcloud"
nameOverride: "wasmcloud"
hostConfig:
# Whether to use the wasmCloud host configuration custom resource; defaults to "false".
enabled: false
name: wasmcloud-host
lattice: default
# # Number of hosts (pods). Defaults to 1.
# hostReplicas: 1
# Which version of wasmCloud to use; defaults to "latest"
version: "1.2.1"
# registryCredentialsFile: config.json
# natsCredentialsFile: secret.yaml
resources:
nats: {}
wasmCloudHost: {}
helm upgrade --install \
wasmcloud-platform \
--values ./values.yaml \
oci://ghcr.io/wasmcloud/charts/wasmcloud-platform \
--dependency-update
Wait for all components to install and wadm-nats
communications to establish:
kubectl rollout status deploy,sts -l app.kubernetes.io/name=nats
kubectl wait --for=condition=available --timeout=600s deploy -l app.kubernetes.io/name=wadm
kubectl wait --for=condition=available --timeout=600s deploy -l app.kubernetes.io/name=wasmcloud-operator
Next create a wasmCloud host:
helm upgrade --install wasmcloud-platform \
--values ./values.yaml \
oci://ghcr.io/wasmcloud/charts/wasmcloud-platform \
--dependency-update \
--set "hostConfig.enabled=true"
If the deployment is successful, you should receive the note:
✨ Congratulations! Your wasmCloud platform has been deployed successfully.
- 🛀 To use the wash cli with your new wasmCloud platform, run:
kubectl port-forward service/nats 4222:4222 4223:4223
- 🗺️ To launch the wasmCloud dashboard on http://localhost:3030, in a different terminal window, run:
wash ui
If you'd like, you can check wasmCloud host status:
kubectl describe wasmcloudhostconfig wasmcloud-host
Run a WebAssembly component on Kubernetes
When you kubectl apply
a wasmCloud application manifest, the cluster automatically provisions the component workload with wasmCloud.
This example uses the hello-world-application.yaml
manifest included in the operator's quickstart. (The source code for the application is available in the wasmCloud repository.)
Below is an excerpt of the manifest:
...
spec:
components:
- name: http-component
type: component
properties:
image: ghcr.io/wasmcloud/components/http-hello-world-rust:0.1.0
...
The component is packaged as an OCI artifact and specified in the image
field. This isn't a container, but a component conforming to OCI standards, meaning that it can be used with existing registries for container images.
Run kubectl apply
:
kubectl apply -f https://raw.githubusercontent.com/wasmCloud/wasmcloud-operator/main/examples/quickstart/hello-world-application.yaml
Check the deployment status:
kubectl get application
APPLICATION DEPLOYED VERSION LATEST VERSION STATUS
hello-world v0.0.1 v0.0.1 Deployed
When you run a wasmCloud application that uses the httpserver
provider with a daemonscaler, as this one does, the operator automatically creates a Kubernetes service for the application.
When you're using the HTTP Server provider in an application that will run on Kubernetes with the wasmCloud operator, make sure the application manifest configures the provider to use the address 0.0.0.0
, for example:
- name: httpserver
type: capability
properties:
image: ghcr.io/wasmcloud/http-server:0.26.0
traits:
- type: link
properties:
target: http-component
namespace: wasi
package: http
interfaces: [incoming-handler]
source_config:
- name: default-http
properties:
address: 0.0.0.0:8000
Because of the way the application runs within a wasmCloud host pod, using 127.0.0.1
results in networking errors when running on Kubernetes.
View services:
kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-world ClusterIP 10.105.170.131 <none> 8000/TCP 2m53s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 9m39s
nats ClusterIP 10.102.201.180 <none> 4222/TCP,7422/TCP,4223/TCP 7m54s
nats-headless ClusterIP None <none> 4222/TCP,7422/TCP,4223/TCP,6222/TCP,8222/TCP 7m54s
wasmcloud-host ClusterIP 10.102.144.92 <none> 4222/TCP 6m32s
wasmcloud-operator ClusterIP 10.96.73.87 <none> 8443/TCP 7m54s
Test the application
On a cluster without ingress (such as this one), you can still test the component from within the wasmCloud host container where the application is running.
Assign the wasmCloud host pod name to an environment variable:
WASMCLOUD_HOST_POD=$(kubectl get pods -o jsonpath="{.items[*].metadata.name}" -l app.kubernetes.io/instance=wasmcloud-host)
Port-forward the wasmCloud host's port 8000:
kubectl port-forward pods/$WASMCLOUD_HOST_POD 8000
curl
the application:
curl http://localhost:8000
You should get the response:
Hello from Rust!
Debugging
You can use kubectl
to get logs from the wasmCloud host running on your cluster:
kubectl logs -l app.kubernetes.io/instance=wasmcloud-host -c wasmcloud-host
You can use a debug pod to test connections to an HTTP application's service from within the cluster:
kubectl run -i --tty --rm debug --image=curlimages/curl --restart=Never -- sh
Once the command prompt appears, you can try running curl
against the service name and port of your application. For the hello-world
application in the guide above, this would look like:
curl hello-world:8000
Common mistakes
- If you have issues deploying the platform chart, check the GKE web console to ensure that you haven't hit a quota limit. You may need to enable cluster autoscaling.
- If you're having trouble deploying an application, make sure your wadm application manifest references an OCI image and not a local file.
- If a service is not automatically generated for an application using the httpserver provider, check to ensure that the provider uses
daemonscaler
in the application manifest. (You can see an example of this in thehello-world-application
manifest.) - If you're having trouble connecting to an application that uses the HTTP Server provider, make sure it is configured to use the address
0.0.0.0
.
Manage applications with wash
Connect your local wash
with the wasmCloud deployment. 4222
is the port for the NATS service and 4223
is the port for NATS websockets.
kubectl port-forward service/nats 4222:4222 4223:4223
Now you can use your local wash
toolchain with your wasmCloud deployment:
wash get inventory
The output should look like this:
Host labels
hostcore.arch aarch64
hostcore.os linux
hostcore.osfamily unix
kubernetes true
Component ID Name Max count
hello_world-http_component http-hello-world 1
Provider ID Name
hello_world-httpserver http-server-provider
Clean up
Delete the hello-world
application:
kubectl delete -f https://raw.githubusercontent.com/wasmCloud/wasmcloud-operator/main/examples/quickstart/hello-world-application.yaml
Delete the wasmCloud host and associated resources:
kubectl delete -f https://raw.githubusercontent.com/wasmCloud/wasmcloud-operator/main/examples/quickstart/wasmcloud-host.yaml
All resources installed via Helm can be removed with helm uninstall
:
helm uninstall wasmcloud-platform
Follow the instructions from the GKE documentation to delete your cluster and nodes. Generally, you'll use the following command:
gcloud container clusters delete $WASMCLOUD_GKE_CLUSTER_NAME --region $WASMCLOUD_GKE_CLUSTER_REGION