Krustlet with Kindでの複数WASM実行と展望
12/19変更
調査目的
複数同時にWASM(WebAssembly)を動かした場合の挙動を調べるため実施
具体的には新たにプロセルorスレッドで実行されるのか調査
Krustletについて
- kubeletをRustで構築し、WebAssemblyを動かせるようにしたもの
- WebAssemblyを利用する上で無駄が多いCRIなどの部分を排除し、直接kubeletAPIからWasmランタイムを扱えるようにした
画像引用:コンテナランタイムの動向を整理してみた件 https://qiita.com/mamomamo/items/ed5db2ab1555078f8a24
構成
マスターをKindで構築、workerとしてKrustletを追加
環境構築に関しては以下を参考に構築
Krustletを使ってKubernetesでWebAssemblyアプリケーションを実行する - Qiita
https://docs.krustlet.dev/howto/krustlet-on-kind/
使用バージョン
hostOS : ubuntu : 20.04
kubernetes : v1.21.12(v1.22以降は別バイナリ対応)
krustlet : 1.0.0-alpha.1
wasi-sdk : 14.0
wasmtime : 0.36.0
krustletでのwasmランタイム挙動確認
動作状況を可視化するために
フィボナッチ数列を無限に計算するWasmを用意し、htopのCPU使用率から一目でで動作する個数がわかるようにした
リアルタイムに標準出力(log)を追うために
fflush(stdout)で標準出力のストリームを解放する必要がある
ない場合、kubectl logs [pod name] でprintfのログがストリームがいっぱいになったタイミングでしか表示されない
→コマンドラインでwasmtimeではなくても表示される。KrustletにはWebAssemblyランタイムとしてwasmtimeが組み込まれているが、コマンドラインでwasmtimeと挙動が異なる
- fflushなしwasm yaml
krustlet-DemoWasmApp/no-fflush.yaml at main · nao-ri/krustlet-DemoWasmApp
- WebAssembly生成用コード fibonacci.c
/* * C言語のサンプルプログラム - Webkaru * - フィボナッチ数の計算 - */ #include <stdio.h> #include <unistd.h> int main(void) { /* 変数の宣言 */ int n; double f0, f1, f2; f0 = 0; f1 = 1; /* フィボナッチ数(n=0)の出力 */ printf("%lf\n", f0); /* フィボナッチ数の計算 */ while (1) { n++; // フィボナッチ数の出力(n>0) if (n == 1000000000) { printf("%lf\n", f1); fflush(stdout);//標準出力 n = 0; } // フィボナッチ数の計算 f2 = f1 + f0; // 変数の代入 f0 = f1; f1 = f2; } return 0; }
複数Wasmの動作設定
wasm二つで計算
Replicasetを利用
https://blog.a-know.me/entry/2018/08/14/185324#ReplicaSet-とは
- doubleFibonacci.yaml
apiVersion: apps/v1 kind: ReplicaSet metadata: name: fibonacci spec: replicas: 2 selector: matchLabels: app: wasm template: metadata: labels: app: wasm spec: nodeSelector: kubernetes.io/arch: wasm32-wasi containers: - name: fibonacci-wasm image: ghcr.io/nao-ri/fibonacci-wasm:1.0 imagePullPolicy: Always imagePullSecrets: - name: dockerconfigjson-github-com tolerations: - effect: NoExecute key: kubernetes.io/arch operator: Equal value: wasm32-wasi - effect: NoSchedule key: kubernetes.io/arch operator: Equal value: wasm32-wasi
結果
kubectl から実行を確認
oss-kube@osskube-Super-Server:~$ kubectl get node -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME kind-control-plane Ready control-plane,master 197d v1.21.12 172.18.0.2 <none> Ubuntu 21.10 5.15.0-53-generic containerd://1.6.4 krustlet Ready <none> 197d 1.0.0-alpha.1 172.17.0.1 <none> <unknown> <unknown> mvp oss-kube@osskube-Super-Server:~$ kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES fibonacci-4578v 1/1 Running 0 29m <none> krustlet <none> <none> fibonacci-dnfkq 1/1 Running 0 29m <none> krustlet <none> <none>
htopで2コアを占有する二つの実行状態を確認
/proc でスレッドで実行されていることを確認
oss-kube@osskube-Super-Server:~$ ls /proc/73566/task/3197 319756/ 319783/
確認できたこと
- 実行するごとにスレッドが増加
- 二つのwasmモジュールを起動されているため、コアを二つ占有して処理
- 個別のスレッドごとのCPU使用率は把握可能、メモリ利用については取得不可
Krustletについて今後の展望
Krustletは2021年からgithub上の更新が止まっている。さらに開発元であるDeis Labsは、OCI対応によって低レベルコンテナライムレイヤーへの変更のみでWebAssemblyに対応するrunwasiの開発に着手している。 よって、K8s上でWebAssemblyを動かすためにkubeletを改造するアプローチ(Krustlet)の開発が再開される可能性は低い。
この理由はKrustletプロジェクトのようにkubelet以下を全部WebAssembly対応に作ることはバージョン追従などメンテナンスにかかるコストが高いと推測される。そのため、K8sでwebassemblyを動かす際は、メンテナンス範囲が少なくなる低レベルコンテナライムレイヤーの実装が主流になっていくと考えられる。
実際、runwasi以外にもcrun(c言語の低レベルコンテナランタイム実装)にWebAssemblyランタイムを埋め込み利用できるOSS(wasmedge)が存在し盛んに開発行われている。
runwasi https://nigelpoulton.com/what-is-runwasi/
実行ソース
demowasmとyaml https://github.com/nao-ri/krustlet-DemoWasmApp