0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

K8s on ラズパイ(ARM64)にcri-o+podmanでworkerを追加してみた

Last updated at Posted at 2020-12-28

はじめに

2020/12末時点で、kubernetesのworkerノードを「cri-o」と「podman」で構築してみた結果です。

環境

  • Raspberry Pi 4B
  • OS: RaspiOS Lite(ARM64) beta 2020/8/24 (※本手順では最終的にkernelの入れ替えをしています)
  • kubernetes: v1.20.1 (※タイミング悪くv1.20.0のマスターにv1.20.1を追加してます)

構築した手順

メモ書き程度ですが、ご参考まで。
RaspiOS Lite(ARM64)をインストール後、ホスト名やネットワークの設定後の状態からです。
https://downloads.raspberrypi.org/raspios_lite_arm64/images/raspios_lite_arm64-2020-08-24/

1. スワップ無効化

swap有効化のままでもkubeletがインストールできる方法もあるようですが、私は無効化してます。

dphys-swapfile swapoff
systemctl disable dphys-swapfile

2. cgroupsの設定

cgroups...kernelによってsysfs上の階層構成が変わったりしてたり、よくわかってません。

perl -pi -e "s/^/cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1 /" /boot/cmdline.txt 

3. cri-o,podmanのインストール

arm64のパッケージが含まれる最新バージョンが「1.18.3」のようです。コンパイルすればもっと最新が使えそうですがやってません。

OS=Debian_Unstable
VERSION=1.18:1.18.3

curl -L https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:$VERSION/$OS/Release.key | sudo apt-key --keyring /etc/apt/trusted.gpg.d/libcontainers.gpg add -
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/Release.key | sudo apt-key --keyring /etc/apt/trusted.gpg.d/libcontainers.gpg add -

cat <<EOF | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.list
deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/ /
EOF

cat <<EOF | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/ /
EOF

ここまでは公式の手順で良いのですが、1.18.3は「1.18:/1.18.3」という階層にあるので修正します。
一旦「apt update」してエラーが出ないか確認しましょう。

perl -pi -e 's/18:/18:\//' /etc/apt/sources.list.d/devel\:kubic\:libcontainers\:stable\:cri-o\:1.18\:1.18.3.list
apt update

Debian10用にバックポートされた「libseccomp2」パッケージ用のリポジトリ追加です。

echo 'deb http://deb.debian.org/debian buster-backports main' >> /etc/apt/sources.list
apt update

パッケージのインストールをします。
dockerコマンドの代替えである「podman」はkubernetes関連のパッケージと競合しているようなので、「podman-rootless」をインストールします。
https://github.com/containers/podman/issues/5296

apt -t buster-backports install libseccomp2
apt install cri-o cri-o-runc podman-rootless

インストールできたらcrioサービスを有効化します。

systemctl enable crio

4. kubelet,kubeadm,kubectlのインストール

定番なので説明は書きませんが、「apt update」が失敗する事があるので、成功するまで「apt update」してます。

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" >> /etc/apt/sources.list.d/kubernetes.list
apt update
apt install kubelet kubeadm kubectl

バージョン指定でインストールする場合は以下のように指定できます。
apt install kubelet=1.20.0-00 kubeadm=1.20.0-00 kubectl=1.20.0-00

5. その他設定

必要なカーネルパラメータを追加しておきます。

cat <<EOF > /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

必要な前提カーネルモジュールを定義しておきます。

echo "br_netfilter" >> /etc/modules

一応、nftablesを使わないようにします。詳しく調べてませんが、kube-proxyはnftablesで良くても、flannelがiptablesじゃなきゃダメなのかなと思ってます。

update-alternatives --set iptables /usr/sbin/iptables-legacy

dockerを利用しないので、iptablesのFORWARDのデフォルトポリシーはACCEPTのままなはずですが、DROPの場合はACCEPTに変更してください。

kubeletがcgroup-driverとしてsystemdを使うように設定します。

echo "KUBELET_EXTRA_ARGS=--cgroup-driver=systemd" >> /etc/default/kubelet

本記事前提OSのカーネル以外の場合は、この状態でrebootして「kubeadm join」すればうまく動くかもしれません。

6. kernelの入れ替え

RaspiOS Lite(ARM64)の場合は、カーネルがよろしくないようでkubernetesクラスタに参加できてもPodがデプロイされませんでした。
具体的には「〜cpu.cfs_period_us: permission denied」と出てPodのデプロイに失敗します。
調べると以下の記事を発見しました。(最初からここ見ればよかったなぁ〜)
https://gist.github.com/dmesser/b110d717b372e36607b3fb75b52ab0ca

ただ、実際カーネルを調べると「CONFIG_CFS_BANDWIDTH」は有効になっているはずなのですが、/procや/sysの階層がkubeletが想定しているような階層になっていないように思えました。
どちらにせよ、おそらくカーネルを再コンパイルしなくてはならないと思われますが、Cephを導入した際にrbdを有効にしたカスタムカーネルがあったので、試しに入れ替えたらうまく動きました。

カーネルをコンパイルした手順は以下になります。
https://qiita.com/Y-Shikase/items/c6fffbbd11a3d039b380#kernel%E3%83%93%E3%83%AB%E3%83%89

上記手順でカーネルを入れ替えて再起動後、「kubeadm join」でうまくクラスタへの参加とPodのデプロイができました。

masterノードでの作業
# kubeadm token create
cbrhlc.ckwxfkt2zfv75b4b
# openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
9dce510f61f13a841dc94fd43d27c5264a76c671deae350363069c6e43c04879

tokenとhashをメモる。

workerノードでの作業
kubeadm join 10.0.0.1:6443 --token cbrhlc.ckwxfkt2zfv75b4b --discovery-token-ca-cert-hash sha256:9dce510f61f13a841dc94fd43d27c5264a76c671deae350363069c6e43c04879

注意点

自炊イメージを使用している場合

dockerでコンテナイメージを自炊して、kubernetes上で使っている場合には少し注意が必要です。
dockerではリポジトリに階層を付けない事ができるのですが、podmanでは「localhost/」という階層が必ず付きますので、dockerとpodmanで混在している場合はpodman側に合わせなければなりません。
dockerのworkerでは自炊のイメージにエイリアスで「localhost/」のリポジトリ名を付けて、kubernetesのyamlも「image: lcoalhost/〜」としました。

kubeletのエラー

動いてはいますが、kubeletがエラーを吐いてます。
スクリーンショット 2020-12-28 18.22.55.png

コンテナのデバッグ

cri-oの不具合でexecが実行できません。
https://github.com/cri-o/cri-o/issues/4280

スクリーンショット 2020-12-28 20.15.39.png

ARM64向けの新バージョンのcri-oが出るのを待つか、最新を自分でコンパイルする必要がありそうです。

[追記]
再構築する前にダメ元でxUbuntu用のcri-o 1.20.0をインストールしたらデバッグできるようになりました。

wget http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.20/xUbuntu_20.04/arm64/cri-o_1.20.0~0_arm64.deb
dpkg -i cri-o_1.20.0~0_arm64.deb

また、1.20.0にしたからかはちゃんと確認してませんが、イベントに以下のWarningが定期的に出るようになりました。

$ kubectl get events -A -w
       :
default          0s          Warning   ImageGCFailed             node/maya                                       failed to get imageFs info: non-existent label "crio-images"

kubeletのログは以下のようなログが出ます。

Jan  3 00:00:52 maya kubelet[455]: E0103 00:00:52.287957     455 log_metrics.go:66] failed to get pod stats: failed to get imageFs info: non-existent label "crio-images"

対策は、以下のissuesに書かれているように、サービス起動ファイルの[Unit]に「Before=kubelet.service」を追記しましょう。
https://github.com/cri-o/cri-o/issues/4437

dockershim vs cri-o

大袈裟な書き方ですが、同じHW構成でコンテナランタイムだけ違うworkerの無風状態での負荷を比較しました。
Loadがdockerは1.2くらいの平均で、cri-oは0.6くらいの平均になりました。cri-oは100MBくらいメモリ使用量も少なかったです。
スクリーンショット 2020-12-26 15.24.56.png
スクリーンショット 2020-12-26 18.05.45.png
スクリーンショット 2020-12-26 18.14.58.png

podmanについて

まだ使い込んでないのですが、Dockerfileからのbuildができたので、docker互換として使えるようです。

「images」はそのまま使えましたし、「load/save」も使えそうです。
ただ、「ps」は表示されません。
スクリーンショット 2020-12-28 18.02.53.png

CRI経由で作成されたものだからかもしれませんが、crictlコマンドで表示できました。
スクリーンショット 2021-01-04 14.38.15.png

おわりに

色々試しましたが以下のような結果になりました。

・podmanでDockerfileからのbuild、イメージのsave/loadはできたので、脱dockerはできそう
・負荷はdockerより軽い
・cri-o 1.18.3では不具合によりコンテナのデバッグできない→xUbuntu用のcri-o 1.20.0で動いた!?

新バージョンのcri-oをコンパイルする元気が無かったので、個人的には「もう少し待った方がいいかなー」という感じでした。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?