fbpx

k0s 1.27の新機能: コンテナランタイムプラグインでWASMを簡単に動かそう #k0s #kubernetes #k8s #webassembly #wasm #wasi

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を動かそう」では手動で WasmEdgerunwasi のインストール、containerd の設定変更を行って、WASMを動かせるようにしていました。

ここでは wasm-enabler をデプロイするだけでWASMを動かせるようにしてみます。wasm-enabler は、次の作業を自動化する DaemonSet として動作します。

これにより、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 について調査していきたいと思います。

関連記事

Author

Chef・Docker・Mirantis製品などの技術要素に加えて、会議の進め方・文章の書き方などの業務改善にも取り組んでいます。「Chef活用ガイド」共著のほか、Debian Official Developerもやっています。

Daisuke Higuchiの記事一覧

新規CTA