重力に縋るな

千種夜羽です

ラズパイで Kubernetesを 立ててみる(575)

はい.

Kubernetes,去年ぐらいから名前は聞いたことあったんですよね.なんなのかはまったく知らなかったけど. たまにTLに出てくるやつ.あとオタクがプロフィールにk8sとか書いてたりする. まあk8s=Kubernetesだということを知ったのもだいぶ最近なので,完全に謎の文字列として見ていましたが*1

じゃあなんで急に手を出したのかというと,KOBA789とかいうオタクが自宅サーバで使っていて,Kubernetes The Hard WayしているところやArgoCDからポチポチやってpodがポコポコ生えたりする様子を見せてもらったりしたんですよね. しかもこれがクラスタ上で動いているらしい.高校生の時にノートPC3,4台並べてMPIで並列計算や!とかやっていた程度には計算機クラスタという概念に対する憧れみたいなものもあるので,これはやるしかねえなと思ったのでした.

一応簡単にKubernetesがどんなものか書いておくと,コンテナに固めたアプリケーションをクラスタに対してガンガンデプロイしていくための物体です. あらゆるリソースをYAMLで記述し(マニフェスト),それをKubernetesに対して適用する形でデプロイとか設定とかをやっていきます. そんんでもってクラスタ上で動いているのでもちろんコンテナをスケールアウトさせることとかもできる,みたいなところですかね.

そんなかんじのものなので,クソデカクラウドサービスの裏側とかで結構使われているらしいです. まあそんなものを自宅で飼う必要性は皆無なわけですが,実は大学に入ってから計算機が増えたこともあって,自室内にちょこちょこサーバを立てて使ってるんですよね*2. 去年はそれらをほぼすべてdocker-composeに移行したりしてました.こいつらは既にコンテナになっている. なので今年はこいつらをKubernetesに移行してみたいという野望があったりします.楽しそうなので. 今回はその前に色々な概念を理解するためにラズパイで雑にKubernetesクラスタを作ってみます. 前置き終わり,

ではやっていきましょう.

ラズパイのセットアップ

オタクの皆さんの散らかった部屋にはラズパイが山のように転がっていると思うんですが,僕は無いんですよね. なので自室ネットワークのクソデカSPoF太郎になっているラズパイとなんか前にラズパイ欲しいってツイートしたら大学教員から高速発射されてきたラズパイ(何?)を使うことにしました.

したんですが,なんか机の上の紙束の下に埋もれてたラズパイがあったのでこれと飛んできたラズパイを使うことにしました. クソデカSPoF太郎はマジでクソデカSPoF太郎なので,こいつが死ぬとインターネットってやつから切り離されちゃうんですよね.

まあ別に実用するわけではないですし,専用で使えるノードが2個(control plane, worker)あればええねん. そもそもこれ全部3B+とかなので実用はスペック的にもやや無理がある.

送られてきたラズパイにはGUI付きのRaspbian,なんか出てきたラズパイにはRaspbianが入っていたので,とりあえずこれらは吹き飛ばしてなんか別のものを入れます. なんか出てきたラズパイは高校生の時に使っていたやつだったらしく,受験期に限界になって部屋の電灯のAPIをインターネットに公開してツイキャスで配信とかしてたやつ*3スクリプトとかが出てきて懐かしい気持ちになるなどしました.

で何を入れるかは色々調べてHypriotとかと迷ったんですが,そういや僕の部屋で動いているディストリはおそらく全てArch Linuxだったな,と思い直して(?),Arch Linux ARMを入れることにしました. SPoF太郎もそうだし.ただしせっかくなのでAArch64版を入れることにしました.といってもtar.gzをAArch64版にするだけ.

archlinuxarm.org

インストールできたらホスト名を決めます.例によってここが一番時間かかった気すらする.

https://imgs.xkcd.com/comics/permanence.png

xkcd: Permanence

結局あまり考えずに(は?),クラスタ→星団ということで順番にプレイアデス7姉妹の名前を付けていくことにしました.これが7台になることは無いと思うけど. なんでプレアデス星団かって?だって散開星団は若くて寿命が短い星が多いから...

やる

ようやく肝心のKubernetesのインストールです.といっても最近は超簡単にクラスタをセットアップできるツールが色々あるらしいです.やったね.

ということでk0s - Zero Friction Kubernetesを使ってセットアップしようとしたんですが,めちゃくちゃFrictionしまくったので公式ツールのkubeadmを自分でチマチマ叩くことにしました. そもそもわざわざ実際にクラスタ組んでるのがminikubeがうまく動かなかったからだったりもする(なんでだよ).まあたぶん僕の環境が悪い.

ここらへんを見てやっていきます.まずはコンテナランタイムから.

kubernetes.io

コンテナランタイムはcontainerdを使うことにしました.Docker非推奨になったらしいし,どうせDockerはcontainerd使ってるし. 次やるときはcri-oにしてみますかね.コンテナランタイムがCRI*4に準拠しているやつなら自由に選べるというのはおもしろいですね.

$ cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF

$ sudo modprobe overlay
$ sudo modprobe br_netfilter
$ cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
$ sudo sysctl --system
$ yay -S containerd
$ sudo systemctl enable --now containerd
$ sudo mkdir /etc/containerd

これの後に/etc/containerd/config.tomlを作ってゴチャゴチャ弄ってオンオンkubeletが動かん,とか言ってたんですがそもそもこのファイルを消したら動いた回などがありました.

github.com

次にkubeadmを入れます.

kubernetes.io

$ cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF
$ sudo reboot
$ lsmod | grep br_netfilter
br_netfilter           28672  0
bridge                245760  1 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
EOF
$ sudo sysctl --system
$ yay -S kubeadm-bin kubelet-bin kubectl-bin
$ kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.2", GitCommit:"faecb196815e248d3ecfb03c680a4507229c2a56", GitTreeState:"clean", BuildDate:"2021-01-13T13:25:59Z", GoVersion:"go1.15.5", Compiler:"gc", Platform:"linux/arm64"}
$ sudo systemctl daemon-reload
$ sudo systemctl enable --now kubelet

Kubernetes本体は迂闊にバージョン上げると死ぬらしいのでIgnorePkgに追加しておきます.

これで純美ができたのでControl Plane(master node)を建立します.

$ yay -S crictl ebtables ethtool socat conntrack-tools
$ sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --ignore-preflight-errors=Mem --cri-socket unix:///run/containerd/containerd.sock

事前に--dry-runしてからやった方がいいです.失敗したらkubeadm reset

成功したら$HOME/.kubeを作れとか言われるのでその通りにする.あとちゃんと/etc/hostsは書いておいた方がいい.

あとはWorker Nodeをセットアップする.

# pacman-key --init
# pacman-key --populate archlinuxarm
# pacman -Syu
# pacman -S vim sudo git
# pacman -S --needed git base-devel
# EDITOR=vim visudo
# useradd -m -G wheel -s /bin/bash sksat
# passwd sksat
$ mkdir build
$ cd build
$ git clone https://aur.archlinux.org/yay.git
$ cd yay
$ makepkg -si
$ sudo vim /etc/fstab
$ sudo vim /etc/hostname
$ cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
$ cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
$ cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
$ sudo sysctl --system
$ sudo reboot
$ yay -S containerd kubeadm-bin kubelet-bin kubectl-bin cni-plugins
$ sudo systemctl enable --now containerd
$ yay -S crictl ebtables ethtool socat conntrack-tools
$ sudo systemctl daemon-reload
$ sudo systemctl enable --now kubelet
$ kubeadm join electra:6443 --token <TOKEN> --discovery-token-ca-cert-hash sha256:<HASH>

ちゃんとjoinできてたらkubectl get nodesを叩くとちゃんとノードが生えていてうれしい. ただしstatusがNotReadyとか書いてあるので,これをReadyにする必要がある. ここで必要なのがオーバーレイネットワークというやつ.これも色々実装があっておもしろい.今回はラズパイなのでシュッと動いてくれそうなflannelを使うことにした(なので--pod-network-cidrを10.244.0.0/16にした).

coreos.com

あとflannel回りでコケている時はkubeadm resetする前にこれもやる.

# ip link delete cni0
# ip link delete flannel.1

ちゃんと動くとノードがReadyになってうれしい.よかったね.

使う

後はwatch kubectl get pods --all-namespacesでも見ながらpodをポコポコ生やしたり潰したりして遊びます.たのしい.

これで終わってもいいんですが,正直kubectlを叩くのはダルい.あとYAMLを手元でゴチャゴチャ弄ってapplyするのはダルい.どうにかならんのか.ということでどうにかする.

どうにかするのがGitOpsとかいうやつ.これもオタクがツイートしているのは見たことある文字列だな. まあマニフェストファイルとかをGitで管理して運用をGitリポジトリの管理にすり替えちゃえばいいじゃん,みたいなかんじなんですかね. サーバにsshしてコマンド叩いて,みたいな作業を消せてうれしいしrevertとかもできる.

そんんでもってこのGitOpsをKubernetesでいいかんじにやるためのやつがArgoCDというわけです. 最初にオタクに見せてもらってオオ〜となったやつ.まあ名前忘れてたんで「アレdashboardの実装の一つなのか...?」とか思って探したりしたんですが(その後このYAML共はどう管理したらええねんとなって普通にGitOpsの文脈から再発見した).

argoproj.github.io

というわけでArgoCDでポチポチしたらGitリポジトリと繋がってポンポンpodが生やせるしいいかんじに可視化されてうれしい,となればよかったんですがうまくいきませんでした.かなしい. というか色々確かめてみた結果(ログと実態がだいぶ違ったりして厳しかった),pod内部からの名前解決が異様に遅い上にできたりできなかったりしているっぽいことが分かりました.そもそもセットアップ微妙に失敗している可能性がある.かなしい.でもCoreDNSのpod生きてるしなあ.なぜ〜〜〜

ということで煮えきらないかんじですが今回はここで終了です.どうにかなったら追記します.

*1:微妙に界隈が違う人が多めだったりして特に調べようとも思わなかったんだと思う.たぶんはいはいWebのなんかね,ぐらいの認識

*2:よく使っているのはCoreDNS,Nextcloud,Jellyfinあたり

*3:https://twitcasting.tv/sksat_tty/movie/516218129

*4:Container Runtime Interface