自作Wasm Runtimeをcontainerdで動かしてみた
はじめに
以前に、RustでWasm Runtimeを実装したという記事を書きました。
それ以来しばらく放置していたのですが、先日開催されたWebAssembly night #11に参加してモチベーションが上がってきたので、以前から試そうと思っていた自作Wasm Runtimeをコンテナランタイムと連携して動かすのを実際にやってみました。
この記事は詳しい説明はせず、概ねどんなことをやったのかの記録となっています。
また、筆者はコンテナランタイムに疎いので雰囲気で書いているところもあるので、間違いなどがありましたらコメントなどで教えていただければと思います。
成果物
実装はこちらにおいてあります。
こんな感じで動きます。
skanehira@pi1:~/work$ ls -la /usr/local/bin/
total 118208
drwxr-xr-x 2 root root 4096 Sep 18 12:46 .
drwxr-xr-x 10 root root 4096 Feb 18 2023 ..
-rwxr-xr-x 1 root root 40118648 Jun 3 08:06 containerd
-rwxr-xr-x 1 root root 6422528 Jun 3 08:06 containerd-shim
-rwxr-xr-x 1 root root 15901680 Sep 18 12:46 containerd-shim-chibiwasm-v1
-rwxr-xr-x 1 root root 8060928 Jun 3 08:06 containerd-shim-runc-v1
-rwxr-xr-x 1 root root 11534336 Jun 3 08:06 containerd-shim-runc-v2
-rwxr-xr-x 1 root root 18939904 Jun 3 08:06 containerd-stress
-rwxr-xr-x 1 root root 20054016 Jun 3 08:06 ctr
skanehira@pi1:~/work$ cat Dockerfile
FROM scratch
COPY ./hello.wasm /hello.wasm
ENTRYPOINT [ "/hello.wasm" ]
skanehira@pi1:~/work$ sudo ctr images list
REF TYPE DIGEST SIZE PLATFORMS LABELS
docker.io/library/hello-wasm:latest application/vnd.oci.image.index.v1+json sha256:fd9c651890a70a636941e5083fc4b914f677aa5f22e7fafa5abcbdeae625023e 503.0 KiB linux/arm64,unknown/unknown -
skanehira@pi1:~/work$ sudo ctr run --rm --runtime=io.containerd.chibiwasm.v1 docker.io/library/hello-wasm:latest hello-wasm
Hello, World!
skanehira@pi1:~/work$
containerd-shim-wasm
去年にDocker
がWasm
対応を発表されてました。
通常のLinuxコンテナの代わりにWasm
を実行できるといった内容でした。
記事内にある次の図を見ると、コンテナを直接作成するrunc
に代わってwasmedge
といったWasm Runtime
を使っていました。
そして、containerd
とrunc
の橋渡し役であるcontainerd-shim
がcontainerd-shim-wasm
に代わっていました。
つまり、自作Runtimeに対応したcontainerd-shim-wasm
を用意すれば、オレオレWasm Runtime
を動かせそうということがわかります。
ちなみに、--runtime
で指定したランタイムio.containerd.wasmedge.v1
は/usr/local/bin
などPATHが通っている場所にあるcontainerd-shim-wasmtime-v1
バイナリにマッピングされます。
バイナリがなければエラーになります。
つまり、containerd-shim-chibiwasm-v1
という名前で配置すればio.containerd.chibiwasm.v1
というランタイム名になるとういことですね。
runwasi
では、containerd-shim-xxx
はどうやって用意すればいいのか?という話は次のブログを読めば大体わかります。
簡潔にいうとrunwasiを使います。
使用するクレートは次の2つになります。
containerd
とshim
の間ではttrpc
を使って通信するようですが、そこの処理はcontainerd-shim
クレートがやっているっぽい(未確認)です。
なので、Instance
トレイトを満たすように、コンテナの起動や停止、削除といった処理を実装するだけで動くようになっています。
今回はほぼrunwasi
が提供しているcontainerd-shim-wasmtime
の実装をそのまま使いました。
やっていることはスレッドでコンテナを作成、起動して、終了待ちをしています。
ここで「runc
の代わりにWasm Runtime
を使うのに結局コンテナを作るの?」と疑問に思ったんのですが、どうやらコンテナを作成してその中でWasm Runtime
を使ってWasm
を実行するようです。
次の処理はlibcontainerというクレートを使ってコンテナを作成していて、with_executor
でChibiwasmExecutor
を指定しています。
ChibiwasmExecutor
はlibcontainer
のExecutor
トレイトを実装していて、その中で自作したWasm Runtime
を使ってコンテナ内にあるWasm
バイナリを読み取って実行しています。
実装はこれで大体終わりで、あとはバイナリをビルドしてPATH
が通った場所に配置して--runtime=io.containerd.chibiwasm.v1
を指定すれば動きます。
skanehira@pi1:~/work$ sudo ctr run --rm --runtime=io.containerd.chibiwasm.v1 docker.io/library/hello-wasm:latest hello-wasm
Hello, World!
さいごに
実際に自作Wasm Runtime
をcontainerd
で動かせるようにしてみて、コンテナが作られないと勘違いしていたことがわかってよかったです。
そして思ったよりもコンテナランタイムのこと何もわからないことがわかったので、機会があれば深掘りしていきたいと思っています。
ちなみに、k8sやDockerで試していないのですが、contianerd
で動くので基本的に動くと思います。
Discussion