Closed10

Wasm Component binary を Docker Desktop か Podman Desktop か Rancher Desktop か k8s で動かしたい

tanishikingtanishiking

コンテナ事情がわからなすぎるのだけれど、Scala から wasi:http/proxy を使った echo server 実装できたので、これをLinuxコンテナを介さずに実行したい。
https://github.com/scala-wasm/scala-wasm/tree/scala-wasm/examples/echo-server

環境はM2 Macなんですが...やっぱLinuxがないとダメ?


Docker Desktop, Rancher Desktop, Podman Desktop

https://www.publickey1.jp/blog/23/dockerwasm_tchnical_preview_2wasmrunwasiwasm.html

https://www.publickey1.jp/blog/24/rancher_desktop_113webassembly.html

https://podman-desktop.io/blog/wasm-workloads-on-macos-and-windows-with-podman

colima でも出来そうだけどなんか大変そうだ

https://dev.to/bguijt/howto-wasm-runtimes-in-docker-colima-52c2


Wasm OCI artifact を作っておく

https://opensource.microsoft.com/blog/2024/09/25/distributing-webassembly-components-using-oci-registries/

Wasm OCI artifact の定義はこれかな https://github.com/cncf/tag-runtime/blob/7d0be31ca4f6ac9468b23f9841549d30cfd7077e/wgs/wasm/deliverables/wasm-oci-artifact/index.md

github container registry にアップロードしよう。write:packages で access token 作る https://github.com/settings/tokens/new

https://github.com/sunfishcode/hello-wasi-http これをビルドして...

$ cargo component build --target wasm32-wasip2 -r
    Creating component target/wasm32-wasip1/release/hello_wasi_http.wasm

$ wasm-tools print target/wasm32-wasip1/release/hello_wasi_http.wasm | head -n 5
(component
  (type (;0;)
    (instance
      (export (;0;) "error" (type (sub resource)))
    )



$ wkg oci push -u tanishiking -p <access_token> ghcr.io/tanishiking/hello-wasi-http:latest target/wasm32-wasip1/release/hello_wasi_http.wasm

pushed: ghcr.io/tanishiking/hello-wasi-http:latest
digest: sha256:2eb7107596f175c77f76976ea5aed13a376cc100571f0a8d04667efd7d6455b7

アップロードしたのはこちら: https://github.com/users/tanishiking/packages/container/package/hello-wasi-http

参考にした

https://zenn.dev/chikoski/articles/wkg-command-101#ghcrに登録する場合

tanishikingtanishiking

Docker Desktop

$ docker run --rm --runtime=io.containerd.wasmtime.v1 --platform=wasi/wasm secondstate/rust-example-hello:latest
Unable to find image 'secondstate/rust-example-hello:latest' locally
latest: Pulling from secondstate/rust-example-hello
269cd1915aa9: Pull complete
Digest: sha256:0e9edda42141012ed92fb65ee20de32f9469f1cd83e0131adf110eb4215f85f5
Status: Downloaded newer image for secondstate/rust-example-hello:latest
docker: Error response from daemon: failed to create task for container: failed to start shim: failed to resolve runtime path: runtime "io.containerd.wasmtime.v1" binary not installed "containerd-shim-wasmtime-v1": file does not exist

Run 'docker run --help' for more information

containerd-shim-wasmtime-v1 Docker が勝手に shims インストールしてくれるって話かと思った


https://docs.docker.com/desktop/features/wasm/

Docker Desktop downloads and installs the following runtimes:
io.containerd.slight.v1
io.containerd.spin.v2
io.containerd.wasmedge.v1
io.containerd.wasmtime.v1
io.containerd.lunatic.v1
io.containerd.wws.v1
io.containerd.wasmer.v1

インストールしてくれそうだが...

https://github.com/docker/for-mac/issues/7666

これと同じ症状。

そもそも runwasi が MacOS サポートしてないんだから、動かない? https://github.com/containerd/runwasi/issues/42
いや、Docker Desktop は Linux VM を立ててその上でコンテナを動かすという理解なので、動いてほしいけどなぁ

tanishikingtanishiking

Podman Desktop インストールしたけど CLI はついて来なかった? ので brew install podman した。

$ podman version
Client:        Podman Engine
Version:       5.5.0
API Version:   5.5.0
Go Version:    go1.24.3
Built:         Wed May 14 03:59:13 2025
Build Origin:  brew
OS/Arch:       darwin/arm64

Server:       Podman Engine
Version:      5.5.0
API Version:  5.5.0
Go Version:   go1.23.8
Git Commit:   0dbcb51477ee7ab8d3b47d30facf71fc38bb0c98
Built:        Tue May 13 09:00:00 2025
OS/Arch:      linux/arm64

Podman はVM(Podman Machine)というLinux VMの中でコンテナを実行

When using containers with Podman on macOS or Windows, you have a virtual machine called a "Podman machine" that is executing a Linux environment. We need to add support for Wasm inside this Linux environment. Podman is using the crun project as its OCI runtime, so crun needs to be able to run or delegate execution to Wasm runtimes. Lucky for us, crun supports Wasm execution.
https://podman-desktop.io/blog/wasm-workloads-on-macos-and-windows-with-podman

Many people do not realize that containers are really Linux. As such, Linux containers cannot run natively on macOS. Therefore, the containers must run in a Linux virtual machine (VM), and a Podman client interacts with that VM. This is in line with all solutions for running containers on macOS.
https://www.redhat.com/en/blog/podman-mac-machine-architecture


とりあえずデモを動かす

$ podman run --platform wasi/wasm quay.io/podman-desktop-demo/wasm-rust-hello-world

!... Hello Podman wasm World ...!

         .--"--.
       / -     - \
      / (O)   (O) \
   ~~~| -=(,Y,)=- |
    .---. /`  \   |~~
 ~/  o  o \~~~~.----. ~~
  | =(X)= |~  / (O (O) \
   ~~~~~~~  ~| =(Y_)=-  |
  ~~~~    ~~~|   U      |~~

Project:   https://github.com/containers/podman
Website:   https://podman.io
Documents: https://docs.podman.io
Twitter:   @Podman_io

でもこれ明らかにwasip1だよね https://github.com/redhat-developer/podman-desktop-demo/tree/main/wasm/rust-hello-world


Podman desktop で ghcr にログインしておいて...

$ podman run --platform wasi/wasm ghcr.io/tanishiking/hello-wasi-http:latest
Trying to pull ghcr.io/tanishiking/hello-wasi-http:latest...
Error: internal error: unable to copy from source docker://ghcr.io/tanishiking/hello-wasi-http:latest: parsing image configuration: unsupported image-specific operation on artifact with type "application/vnd.wasm.config.v0+json"

crun が(?) application/vnd.wasm.config.v0+json に対応してないから使えないのかな? そもそも podman がいってる Wasm OCI image って何? これ? https://github.com/solo-io/wasm/blob/master/spec/README.md

https://podman-desktop.io/blog/wasm-workloads-on-macos-and-windows-with-podman#building-wasm-oci-images-with-podman

tanishikingtanishiking

Rancher Desktop

https://github.com/containerd/runwasi/releases/tag/containerd-shim-wasmtime%2Fv0.6.0 から containerd-shim-wasmtime をインストールする。aarch64x86 どっちにすればいいんだろう、ホストがaarch64だしそっちから

$ mkdir ~/Library/Application\ Support/rancher-desktop/containerd-shims
$ cp containerd-shim-wasmtime-aarch64-linux-musl/containerd-shim-wasmtime-v1 ~/Library/Application\ Support/rancher-desktop/containerd-shims/

これでRancher Desktopを立ち上げる
あの... nerdctl 入らないんですが... -> PATH 設定を Manual にすると ~/.rd/bin に nerdctl 入ってた。よしよし

https://github.com/containerd/nerdctl/blob/main/docs/registry.md#github-container-registry-ghcr nerdctl から ghcr に login して

$  nerdctl login ghcr.io -u tanishiking
$  nerdctl run --rm --runtime=io.containerd.runwasi.v1 --name hello-wasi-example ghcr.io/tanishiking/hello-wasi-http:latest
FATA[0002] unknown media type "application/vnd.wasm.config.v0+json"
Error: exit status 1

う〜ん、何故

moby backend にした場合はこれ、なんでやねん???

$ docker run --rm --runtime=io.containerd.wasmtime.v1  --platform=wasi/wasm ghcr.io/tanishiking/hello-wasi-http:latest
Unable to find image 'ghcr.io/tanishiking/hello-wasi-http:latest' locally
latest: Pulling from tanishiking/hello-wasi-http
Digest: sha256:2eb7107596f175c77f76976ea5aed13a376cc100571f0a8d04667efd7d6455b7
Status: Image is up to date for ghcr.io/tanishiking/hello-wasi-http:latest
docker: Error response from daemon: No such image: ghcr.io/tanishiking/hello-wasi-http:latest
tanishikingtanishiking

kubernetes (kind)

$ system_profiler SPHardwareDataType
Hardware:

    Hardware Overview:

      Model Name: MacBook Pro
      Model Identifier: Mac14,7
      Model Number: Z16R000S2J/A
      Chip: Apple M2
      Total Number of Cores: 8 (4 performance and 4 efficiency)
      Memory: 16 GB
      System Firmware Version: 11881.121.1
      OS Loader Version: 11881.121.1
      Serial Number (system): JXGD2QK61V
      Hardware UUID: EA3516EF-EA8F-555A-AE7B-887568CB2AD7
      Provisioning UDID: 00008112-001819D634A3C01E
      Activation Lock Status: Enabled

$ uname -m
arm64

runwasi の quickstart with Kubernetes 試してみよう

https://runwasi.dev/getting-started/quickstart.html

https://github.com/containerd/runwasi/releases から containerd-shim-wasmtime-aarch64-linux-musl.tar.gz をダウンロード、展開して /usr/local/bin/containerd-shim-wasmtime-v1 にコピーして chmod +x

$ cat kind-config.yaml
# kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: runwasi-cluster
nodes:
- role: control-plane
  extraMounts:
  - hostPath: /usr/local/bin/containerd-shim-wasmtime-v1
    containerPath: /usr/local/bin/containerd-shim-wasmtime-v1

$ kind create cluster --name runwasi-cluster --config kind-config.yaml

$ docker ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED         STATUS         PORTS                       NAMES
d776f952e99d   kindest/node:v1.33.1   "/usr/local/bin/entr…"   4 minutes ago   Up 4 minutes   127.0.0.1:55740->6443/tcp   runwasi-cluster-control-plane

runwasi-cluster-control-plane/etc/containerd/config.toml に containerd 設定を書き込んで、再起動

$ cat << EOF | docker exec -i runwasi-cluster-control-plane tee /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.wasm]
runtime_type = "io.containerd.wasmtime.v1"
EOF

$ docker exec runwasi-cluster-control-plane systemctl restart containerd
# deploy.yaml
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: wasm
handler: wasm
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wasi-demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wasi-demo
  template:
    metadata:
      labels:
        app: wasi-demo
    spec:
      runtimeClassName: wasm
      containers:
      - name: demo
        image: ghcr.io/containerd/runwasi/wasi-demo-app:latest
$ kubectl --context kind-runwasi-cluster apply -f deploy.yaml
$ kubectl --context kind-runwasi-cluster get pods
NAME                         READY   STATUS              RESTARTS   AGE
wasi-demo-6d48f6979f-bplf4   0/1     ContainerCreating   0          6m25s
$ kubectl --context kind-runwasi-cluster logs -l app=wasi-demo
Error from server (BadRequest): container "demo" in pod "wasi-demo-6d48f6979f-bplf4" is waiting to start: ContainerCreating

$ kubectl describe pod -l app=wasi-demo
Name:                wasi-demo-6d48f6979f-bplf4
Namespace:           default
Priority:            0
Runtime Class Name:  wasm
Service Account:     default
Node:                runwasi-cluster-control-plane/172.18.0.2
Start Time:          Wed, 04 Jun 2025 09:26:25 +0900
Labels:              app=wasi-demo
                     pod-template-hash=6d48f6979f
Annotations:         <none>
Status:              Pending
IP:
IPs:                 <none>
Controlled By:       ReplicaSet/wasi-demo-6d48f6979f
Containers:
  demo:
    Container ID:
    Image:          ghcr.io/containerd/runwasi/wasi-demo-app:latest
    Image ID:
    Port:           <none>
    Host Port:      <none>
    State:          Waiting
      Reason:       ContainerCreating
    Ready:          False
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-7zr6j (ro)
Conditions:
  Type                        Status
  PodReadyToStartContainers   False
  Initialized                 True
  Ready                       False
  ContainersReady             False
  PodScheduled                True
Volumes:
  kube-api-access-7zr6j:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type     Reason                  Age               From               Message
  ----     ------                  ----              ----               -------
  Normal   Scheduled               3m35s             default-scheduler  Successfully assigned default/wasi-demo-6d48f6979f-bplf4 to runwasi-cluster-control-plane
  Warning  FailedCreatePodSandBox  3m34s             kubelet            Failed to create pod sandbox: rpc error: code = Unknown desc = unable to get OCI runtime for sandbox "18c1a680837ab9690d40bc8e5f70c83122ae908149f733e2f97835c79b35230c": no runtime for "wasm" is configured
  Warning  FailedCreatePodSandBox  3m21s             kubelet            Failed to create pod sandbox: rpc error: code = Unknown desc = unable to get OCI runtime for sandbox "6e7420b360feec3532b90f681fa0d74883e7945fcf1b6ace83214d1f606fb3fb": no runtime for "wasm" is configured
  Warning  FailedCreatePodSandBox  3m7s              kubelet            Failed to create pod sandbox: rpc error: code = Unknown desc = unable to get OCI runtime for sandbox "3c4781367cde6554a00a65a55f98ca63c5d1e7afa4dfda630ae4268d5425b92b": no runtime for "wasm" is configured
  Warning  FailedCreatePodSandBox  2m52s             kubelet            Failed to create pod sandbox: rpc error: code = Unknown desc = unable to get OCI runtime for sandbox "81db1c659ee3fb2b88adeb829ef1f2c175ec1032ddeb4dee3ca9cf7b329af3ec": no runtime for "wasm" is configured
  Warning  FailedCreatePodSandBox  2m39s             kubelet            Failed to create pod sandbox: rpc error: code = Unknown desc = unable to get OCI runtime for sandbox "5c342538c1028a432b1b5516f5576e149a6c7bd2bbe7295cd89b70ae6a355ade": no runtime for "wasm" is configured
  Warning  FailedCreatePodSandBox  2m26s             kubelet            Failed to create pod sandbox: rpc error: code = Unknown desc = unable to get OCI runtime for sandbox "d4dea10f255e271f50522be576a5743182cab39ee8e8c8808f805fe7d391e3e0": no runtime for "wasm" is configured
  Warning  FailedCreatePodSandBox  2m15s             kubelet            Failed to create pod sandbox: rpc error: code = Unknown desc = unable to get OCI runtime for sandbox "550d4c6aead977349f4c1a8e0ba2f37d8cc34428d39b3276bfa6ed80ee83456e": no runtime for "wasm" is configured
  Warning  FailedCreatePodSandBox  2m                kubelet            Failed to create pod sandbox: rpc error: code = Unknown desc = unable to get OCI runtime for sandbox "54bcfa907c2b5fb6e3066f0f1b341ea10d251e6c7a8c39be397d65d009698823": no runtime for "wasm" is configured
  Warning  FailedCreatePodSandBox  108s              kubelet            Failed to create pod sandbox: rpc error: code = Unknown desc = unable to get OCI runtime for sandbox "2f75d74a5fc6e91b093004ca40163b534c63fb1bcab4496c49ab216280e4ffc4": no runtime for "wasm" is configured
  Warning  FailedCreatePodSandBox  5s (x8 over 97s)  kubelet            (combined from similar events): Failed to create pod sandbox: rpc error: code = Unknown desc = unable to get OCI runtime for sandbox "1a969db3abb0e6f43eb68d857735841653d60954bbde84f80259b8dfe9053bdf": no runtime for "wasm" is configured

no runtime for "wasm" is configured

うーむ


kind の container に入って containerd config 叩いてみたけど、普通にruntime設定できてなくないか?

こういうこといわれてるし

WARN[0000] Ignoring unknown key in TOML for plugin       error="strict mode: fields in the document are missing in the target struct" key=containerd plugin=io.containerd.grpc.v1.cri
WARN[0000] Ignoring unknown key in TOML for plugin       error="strict mode: fields in the document are missing in the target struct" key="containerd runtimes" plugin=io.containerd.grpc.v1.cri
WARN[0000] Ignoring unknown key in TOML for plugin       error="strict mode: fields in the document are missing in the target struct" key="containerd runtimes wasm" plugin=io.containerd.grpc.v1.cri
WARN[0000] Ignoring unknown key in TOML for plugin       error="strict mode: fields in the document are missing in the target struct" key="containerd runtimes wasm options" plugin=io.containerd.grpc.v1.cri
[plugins."io.containerd.cri.v1.runtime".containerd.runtimes.wasm]
  runtime_type = "io.containerd.wasmtime.v1"
EOF

これだといけたわ。(ほかの containerd config dump 設定をまねた)

tanishikingtanishiking
    spec:
      runtimeClassName: wasm
      containers:
      - name: demo
        image: ghcr.io/tanishiking/hello-wasi-http:latest

これだと

  Normal   Pulled     2s (x2 over 14s)    kubelet            (combined from similar events): Successfully pulled image "ghcr.io/tanishiking/hello-wasi-http:latest" in 627ms (627ms including waiting). Image size: 90554 bytes.
  Warning  Failed     2s (x2 over 14s)    kubelet            (combined from similar events): Error: failed to generate container "d749477ff3e9b92d3d17b85870ebe42532fb3451d3ebfe4aec8caebd2bce95bb" spec: failed to generate spec: no command specified

    spec:
      runtimeClassName: wasm
      containers:
      - name: demo
        image: ghcr.io/tanishiking/hello-wasi-http:latest
        command: [""]

これならok

 kubectl port-forward wasi-demo-65c85ddd56-hgtpg 8080:8080

$ curl http://localhost:8080
Hello, wasi:http/proxy world!
このスクラップは3ヶ月前にクローズされました