tutorial

How to Monitor KWasm Kubernetes WebAssembly Runtime with Vigilmon (HTTP + TCP + Alerts)

KWasm is a Kubernetes operator that brings WebAssembly (Wasm) runtimes to your cluster nodes. It provisions and manages runtimes like WasmEdge, Wasmtime, and...

KWasm is a Kubernetes operator that brings WebAssembly (Wasm) runtimes to your cluster nodes. It provisions and manages runtimes like WasmEdge, Wasmtime, and Spin so you can schedule Wasm workloads alongside your regular container pods. When KWasm's operator fails or a node loses its Wasm runtime configuration, your Wasm-based workloads stop scheduling — and Kubernetes has no built-in visibility into whether a RuntimeClass is actually functional on any given node.

In this tutorial you'll set up comprehensive uptime monitoring for your KWasm-enabled Kubernetes cluster using Vigilmon — free tier, no credit card required.


Why KWasm clusters need external monitoring

KWasm extends Kubernetes with a new failure surface that the default control plane doesn't track:

  • kwasm-operator pod crashes — no new nodes get Wasm runtimes provisioned; existing Wasm pods keep running but new scheduling requests fail silently
  • Node annotation drift — if kwasm.sh/kwasm-node=true annotations are removed, the operator stops managing those nodes; Wasm RuntimeClasses on affected nodes become non-functional without any Kubernetes event
  • DaemonSet installer fails on a node — the kwasm-node-installer DaemonSet runs on annotated nodes; if it fails, that node cannot schedule Wasm workloads while the node itself shows Ready
  • Wasm runtime binary corruption — the runtime binary (e.g., runwasi, spin) on a node may be absent or mismatched; pods using the RuntimeClass get stuck in ContainerCreating indefinitely
  • RuntimeClass disappears — if the RuntimeClass object is accidentally deleted, all pods using it fail to schedule immediately; there is no cluster-level alert for this condition

These failures are particularly subtle because Kubernetes liveness checks confirm container processes are alive, not that the underlying Wasm runtime is functional.


What you'll need

  • A Kubernetes cluster with KWasm installed (kwasm-operator running)
  • At least one Wasm workload exposed via a Service or Ingress
  • A free Vigilmon account (sign up takes 30 seconds)

Step 1: Expose a health endpoint for monitoring

Deploy a Wasm workload with a reachable health route alongside a standard HTTP probe:

# Verify kwasm-operator is running
kubectl get pods -n kwasm -l app.kubernetes.io/name=kwasm-operator
# NAME                             READY   STATUS    RESTARTS   AGE
# kwasm-operator-7d8f9b4c6-xk2nm   1/1     Running   0          3d

# Check which nodes are Wasm-enabled
kubectl get nodes -l kwasm.sh/kwasm-node=true

# Verify RuntimeClasses exist
kubectl get runtimeclass
# NAME        HANDLER   AGE
# spin        spin      2d
# wasmtime    wasmtime  2d

Deploy a lightweight Wasm HTTP service using the Spin runtime (or substitute your runtime):

# wasm-health.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wasm-health
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: wasm-health
  template:
    metadata:
      labels:
        app: wasm-health
    spec:
      runtimeClassName: spin
      containers:
        - name: health
          image: ghcr.io/fermyon/spin-http-go-hello-world:latest
          ports:
            - containerPort: 3000
          readinessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 5
            periodSeconds: 10
          livenessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 10
            periodSeconds: 30
---
apiVersion: v1
kind: Service
metadata:
  name: wasm-health
  namespace: default
spec:
  type: LoadBalancer
  selector:
    app: wasm-health
  ports:
    - port: 80
      targetPort: 3000
      protocol: TCP
kubectl apply -f wasm-health.yaml

# Get the LoadBalancer IP
kubectl get svc wasm-health
# NAME           TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)   AGE
# wasm-health    LoadBalancer   10.96.45.100    203.0.113.80    80/TCP    1m

# Verify the Wasm pod scheduled successfully
kubectl get pods -l app=wasm-health -o wide
# NAME                          READY   STATUS    NODE
# wasm-health-6d9b4f8c5-abcde   1/1     Running   kwasm-node-1

# Confirm it responds
curl http://203.0.113.80/health
# {"status":"ok","runtime":"spin"}

Step 2: Set up HTTP monitoring in Vigilmon

With your Wasm health endpoint exposed, add it to Vigilmon:

  1. Log in to vigilmon.online and go to Monitors → New Monitor
  2. Choose HTTP / HTTPS as the type
  3. Set the URL to your service endpoint: http://203.0.113.80/health
  4. Set the check interval to 1 minute
  5. Under Expected response, set:
    • Status code: 200
    • Response body contains: "status":"ok"
  6. Save the monitor

This monitor validates the complete KWasm path: the kwasm-operator must be healthy, the RuntimeClass must exist, the node installer must have provisioned the runtime, the pod must have scheduled, and the Wasm binary must be executing — all for a 200 to reach Vigilmon.

Why external monitoring catches what Kubernetes misses

Kubernetes reports pod phase (Running, Pending) but cannot validate that a Wasm module is actually executing correctly. A pod in ContainerCreating limbo due to a missing runtime shows no error in kubectl get pods until you inspect events. Vigilmon's multi-region consensus probes from independent geographic locations and only fires when multiple probes agree — eliminating false positives from transient network conditions while catching real Wasm scheduling failures within minutes.


Step 3: Monitor TCP ports and the kwasm-operator

Add monitors to detect failures at multiple layers:

Service TCP check:

  1. Go to Monitors → New Monitor
  2. Choose TCP Port
  3. Enter: Host 203.0.113.80, Port 80
  4. Save the monitor

kwasm-operator API health:

The kwasm-operator exposes a metrics endpoint you can optionally proxy for monitoring:

# Port-forward to the operator metrics
kubectl port-forward -n kwasm svc/kwasm-operator 8080:8080

# Check operator health
curl http://localhost:8080/healthz
# ok

Expose the operator health endpoint via an Ingress or internal service if you want continuous monitoring, then add it as an HTTP monitor in Vigilmon.

Node-level Wasm validation:

Use a CronJob to validate that RuntimeClasses are functional on each node and push a heartbeat to Vigilmon when successful:

# wasm-validator-cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: wasm-runtime-validator
  namespace: default
spec:
  schedule: "*/5 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          runtimeClassName: spin
          restartPolicy: Never
          containers:
            - name: validator
              image: curlimages/curl:latest
              command:
                - sh
                - -c
                - |
                  curl -fsS https://uptime.vigilmon.online/api/v1/heartbeat/YOUR_HEARTBEAT_KEY
kubectl apply -f wasm-validator-cronjob.yaml

Step 4: Configure alert channels

KWasm failures are invisible until users report that Wasm-based services are down. Alert fast.

Email alerts

  1. In Vigilmon, go to Alert Channels → Add Channel → Email
  2. Enter your platform team's on-call email
  3. Assign the channel to all KWasm monitors

Webhook alerts (Slack, PagerDuty, etc.)

  1. Go to Alert Channels → Add Channel → Webhook
  2. Enter your webhook URL
  3. Assign the channel to your monitors

Example payload when the Wasm health endpoint goes down:

{
  "monitor_name": "KWasm Wasm Health",
  "status": "down",
  "url": "http://203.0.113.80/health",
  "started_at": "2024-01-15T14:30:00Z",
  "duration_seconds": 120
}

Run these diagnostics when an alert fires:

# Check kwasm-operator
kubectl get pods -n kwasm
kubectl logs -n kwasm -l app.kubernetes.io/name=kwasm-operator --tail=100

# Check RuntimeClasses
kubectl get runtimeclass
kubectl describe runtimeclass spin

# Check node installer DaemonSet
kubectl get daemonset -n kwasm
kubectl get pods -n kwasm -l app=kwasm-node-installer -o wide

# Check Wasm pod events
kubectl describe pod -l app=wasm-health | grep -A10 Events

# Check node installer logs on a specific node
kubectl logs -n kwasm -l app=kwasm-node-installer --field-selector spec.nodeName=kwasm-node-1 --tail=50

Step 5: Create a public status page

Wasm-backed services may serve external users. Give them visibility during incidents.

  1. In Vigilmon, go to Status Pages → New Status Page
  2. Give it a name: "KWasm Runtime Status"
  3. Add your monitors: Wasm Health HTTP, Service TCP, Heartbeat
  4. Group them: Wasm Services, Runtime Infrastructure, Scheduler Health
  5. Publish the page

Share this URL with your development teams and any external users of Wasm-backed services.


Putting it all together

Here's a summary of the monitors to create for a KWasm cluster:

| Monitor | Type | What it catches | |---------|------|-----------------| | http://203.0.113.80/health | HTTP | Full Wasm execution path (operator → RuntimeClass → pod → binary → response) | | 203.0.113.80:80 | TCP | Service reachability | | kwasm-operator /healthz | HTTP | Operator health; new node provisioning ability | | Wasm validator heartbeat | Heartbeat | Wasm scheduling still works on cluster nodes |

And the KWasm diagnostics to run when an alert fires:

# Triage: operator or runtime?
kubectl get pods -n kwasm
kubectl get runtimeclass

# Is the installer healthy on all nodes?
kubectl get pods -n kwasm -l app=kwasm-node-installer -o wide

# Did any Wasm pods get stuck?
kubectl get pods -A -o wide | grep -v Running | grep -v Completed

# Check node-level runtime binaries
kubectl debug node/kwasm-node-1 -it --image=busybox -- \
  ls -la /usr/local/bin/containerd-shim-spin-v2

What's next

  • SSL certificate monitoring — add SSL monitors for any HTTPS Wasm services
  • Heartbeat monitoring — use Vigilmon heartbeats to verify your Wasm validator CronJobs run on schedule
  • Multi-runtime coverage — create separate monitors for each RuntimeClass (spin, wasmtime, wasmedge) to isolate which runtime is failing

Get started free at vigilmon.online — no credit card, monitors start running in under a minute.

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →