普段はCRIはDocker、OCIはrunc、CNIはcalicoで構成することが多いのだけど、たまには違う構成でもとってみようと思いインストールしてみる。 特にこれまでKata containersはさわったことなかったので。 OSはUbuntuを適当に入れた
Kataのインストール
https://github.com/kata-containers/documentation/blob/master/install/ubuntu-installation-guide.md
ARCH=$(arch)
BRANCH="${BRANCH:-master}"
sudo sh -c "echo 'deb http://download.opensuse.org/repositories/home:/katacontainers:/releases:/${ARCH}:/${BRANCH}/xUbuntu_$(lsb_release -rs)/ /' > /etc/apt/sources.list.d/kata-containers.list"
curl -sL http://download.opensuse.org/repositories/home:/katacontainers:/releases:/${ARCH}:/${BRANCH}/xUbuntu_$(lsb_release -rs)/Release.key | sudo apt-key add -
sudo -E apt-get update
sudo -E apt-get -y install kata-runtime kata-proxy kata-shim
CRI-Oのインストール
https://github.com/cri-o/cri-o#installing-cri-o
. /etc/os-release
sudo sh -c "echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/x${NAME}_${VERSION_ID}/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list"
wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/x${NAME}_${VERSION_ID}/Release.key -O- | sudo apt-key add -
sudo apt-get update -qq
apt-get install -y cri-o-1.17
sudo systemctl enable crio
Ubuntuのパッケージは、1.18がまだ無いようなので1.17を利用した。
CRI-Oのランタイムの設定
https://github.com/kata-containers/documentation/blob/master/how-to/run-kata-with-k8s.md#cri-o
/etc/crio/crio.conf に書かれている設定を入れた。 デフォルトはruncのままにしてある。
[crio.runtime.runtimes.kata-runtime]
runtime_path = "/usr/bin/kata-runtime"
runtime_type = "oci"
kubernetesのインストール
kubeadmでインストール。
全ノードで
sudo modprobe overlay
sudo modprobe br_netfilter
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
sudo apt-get update && sudo apt-get install -y apt-transport-https curl
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
sudo apt-get update
sudo apt-get install -y kubelet=1.17.0-00 kubeadm=1.17.0-00 kubectl=1.17.0-00
sudo apt-mark hold kubelet kubeadm kubectl
cat <<EOF | sudo tee /etc/systemd/system/kubelet.service.d/0-crio.conf
[Service]
Environment="KUBELET_EXTRA_ARGS=--container-runtime=remote --cgroup-driver=systemd --runtime-request-timeout=15m --container-runtime-endpoint=unix:///var/run/crio/crio.sock"
EOF
sudo systemctl daemon-reload
sudo systemctl restart kubelet
コントロールプレーンで以下を実行。
sudo kubeadm init --skip-preflight-checks --cri-socket /var/run/crio/crio.sock --pod-network-cidr=10.244.0.0/16
実行後には、joinコマンドが表示されるので、今度はそれを各ノードで実行する。もし、見逃してしまった場合は、以下のコマンドで再表示できる。
kubeadm token create --print-join-command
前に入れたときは、CNIプラグイン入れないとNodeの状態がREADYにならなかったはずなのに、 今回試したらNodeが参加した時点でREADYになってた。ランタイムが違うから?そんなことある?
とりあえず、WeaveNetをいれておく。
kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
クラスタのテスト
OCIとして、runcを使うPodとkataを使うPodをデプロイしてみる
kubectl run hello-runc --image=gcr.io/google-samples/hello-app:1.0 --restart Never
cat <<EOF | kubectl apply -f -
apiVersion: node.k8s.io/v1beta1
kind: RuntimeClass
metadata:
name: kata
handler: kata-runtime
EOF
kubectl get pod hello-runc -o yaml > hello-kata.yaml
hello-kata.yamlを以下の通り編集
apiVersion: v1
kind: Pod
metadata:
labels:
run: hello-kata
name: hello-kata
spec:
containers:
- image: gcr.io/google-samples/hello-app:1.0
imagePullPolicy: IfNotPresent
name: hello-kata
dnsPolicy: ClusterFirst
restartPolicy: Never
runtimeClassName: kata
これを流したんたけどPodが起動しない。eventを見てみると以下のようなログが。
Failed to create pod sandbox: rpc error: code = Unknown desc = container create failed: failed to launch qemu: exit status 1, error messages from qemu log: Could not access KVM kernel module: No such file or directory
qemu-vanilla-system-x86_64: failed to initialize kvm: No such file or directory
今回ESXi上の仮想マシンでやったのだけど、CPUの仮想化を有効にするの忘れてた。仮想マシンの設定変更から、 「CPU仮想化 ハードウェア アシストによる仮想化をゲストOSに公開」を有効にしたところ解決。
kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
hello-kata 1/1 Running 0 9h 10.32.0.2 node1 <none> <none>
hello-runc 1/1 Running 0 9h 10.38.0.3 node2 <none> <none>
無事に起動したっぽい。
動作を見比べる
うまいことnode1とnode2に分散してPodを動かしたので、通常のruncで動くパターンとkataで動くパターンのプロセス構成などを見てみる。
kata-runtime list
kataで動いているコンテナのリストは、 kata-runtime list
で確認することができる。
- Node1 (kata利用)
$ sudo kata-runtime list
ID PID STATUS BU
NDLE CREATED OWNER
fa157caa041230c1593ced717618dc2f96a80f4c0704b7d965421a8e95dc791f 2850 running /run/containers/storage/overlay-containers/fa157caa041230c1593ced717618dc2f96a80f4c0704b7d965421a8e95dc791f/userdata 2020-07-11T23:51:20.244499159Z #0
4fe1ddb9154cbfc14a7ca514e2705b91f54bfc9b89300c940ff1000b2f0bd17c 3115 running /run/containers/storage/overlay-containers/4fe1ddb9154cbfc14a7ca514e2705b91f54bfc9b89300c940ff1000b2f0bd17c/userdata 2020-07-11T23:51:26.190503017Z #0
- Node2 (runc利用)
$ sudo kata-runtime list
ID PID STATUS BUNDLE CREATED OWNER
たしかに、Node1では動いているプロセスがいて、Node2にはいないことがわかる。 でも、なんで2つ? Podはひとつしか起動してないのに。
もう少しNode1側を詳しく見てみる。
$ sudo kata-runtime state fa157caa041230c1593ced717618dc2f96a80f4c0704b7d965421a8e95dc791f
{
"ociVersion": "1.0.1-dev",
"id": "fa157caa041230c1593ced717618dc2f96a80f4c0704b7d965421a8e95dc791f",
"status": "running",
"pid": 2850,
"bundle": "/run/containers/storage/overlay-containers/fa157caa041230c1593ced717618dc2f96a80f4c0704b7d965421a8e95dc791f/userdata",
"annotations": {
"io.katacontainers.pkg.oci.bundle_path": "/run/containers/storage/overlay-containers/fa157caa041230c1593ced717618dc2f96a80f4c0704b7d965421a8e95dc791f/userdata",
"io.katacontainers.pkg.oci.container_type": "pod_sandbox"
}
}
$ sudo kata-runtime state 4fe1ddb9154cbfc14a7ca514e2705b91f54bfc9b89300c940ff1000b2f0bd17c
{
"ociVersion": "1.0.1-dev",
"id": "4fe1ddb9154cbfc14a7ca514e2705b91f54bfc9b89300c940ff1000b2f0bd17c",
"status": "running",
"pid": 3115,
"bundle": "/run/containers/storage/overlay-containers/4fe1ddb9154cbfc14a7ca514e2705b91f54bfc9b89300c940ff1000b2f0bd17c/userdata",
"annotations": {
"io.katacontainers.pkg.oci.bundle_path": "/run/containers/storage/overlay-containers/4fe1ddb9154cbfc14a7ca514e2705b91f54bfc9b89300c940ff1000b2f0bd17c/userdata",
"io.katacontainers.pkg.oci.container_type": "pod_container"
}
}
コンテナタイプが違うのがわかる。公式のドキュメントのアーキテクチャのところを見ると、 pod_sandboxの中に、pod_containerがあるようだ。
https://github.com/kata-containers/documentation/blob/master/design/architecture.md
$ sudo kata-runtime exec 4fe1ddb9154cbfc14a7ca514e2705b91f54bfc9b89300c940ff1000b2f0bd17c ps
PID USER TIME COMMAND
1 root 0:00 ./hello-app
28 root 0:00 ps
$ sudo kata-runtime exec fa157caa041230c1593ced717618dc2f96a80f4c0704b7d965421a8e95dc791f ps
rpc error: code = Internal desc = Could not run process: container_linux.go:349: starting container process caused "exec: \"ps\": executable file not found in $PATH"
pod_contaierの方で、期待するアプリが動いていることが確認できた。sandboxのほうは、shすら起動できなかったので、何が動いているんだろうか。
psの結果
プロセスツリーも見比べてみた。適当にプロセスは実際のものから削っている。
- Node1 (kata利用)
systemd-+-2*[conmon-+-pause]
| `-{conmon}]
|-conmon-+-kube-proxy---7*[{kube-proxy}]
| `-{conmon}
|-conmon-+-kube-utils---8*[{kube-utils}]
| |-launch.sh---weaver---15*[{weaver}]
| `-{conmon}
|-conmon-+-kata-proxy---8*[{kata-proxy}]
| |-kata-shim---8*[{kata-shim}]
| |-qemu-vanilla-sy---3*[{qemu-vanilla-sy}]
| `-{conmon}
|-conmon-+-weave-npc-+-ulogd
| | `-9*[{weave-npc}]
| `-{conmon}
|-conmon-+-kata-shim---10*[{kata-shim}]
| `-{conmon}
|-crio---14*[{crio}]
|-kubelet---16*[{kubelet}]
`-lxcfs---2*[{lxcfs}]
- Node2 (runc利用)
systemd-+-3*[conmon-+-pause]
| `-{conmon}]
|-conmon-+-kube-proxy---8*[{kube-proxy}]
| `-{conmon}
|-conmon-+-kube-utils---8*[{kube-utils}]
| |-launch.sh---weaver---16*[{weaver}]
| `-{conmon}
|-conmon-+-weave-npc-+-ulogd
| | `-9*[{weave-npc}]
| `-{conmon}
|-conmon-+-hello-app---3*[{hello-app}]
| `-{conmon}
|-crio---14*[{crio}]
|-kubelet---16*[{kubelet}]
`-lxcfs---2*[{lxcfs}]
見比べてみると、たしかにruncだと目的のhello-appが直接動いているのに対して、 kataの場合は、hello-appは直接ホストから見えない。 kata-shimで隠蔽されていて、隔離された環境で動いていることがわかる。
まとめ
Kata Containersは、これまで安全にコンテナ実行するために使う、ぐらいしか聞いておらず どういう風に動くのかよくわかっていなかったが、今回構築してみてその動きが理解できた。 構築も、ドキュメントによって書いてあること違ったりでいくつかトラブルところもあったが、 だいたいログ見たらどこがあやしいかわかるし、それほど苦労することはなかった。 1枚噛んでるレイヤが増えるので、性能面とリソースのオーバーヘッドが気になるので、今後その辺見てみたい。
Share