k0s 1.27の新機能: コンテナランタイムプラグインでWASMを簡単に動かそう #k0s #kubernetes #k8s #webassembly #wasm #wasi
この記事は1年以上前に投稿されました。情報が古い可能性がありますので、ご注意ください。
k0sとは、軽量かつ使いやすい、100%オープンソースのKubernetesディストリビューションです。主な特徴としては、
- フル機能のKubernetesを構築するために必要なすべてを単一バイナリに同梱
- k0s特有の改変を加えていない、CNCF認定の純正なKubernetesをデプロイ
- 最低必要リソース1vCPU・1GBメモリ・2GBストレージのシングルノードから、HA構成の大規模クラスタまでサポート
- Konnectivityをデフォルトで有効化
などが挙げられます。より詳しい情報はホワイトペーパーや「5分でわかるk0s」動画シリーズをご覧ください。
2023年4月26日にリリースされたk0s 1.27には、k0s managed dynamic runtime configuration という新機能が追加されています。これは /etc/k0s/containerd.d/ ディレクトリに contained の設定スニペットを投入すると、動的にそれを読み込んで反映させるという機能です。これにより、 containerd の設定ファイル全体を適切に書き換えたりする必要がなくなりました。
本稿では k0s managed dynamic runtime configuration を利用して、過去記事「KubernetesでWASMを動かそう」よりも簡単にKubernetes (k0s)でWASMを動かしてみます。
仮想マシン環境の準備
まず仮想マシン環境をVagrant + VirtualBoxで準備しましょう。コントロールプレーン用VMを1つ、ワーカーノード用VMを2つです。
# -*- mode: ruby -*- # vi: set ft=ruby : Vagrant.configure("2") do |config| config.vm.box = "rockylinux/9" config.vm.box_check_update = false config.vm.define "main" do |cf| cf.vm.hostname = "main" cf.vm.network "private_network", ip: "192.168.56.101" cf.vm.provider "virtualbox" do |vb| vb.memory = 4096 end end ( 1..2 ).each do |i| config.vm.define "node0#{i}" do |cf| cf.vm.hostname = "node0#{i}" cf.vm.network "private_network", ip: "192.168.56.20#{i}" cf.vm.provider "virtualbox" do |vb| vb.memory = 4096 end end end end
k0sによるKubernetesのインストール
コントロールプレーン側
公式ドキュメントをもとにk0s v1.27.1をコントロールプレーン用VMにインストールします。
[vagrant@main ~]$ curl -sSLf https://get.k0s.sh | sudo sh Downloading k0s from URL: https://github.com/k0sproject/k0s/releases/download/v1.27.1+k0s.0/k0s-v1.27.1+k0s.0-amd64 k0s is now executable in /usr/local/bin [vagrant@main ~]$ k0s version v1.27.1+k0s.0 [vagrant@main ~]$
k0s設定ファイルを作成します。ここではIPアドレスの変更のみを行っており、他はデフォルト設定です。
[vagrant@main ~]$ k0s config create > k0s.yaml.orig [vagrant@main ~]$ cp -a k0s.yaml.orig k0s.yaml [vagrant@main ~]$ vi k0s.yaml [vagrant@main ~]$ diff -u k0s.yaml.orig k0s.yaml --- k0s.yaml.orig 2023-04-27 08:16:32.898589360 +0000 +++ k0s.yaml 2023-04-27 08:17:41.367440655 +0000 @@ -5,11 +5,10 @@ name: k0s spec: api: - address: 10.0.2.15 + address: 192.168.56.101 k0sApiPort: 9443 port: 6443 sans: - - 10.0.2.15 - 192.168.56.101 - fe80::a00:27ff:fefc:e996 - fe80::a00:27ff:fee4:c9e9 @@ -72,7 +71,7 @@ storage: etcd: externalCluster: null - peerAddress: 10.0.2.15 + peerAddress: 192.168.56.101 type: etcd telemetry: enabled: true [vagrant@main ~]$
この設定ファイルをもとに、コントロールプレーン用VMにKubernetesをインストールします。
[vagrant@main ~]$ sudo mkdir /etc/k0s [vagrant@main ~]$ sudo mv k0s.yaml /etc/k0s/ [vagrant@main ~]$ sudo /usr/local/bin/k0s install controller -c /etc/k0s/k0s.yaml [vagrant@main ~]$ sudo /usr/local/bin/k0s start [vagrant@main ~]$ sudo /usr/local/bin/k0s status Version: v1.27.1+k0s.0 Process ID: 4094 Role: controller Workloads: false SingleNode: false [vagrant@main ~]$
ワーカーノード参加用トークンを払い出します。
[vagrant@main ~]$ sudo /usr/local/bin/k0s token create --role=worker /etc/k0s/k0s.yaml > join-token [vagrant@main ~]$
この join-token ファイルをワーカーノード用VMにコピーします。
ワーカーノード側
コントロールプレーン用VMからコピーした join-token ファイルをもとにクラスタに参加させます。node01 と node02 で --node-ip オプションに与えるIPアドレスが異なることに注意しましょう。それぞれのVMのIPアドレスになります。
[vagrant@node01 ~]$ curl -sSLf https://get.k0s.sh | sudo sh Downloading k0s from URL: https://github.com/k0sproject/k0s/releases/download/v1.27.1+k0s.0/k0s-v1.27.1+k0s.0-amd64 k0s is now executable in /usr/local/bin [vagrant@node01 ~]$ sudo mkdir /etc/k0s [vagrant@node01 ~]$ sudo mv join-token /etc/k0s/ [vagrant@node01 ~]$ sudo /usr/local/bin/k0s install worker --token-file /etc/k0s/join-token --kubelet-extra-args '--node-ip=192.168.56.201' [vagrant@node01 ~]$ sudo /usr/local/bin/k0s start [vagrant@node01 ~]$ sudo /usr/local/bin/k0s status Version: v1.27.1+k0s.0 Process ID: 3992 Role: worker Workloads: true SingleNode: false Kube-api probing successful: true Kube-api probing last error: [vagrant@node01 ~]$
[vagrant@node02 ~]$ curl -sSLf https://get.k0s.sh | sudo sh Downloading k0s from URL: https://github.com/k0sproject/k0s/releases/download/v1.27.1+k0s.0/k0s-v1.27.1+k0s.0-amd64 k0s is now executable in /usr/local/bin [vagrant@node02 ~]$ sudo mkdir /etc/k0s [vagrant@node02 ~]$ sudo mv join-token /etc/k0s/ [vagrant@node02 ~]$ sudo /usr/local/bin/k0s install worker --token-file /etc/k0s/join-token --kubelet-extra-args '--node-ip=192.168.56.202' [vagrant@node02 ~]$ sudo /usr/local/bin/k0s start [vagrant@node02 ~]$ sudo /usr/local/bin/k0s status Version: v1.27.1+k0s.0 Process ID: 3993 Role: worker Workloads: true SingleNode: false Kube-api probing successful: true Kube-api probing last error: [vagrant@node02 ~]$
クラスタの確認
コントロールプレーン用VMでクラスタの状態を確認します。
[vagrant@main ~]$ sudo /usr/local/bin/k0s kubectl get nodes NAME STATUS ROLES AGE VERSION node01 Ready 4m14s v1.27.1+k0s node02 Ready 110s v1.27.1+k0s [vagrant@main ~]$
これでk0sによるKubernetesクラスタが準備できました。
wasm-enablerのデプロイ
過去記事「KubernetesでWASMを動かそう」では手動で WasmEdge や runwasi のインストール、containerd の設定変更を行って、WASMを動かせるようにしていました。
ここでは wasm-enabler をデプロイするだけでWASMを動かせるようにしてみます。wasm-enabler は、次の作業を自動化する DaemonSet として動作します。
- containerd-shim-spin をワーカーノードの /var/lib/k0s/bin ディレクトリにインストール
- containerd 設定スニペット をワーカーノードの /etc/k0s/containerd.d ディレクトリにインストール
これにより、Kubernetes上で Spinフレームワーク によってビルドされたWASMを動作させられるようになります(※過去記事「KubernetesでWASMを動かそう」とは shim や WASM ランタイムが異なることに注意してください)。
では、wasm-enabler をクラスタにデプロイしてみましょう。例にある次のマニフェストをapplyすればOKです。
[vagrant@main ~]$ vi wasm-enabler.yaml apiVersion: apps/v1 kind: DaemonSet metadata: name: wasm-enabler namespace: kube-system spec: selector: matchLabels: k0s-app: wasm-enabler template: metadata: labels: k0s-app: wasm-enabler spec: initContainers: - name: wasm-enabler image: quay.io/k0sproject/k0s-wasm-plugin:main securityContext: privileged: true volumeMounts: - name: bin mountPath: /var/lib/k0s/bin - name: imports mountPath: /etc/k0s/containerd.d/ containers: # We need one dummy container as DaemonSet do not allow to # run pods with restartPolicy other than Always ¯\_(ツ)_/¯ - name: dummy image: registry.k8s.io/pause:3.6 volumes: - name: bin hostPath: path: /var/lib/k0s/bin type: Directory - name: imports hostPath: path: /etc/k0s/containerd.d/ type: Directory --- apiVersion: node.k8s.io/v1 kind: RuntimeClass metadata: name: wasmtime-spin handler: spin [vagrant@main ~]$
[vagrant@main ~]$ sudo /usr/local/bin/k0s kubectl apply -f wasm-enabler.yaml daemonset.apps/wasm-enabler created runtimeclass.node.k8s.io/wasmtime-spin created [vagrant@main ~]$ sudo /usr/local/bin/k0s kubectl -n kube-system get daemonset wasm-enabler NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE wasm-enabler 2 2 2 2 2 71s [vagrant@main ~]$ sudo /usr/local/bin/k0s kubectl -n kube-system get pods --selector='k0s-app=wasm-enabler' NAME READY STATUS RESTARTS AGE wasm-enabler-72z4n 1/1 Running 0 2m47s wasm-enabler-g75n7 1/1 Running 0 2m47s [vagrant@main ~]$
これで完了です。
wasm-enablerのインストール確認
念のため、ワーカーノードに shim バイナリや containerd 設定スニペットがインストールされたか確認してみましょう。
[vagrant@node01 ~]$ sudo ls -l /var/lib/k0s/bin/containerd* -r-xr-x---. 1 root root 41219960 May 8 06:25 /var/lib/k0s/bin/containerd -r-xr-x---. 1 root root 6557696 May 8 06:25 /var/lib/k0s/bin/containerd-shim -r-xr-x---. 1 root root 8265728 May 8 06:25 /var/lib/k0s/bin/containerd-shim-runc-v1 -r-xr-x---. 1 root root 12009472 May 8 06:25 /var/lib/k0s/bin/containerd-shim-runc-v2 -rwxr-xr-x. 1 root root 48626496 May 8 06:30 /var/lib/k0s/bin/containerd-shim-slight-v1 -rwxr-xr-x. 1 root root 38593352 May 8 06:30 /var/lib/k0s/bin/containerd-shim-spin-v1 [vagrant@node01 ~]$
目的の containerd-shim-spin-v1 がインストールされています。
[vagrant@node01 ~]$ cat /etc/k0s/containerd.d/wasm_spin_runtime.toml ; echo [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.spin] runtime_type = "io.containerd.spin.v1" [vagrant@node01 ~]$
目的の containerd 設定スニペットもインストールされています。
サンプルアプリのデプロイ
では Spinフレームワークで作成されたWASMサンプルアプリをデプロイしてみましょう(※過去記事「KubernetesでWASMを動かそう」で利用したサンプルアプリ michaelirwin244/wasm-example はSpinフレームワーク製ではないので動作しません。Cannot read manifest file from "/run/k0s/containerd/io.containerd.runtime.v2.task/k8s.io/XXXXXXXX/rootfs/spin.toml": unknown のようなエラーになります)
[vagrant@main ~]$ vi wasm-spin.yaml apiVersion: apps/v1 kind: Deployment metadata: name: wasm-spin spec: replicas: 1 selector: matchLabels: app: wasm-spin template: metadata: labels: app: wasm-spin spec: runtimeClassName: wasmtime-spin containers: - name: spin-hello image: ghcr.io/deislabs/containerd-wasm-shims/examples/spin-rust-hello:v0.5.1 command: ["/"] resources: # limit the resources to 128Mi of memory and 100m of CPU limits: cpu: 100m memory: 128Mi requests: cpu: 100m memory: 128Mi --- apiVersion: v1 kind: Service metadata: name: wasm-spin spec: type: NodePort ports: - protocol: TCP port: 80 targetPort: 80 selector: app: wasm-spin [vagrant@main ~]$
デプロイします。
[vagrant@main ~]$ sudo /usr/local/bin/k0s kubectl apply -f wasm-spin.yaml deployment.apps/wasm-spin created service/wasm-spin created [vagrant@main ~]$ sudo /usr/local/bin/k0s kubectl get pods NAME READY STATUS RESTARTS AGE wasm-spin-5d958db977-fsfvf 1/1 Running 0 33s [vagrant@main ~]$ sudo /usr/local/bin/k0s kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 443/TCP 44m wasm-spin NodePort 10.107.65.52 80:31976/TCP 14s [vagrant@main ~]$
NodePortにアクセスしてみましょう。
[vagrant@main ~]$ curl 192.168.56.202:31976/hello ; echo Hello world from Spin! [vagrant@main ~]$
応答が返ってきました!
まとめ
本稿では Vagrant + Virtualbox でテスト環境を準備し、k0s で Kubernetes クラスタを作成し、k0s 1.27 の新機能である k0s managed dynamic runtime configuration を利用してWASIアプリケーションをデプロイできるように設定しました。この機能を利用すれば、Spinフレームワーク以外のWASM動作環境も比較的簡単に構築できるようになると思います。クリエーションラインでは引き続き WebAssmbly と Kubernetes について調査していきたいと思います。