Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

Run Wasm on Kubernetes with SpinKube

By Kokil Thapa | Last reviewed: September 2026

You want fast, portable functions without shipping a full Linux userspace in every pod. To Run Wasm on Kubernetes with SpinKube, you install the Spin operator, point your cluster at a wasm-capable containerd shim, and deploy Spin applications as OCI artifacts through a SpinApp custom resource. SpinKube sits on standard Kubernetes—you still use kubectl, namespaces, and ingress—but pods execute WebAssembly modules instead of traditional container images. This guide walks through a production-minded setup from cluster prep to scaling and troubleshooting.

What is SpinKube and why run Wasm on Kubernetes?

SpinKube is a Kubernetes operator that schedules Fermyon Spin WebAssembly applications as first-class cluster workloads. Spin compiles Rust, Go, Python, JavaScript, and other languages into compact wasm modules. SpinKube wraps those modules in OCI-compatible artifacts and runs them through containerd wasm shims—commonly containerd-shim-spin-v2 backed by Wasmtime.

The payoff is density and cold-start speed. A Spin HTTP handler often starts in milliseconds and uses a fraction of the memory a JVM or Node container needs. For event-driven APIs, webhooks, and edge-style microservices, that matters on cost-sensitive clusters—whether you run Amazon EKS, a bare-metal stack, or K3s at the edge.

SpinKube is not a separate orchestrator. It extends Kubernetes with CRDs, admission hooks, and controllers. You keep your existing CI/CD, observability stack, and network policies. If you already manage Linux servers for clients, the operational model feels familiar—only the runtime layer changes. See the official project at spinkube.dev for release notes and compatibility matrices.

SpinKube on KubernetesSpin CLIBuild + push OCIOCI RegistryGHCR / ECR / HarborSpin OperatorSpinApp CRDKubernetes APIScheduler + HPAWorker Node — containerd + wasm shimSpinApp pod runs wasm module via RuntimeClassIngress / GatewayHTTP routes to SpinObservabilityLogs + metrics
SpinKube architecture: Spin CLI builds OCI wasm artifacts, the operator reconciles SpinApp resources, and containerd wasm shims execute modules on worker nodes.

In my experience working on production Kubernetes deployments, teams adopt SpinKube when container image sizes or startup latency block efficient scaling. A legal-tech webhook that validates document metadata does not need a 400 MB image. A Spin handler compiled from Rust can sit under 5 MB and wake quickly after scale-to-zero events—useful for bursty lead-capture flows on platforms like those described in our Court Marriage In Nepal portfolio case.

How do you prepare a Kubernetes cluster for SpinKube?

SpinKube expects a normal Kubernetes 1.26+ cluster with containerd as the CRI. Managed control planes on EKS, GKE, and AKS work once worker nodes expose a compatible wasm shim. Local development clusters built with Minikube or kind are fine for learning, but confirm wasm RuntimeClass support before you demo to stakeholders.

Install cert-manager and the Spin operator

The Spin operator depends on cert-manager for webhook TLS. Install both into dedicated namespaces so upgrades stay isolated from application workloads.

  1. Install cert-manager following the upstream manifest for your cluster version.
  2. Add the SpinKube Helm repository and install spin-operator into spin-operator namespace.
  3. Verify CRDs exist: spinapps.core.spinkube.dev and related executor types.
  4. Confirm the operator pod reaches Ready state before deploying applications.
helm repo add spinkube https://spinkube.dev/charts
helm repo update

kubectl create namespace spin-operator

helm install spin-operator spinkube/spin-operator \
  --namespace spin-operator \
  --set webhook.enabled=true

kubectl get crd | grep spinkube
kubectl get pods -n spin-operator

Configure the containerd wasm RuntimeClass

Each worker node needs a containerd wasm shim. SpinKube documentation targets containerd-shim-spin-v2. You register a RuntimeClass so the scheduler knows which nodes can run wasm pods. Label nodes that have the shim installed, then tie the RuntimeClass handler to that shim name.

apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: wasmtime-spin-v2
handler: spin-v2
scheduling:
  nodeSelector:
    run-wasm: "true"

On Ubuntu 22.04 or 24.04 worker nodes—the same baseline I use for Linux system administration engagements—install the shim package from SpinKube release artifacts. Restart containerd, then label the node:

kubectl label node worker-01 run-wasm=true

Managed node groups sometimes block custom containerd plugins. If that happens, use self-managed worker pools or bare-metal nodes where you control the CRI configuration. Document the constraint in your runbook so the next deploy does not silently schedule wasm pods onto incompatible nodes.

How do you build and deploy a Spin application with SpinKube?

Fermyon Spin is the application framework; SpinKube is the deployment layer. You write Spin components—HTTP triggers, Redis triggers, cron-like schedules—and package them as OCI artifacts the operator understands. Read the Fermyon Spin documentation for language-specific SDK details.

Scaffold and build locally

Install Spin CLI and add the kube plugin. Scaffold a new HTTP application, build it, and test with spin up before touching the cluster.

curl -fsSL https://developer.fermyon.com/downloads/install.sh | bash
spin plugins install kube

spin new http-rust --accept-defaults
cd http-rust
spin build
spin up

For teams already shipping Laravel or Symfony APIs, Spin handlers often sit in front of existing backends as lightweight gateways. You might route public webhook traffic through Spin while the main app stays on PHP 8.3 or Laravel 13.x. That split keeps heavy business logic where your ORM and queue workers already live.

Push OCI artifacts and apply SpinApp

SpinKube treats wasm apps like container images. Push to GHCR, ECR, or Harbor, then reference the digest in a SpinApp manifest. Pin by digest in production so rollbacks are deterministic—same discipline as any GitOps pipeline with Argo CD.

Spin App Deploy PipelineSourcespin.tomlspin build.wasm artifactOCI pushregistry tagSpinApp YAMLkubectl applyPodsReadyExample SpinApp manifestapiVersion: core.spinkube.dev/v1alpha1kind: SpinAppspec.image: ghcr.io/org/app@sha256:abc...spec.replicas: 3spec.executor: containerd-shim-spin-v2
Deploy SpinKube workloads by building Spin artifacts, pushing to an OCI registry, and applying a SpinApp custom resource that pins image digests.
spin registry login ghcr.io -u YOUR_USER -p YOUR_TOKEN
spin registry push ghcr.io/your-org/hello-spin:v1

cat <<EOF | kubectl apply -f -
apiVersion: core.spinkube.dev/v1alpha1
kind: SpinApp
metadata:
  name: hello-spin
  namespace: apps
spec:
  image: ghcr.io/your-org/hello-spin:v1
  replicas: 2
  executor: containerd-shim-spin-v2
  runtimeClassName: wasmtime-spin-v2
EOF

kubectl get spinapp -n apps
kubectl get pods -n apps -l app.kubernetes.io/part-of=hello-spin

The spin kube plugin can scaffold Kubernetes manifests and deploy in one step during development. For production, keep manifests in Git and let CI run spin build, push the artifact, and apply templated YAML—mirroring how you would promote a Laravel release through GitLab CI and Deployer.

Expose traffic with Ingress

Spin HTTP components listen inside the pod on configured routes. Front them with your existing Ingress controller or Gateway API resource. Set path prefixes to match Spin trigger routes declared in spin.toml. TLS termination stays at the ingress layer; pods can remain plain HTTP behind the cluster network.

Validate end-to-end with a temporary port-forward before switching DNS:

kubectl port-forward svc/hello-spin 8080:80 -n apps
curl -i http://127.0.0.1:8080/hello

How does SpinKube compare to container-based Kubernetes workloads?

SpinKube does not replace every container. Long-running stateful services, legacy PHP monoliths, and databases still belong in standard pods. Wasm excels at short-lived, request-driven logic with minimal dependencies.

CriteriaSpinKube (Wasm)Standard containers
Cold-start latencyMilliseconds typical for small HTTP handlersSeconds common for interpreted runtimes
Image / artifact sizeOften 1–20 MB for focused handlers100 MB–1 GB+ with OS base layers
Memory per instanceLow; no full guest OSHigher baseline from userspace + runtime
Ecosystem fitHTTP APIs, webhooks, glue servicesDatabases, queues, monoliths, CMS
Security boundaryWasm sandbox + K8s pod isolationNamespace + seccomp + distro hardening
Operational maturityGrowing; operator + shim requiredMature tooling everywhere

A practical pattern on booking platforms—like trek-management systems built with Laravel and Livewire—is to keep order workflows in the main app and offload high-frequency status checks or webhook verification to Spin handlers. You gain startup speed without rewriting ten years of domain logic.

Wasm vs Container FootprintSpinKube PodWasm module ~5 MBRuntime shimFast cold startMemory: tens of MBContainer PodOS base layerLanguage runtimeApplication codeMemory: hundreds of MB
SpinKube wasm pods typically carry smaller artifacts and lower memory overhead than traditional container images with full OS layers.

Cost math matters for Nepal-based startups paying for cloud in NPR. Fewer megabytes per replica means more handlers per node. Pair that with Horizontal Pod Autoscaling and sensible resource requests so you do not over-provision after migration.

How do you scale, secure, and observe SpinKube workloads?

SpinKube pods participate in standard Kubernetes scaling and security primitives. Treat them like any other tier-2 service in your platform hardening checklist.

Autoscaling and resource limits

Define CPU and memory requests that reflect wasm’s lean profile, but leave headroom for traffic spikes. HPA on CPU or custom metrics works the same way—it watches pod metrics and adjusts replica counts. For bursty webhook traffic, combine HPA with conservative scale-down stabilization windows so you do not thrash during brief lulls.

resources:
  requests:
    cpu: 50m
    memory: 64Mi
  limits:
    cpu: 500m
    memory: 256Mi

RBAC, network policy, and secrets

Restrict who can create SpinApp objects in production namespaces. Apply RBAC roles that separate developers from cluster admins. Use NetworkPolicies so Spin handlers reach only approved backends—payment gateways, internal APIs, Redis caches.

Inject secrets through Kubernetes Secrets or external secret operators. Spin components read them as environment variables at startup. Never bake tokens into OCI artifacts pushed to registries shared across environments.

Logging and debugging

Stdout from Spin handlers lands in container logs like any pod. Pipe them to your existing aggregation stack. When pods fail, the same techniques from our CrashLoopBackOff debugging guide apply—inspect events, describe the SpinApp, and check shim compatibility on the node.

SpinKube Troubleshooting FlowPod not Ready?Check eventskubectl describe podRuntimeClassNode has wasm shim?Image pullRegistry auth OK?HTTP 502 after Ready?Verify spin.toml route matches Ingress pathPort-forward pod directly before blaming ingressConfirm Service selector labels match operator output
SpinKube troubleshooting: verify pod events, RuntimeClass node labels, registry credentials, then ingress route alignment.

When I troubleshoot production clusters, the most common SpinKube mistake is scheduling wasm pods onto nodes without the shim. The pod stays Pending with RuntimeClass warnings. The fix is either label additional nodes or narrow the SpinApp nodeSelector. Less common but painful: route mismatches between Spin trigger paths and Ingress rules—always curl the pod directly first.

When should you choose SpinKube over other Wasm runtimes?

Alternatives include running wasm inside standard containers via WasmEdge or embedding modules in service meshes. SpinKube’s advantage is native Kubernetes integration through a maintained operator and first-class Spin tooling. If your team already writes Spin components for Fermyon Cloud or local spin up workflows, SpinKube is the shortest path to self-hosted Kubernetes.

Choose standard containers when you need full POSIX compatibility, arbitrary native libraries, or mature APM agents that expect a Linux process model. Choose SpinKube when workloads are small, stateless, HTTP-driven, and cost-sensitive. Hybrid architectures—Laravel for domain logic, Spin for edge handlers—are valid and often easier than forcing everything into wasm.

For JSON config checks during Spin manifest templating, our JSON formatter tool helps catch trailing-comma errors before CI applies YAML. Larger platform work—designing the split between wasm handlers and monolith APIs—falls under enterprise application development when you need architecture review, not just a tutorial.

Related reading: Kubernetes troubleshooting field guide, performance tuning, and how the scheduler places pods. For booking-scale Laravel platforms that might adopt wasm gateways later, see the Adventure Third Pole Trek portfolio entry.

Key Takeaways

  • Install cert-manager and the Spin operator, then register a wasm RuntimeClass on nodes that run containerd-shim-spin-v2.
  • Build Spin apps locally with spin build, push OCI artifacts to a registry, and deploy via SpinApp manifests pinned by digest.
  • Use SpinKube for lightweight HTTP handlers and webhooks; keep databases and monoliths in standard containers.
  • Apply the same RBAC, NetworkPolicy, HPA, and ingress patterns you already use for container workloads.
  • Debug Pending pods by checking RuntimeClass node labels; debug 502 errors by port-forwarding before touching ingress.
  • Integrate SpinKube into GitOps pipelines so wasm promotions follow the same review gates as the rest of your platform.

People Also Ask

Does SpinKube work on managed Kubernetes services like EKS and GKE?

Yes, provided worker nodes support custom containerd wasm shims or you run self-managed node groups. Managed control planes are fine; the constraint is almost always the node image. Confirm shim installation steps for your AMI or node image before committing to a production migration.

Can SpinKube run applications written in languages other than Rust?

Spin supports Rust, Go, Python, JavaScript/TypeScript, and other languages through Fermyon SDKs. The deployment path through SpinKube is identical regardless of source language—you still produce a Spin artifact and reference it in SpinApp.spec.image.

How is SpinKube different from running Wasm inside a Docker container?

SpinKube uses containerd wasm shims to run modules directly without bundling a full OS layer inside the pod spec. Container-wrapped wasm adds image size and startup overhead. SpinKube aims for pod density and cold-start behavior closer to native wasm execution while keeping Kubernetes scheduling semantics.

Do I need Fermyon Cloud to use SpinKube?

No. Spin and SpinKube are open-source paths for self-hosted deployment. Fermyon Cloud is optional hosted infrastructure. Teams that prefer on-prem or existing EKS clusters can run SpinKube independently and push artifacts to any OCI-compatible registry.

Ship wasm workloads with confidence

You now have a complete path to Run Wasm on Kubernetes with SpinKube: prepare nodes with a wasm RuntimeClass, install the operator, build and push Spin artifacts, and expose them through your existing ingress stack. Start with one stateless handler— a webhook validator or health-check proxy—before moving critical paths. Measure cold-start time, memory, and error rates against your current container baseline.

If you want help designing a hybrid Laravel-plus-wasm platform, hardening cluster RBAC, or automating Spin deploys through GitLab CI, contact us or explore custom software development services. You can also browse the Kokil Thapa homepage and about page for more Kubernetes and full-stack engineering content, including mTLS between services and Velero backup strategies for production clusters.

Frequently Asked Questions

SpinKube is a Kubernetes operator that schedules Fermyon Spin WebAssembly applications as first-class cluster workloads. It wraps wasm modules in OCI-compatible artifacts and executes them through containerd wasm shims such as containerd-shim-spin-v2 backed by Wasmtime. You still use kubectl, namespaces, and ingress—the runtime layer changes, not the orchestrator. Teams adopt it when container image sizes or startup latency block efficient scaling. A focused HTTP handler often starts in milliseconds and uses far less memory than a JVM or Node container, which helps on cost-sensitive clusters running EKS, bare metal, or K3s at the edge.

SpinKube expects Kubernetes 1.26 or newer with containerd as the container runtime interface. Managed control planes on Amazon EKS, Google GKE, and Azure AKS work once worker nodes expose a compatible wasm shim. Local clusters built with Minikube or kind are fine for learning, but confirm wasm RuntimeClass support before demoing to stakeholders. The operator also depends on cert-manager for webhook TLS, so both should be installed in dedicated namespaces isolated from application workloads.

Install cert-manager from the upstream manifest for your cluster version, then add the SpinKube Helm repository and install spin-operator into the spin-operator namespace with webhooks enabled. Verify CRDs such as spinapps.core.spinkube.dev exist and the operator pod reaches Ready state before deploying applications. On each worker node, install containerd-shim-spin-v2 from SpinKube release artifacts, restart containerd, label the node with run-wasm=true, and register a RuntimeClass named wasmtime-spin-v2 whose handler is spin-v2 and whose scheduling nodeSelector matches that label.

No separate SpinKube license—cost is your cluster, registry, and engineering time. Wasm pods typically use smaller artifacts and lower memory than full container images, so you fit more handlers per node.

Install the Spin CLI and kube plugin, scaffold an HTTP app with spin new, build with spin build, and test locally using spin up. Push the OCI artifact to GHCR, ECR, or Harbor with spin registry push, then apply a SpinApp manifest referencing the image and pinning the digest in production for deterministic rollbacks. Set spec.executor to containerd-shim-spin-v2 and runtimeClassName to wasmtime-spin-v2. For production, keep manifests in Git and let CI run spin build, push, and apply templated YAML—the same promotion discipline you would use with GitLab CI and Deployer on a Laravel release.

Yes, provided worker nodes support custom containerd wasm shims or you run self-managed node groups. Managed control planes are fine; the constraint is almost always the node image. Managed node groups sometimes block custom containerd plugins. If that happens, use self-managed worker pools or bare-metal nodes where you control the CRI configuration. Document the constraint in your runbook so the next deploy does not silently schedule wasm pods onto incompatible nodes. Confirm shim installation steps for your AMI or node image before committing to a production migration.

Yes. Spin supports Rust, Go, Python, JavaScript, TypeScript, and other languages through Fermyon SDKs. The SpinKube deployment path is identical regardless of source language.

SpinKube uses containerd wasm shims to run modules directly without bundling a full OS layer inside the pod spec. Container-wrapped wasm adds image size and startup overhead. SpinKube wasm pods typically carry artifacts in the 1–20 MB range for focused handlers versus 100 MB to 1 GB or more for traditional images with base layers. Cold-start latency for small HTTP handlers is often milliseconds compared with seconds for many interpreted container runtimes. You trade POSIX compatibility and mature APM agents for density and speed on short-lived, request-driven workloads.

The most common cause is scheduling wasm pods onto nodes without the containerd wasm shim installed. The pod stays Pending with RuntimeClass warnings because no node matches the RuntimeClass nodeSelector, typically run-wasm=true. Fix it by installing containerd-shim-spin-v2 on additional workers, restarting containerd, labeling those nodes, or narrowing the SpinApp nodeSelector. Also verify the RuntimeClass handler name spin-v2 matches your shim registration. Less common but worth checking: registry pull failures and incorrect executor or runtimeClassName values in the SpinApp spec.

Spin HTTP components listen inside the pod on routes declared in spin.toml. Front them with your existing Ingress controller or Gateway API resource, setting path prefixes to match those trigger routes. TLS termination stays at the ingress layer; pods can remain plain HTTP behind the cluster network. Before switching DNS, validate end-to-end with kubectl port-forward to the service and curl the pod directly. Route mismatches between Spin trigger paths and Ingress rules are a frequent source of 502 errors—always confirm the handler responds on port-forward before debugging ingress rules.

SpinKube excels at short-lived, request-driven logic with minimal dependencies; standard containers remain the right choice for databases, queues, legacy monoliths, and CMS workloads. Wasm handlers show lower cold-start latency, smaller artifact size, and lower memory per instance because they skip a full guest OS. Standard pods offer broader POSIX compatibility, arbitrary native libraries, and mature tooling everywhere. A practical hybrid keeps order workflows in Laravel or Symfony while offloading high-frequency webhook verification or status checks to Spin handlers—you gain startup speed without rewriting years of domain logic.

Choose SpinKube for small, stateless, HTTP-driven, cost-sensitive workloads when you already use Spin tooling. Use standard containers for full POSIX needs, native libraries, or mature APM agents.

SpinKube pods participate in standard Horizontal Pod Autoscaling the same way container workloads do. Define CPU and memory requests that reflect wasm’s lean profile—example starting points from production-minded configs are 50m CPU and 64Mi memory requests with 500m CPU and 256Mi limits—but leave headroom for traffic spikes. HPA on CPU or custom metrics watches pod metrics and adjusts replica counts. For bursty webhook traffic, combine HPA with conservative scale-down stabilization windows so replicas do not thrash during brief lulls. Pair sensible resource requests with autoscaling so you do not over-provision nodes after migration.

Treat SpinKube pods like any other tier-2 service in your hardening checklist. Restrict who can create SpinApp objects using RBAC roles that separate developers from cluster admins. Apply NetworkPolicies so Spin handlers reach only approved backends such as payment gateways, internal APIs, or Redis caches. Inject secrets through Kubernetes Secrets or external secret operators as environment variables at startup—never bake tokens into OCI artifacts pushed to registries shared across environments. Wasm adds a sandbox boundary inside the pod, but it complements rather than replaces Kubernetes pod isolation, seccomp, and distro hardening on standard workloads.

Yes, and hybrid architectures are often easier than forcing everything into wasm. Spin handlers commonly sit in front of existing Laravel or Symfony APIs as lightweight gateways—public webhook traffic routes through Spin while business logic stays on PHP 8.3 or Laravel 13.x where your ORM and queue workers already live. On booking platforms, keep order workflows in the main app and offload high-frequency status checks or webhook verification to Spin. Both tiers share the same cluster ingress, network policies, and observability stack; only the runtime layer differs per workload type.

Share this article

0 Comments

Leave a comment

Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

Quick Contact Options
Choose how you want to connect me: