kubeadmを用いてUbuntu22.04上で検証用k8sクラスタをシュッと立てる
背景
検証用で作る/壊すを簡単にできるk8sクラスタを作りたくなった。今までは適当に降ってきたクラスタを使ったり、minikube on docker desktop on M1 macでことを済ませていたけど、いくつかの理由により、kubeadm on ubuntu にしたかった。
やること
k8sクラスタ(とりあえずコントロールプレーン)をkubeadmを使ってubuntu上に構築する
やらないこと
各種初期化の自動化
初期化
kubeadmのインストール を済ませた上でkubeadmを使用したクラスターの作成を見ながら初期化する。Dockerから10.244...
、そもそもマシンには固定のIPを当てていて 192.168...
がすでに降ってきているため、DNSの設定で干渉しなさそうな 172.16.0.0/12
を使う
$ sudo kubeadm init --pod-network-cidr=172.16.0.0/12
[init] Using Kubernetes version: v1.28.4
(中略)
...
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join <your_ip>:6443 --token <token>
$ mkdir -p $HOME/.kube && sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config && sudo chown $(id -u):$(id -g) $HOME/.kube/config
動作確認
とりあえずコントロールプレーンを覗いてみる
$ k get po -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-5dd5756b68-lmrjl 1/1 Running 1 (2m47s ago) 2m54s
coredns-5dd5756b68-rb8sc 1/1 Running 1 (2m48s ago) 2m54s
etcd-hitode 1/1 Running 294 (91s ago) 3m28s
kube-apiserver-hitode 1/1 Running 268 (76s ago) 3m28s
kube-controller-manager-hitode 0/1 CrashLoopBackOff 2 (5s ago) 3m28s
kube-proxy-884d7 0/1 CrashLoopBackOff 2 (8s ago) 2m53s
kube-scheduler-hitode 1/1 Running 281 (102s ago) 4m2s
やばそう
kubeadmのトラブルシューティング#Podの状態がRunContainerError、CrashLoopBackOff、またはErrorとなる では
- kubeadm initの直後には、これらの状態ではPodは存在しないはずです。
となっている。
問題
- k8sのコントロールプレーンのほとんどのコンポーネントが正常に動作していない
- CrashLoopBackOff になっている、あるいは多くの回数のRESTARTが発生している
当たり前と言えば当たり前だけど、APIサーバが動かないとそもそもkubectlコマンドを発行することができない(のでデバッグがかなりしんどい)
$ k get po -n kube-system
The connection to the server 192.168.1.61:6443 was refused - did you specify the right host or port?
$ curl -k 192.168.1.61:6443
curl: (7) Failed to connect to 192.168.1.61 port 6443 after 0 ms: Connection refused
前提の確認
kubeadmのインストール#始める前に で書かれている条件を満たしているか確認する
マシンスペック
超余裕ある
swapがオフになっている
なっている
$ free -h
total used free shared buff/cache available
Mem: 62Gi 961Mi 49Gi 4.0Mi 11Gi 61Gi
Swap: 0B 0B 0B
MACアドレスのユニーク性
ハードウェアデバイスではユニークなアドレスが割り当てられる可能性が非常に高いですが、VMでは同じになることがあります
実機を使っている && 検証が若干面倒なので一旦割愛。
ネットワークアダプタの確認
複数のネットワークアダプターがあり、Kubernetesコンポーネントにデフォルトで到達できない場合
少なくとも一度は k get po -n kube-system
の発行に成功していたので、問題なさそう
ポート開放
6443はあいている
$ sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), deny (routed)
New profiles: skip
To Action From
-- ------ ----
...
6443/tcp ALLOW IN Anywhere
6443/tcp (v6) ALLOW IN Anywhere (v6)
kubeadm, kubelet, kubectl のバージョン
全てのマイナーバージョンまで一致しているので、k8sのバージョニングポリシー(マイナーひとつ分までサポート)的にも問題ない
$ kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"28", GitVersion:"v1.28.2", GitCommit:"89a4ea3e1e4ddd7f7572286090359983e0387b2f", GitTreeState:"clean", BuildDate:"2023-09-13T09:34:32Z", GoVersion:"go1.20.8", Compiler:"gc", Platform:"linux/amd64"}
$ kubelet --version
Kubernetes v1.28.2
$ kubectl version
Client Version: v1.28.2
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.28.4
コントロールプレーンノードのkubeletによって使用されるcgroupドライバーの設定
Dockerを使用した場合、kubeadmは自動的にkubelet向けのcgroupドライバーを検出し、それを実行時に/var/lib/kubelet/kubeadm-flags.envファイルに設定します。
と書いてある。
$ sudo cat /var/lib/kubelet/kubeadm-flags.env
KUBELET_KUBEADM_ARGS="--container-runtime-endpoint=unix:///var/run/containerd/containerd.sock --pod-infra-container-image=registry.k8s.io/pause:3.9"
当該ファイルを確認しても、cgroupに関する記述はなさそうだけど問題ないのか。。??
使用されているcgroupを確認する
kubelet
systemdのがもの使われている
$ sudo cat /var/lib/kubelet/config.yaml | yq e '.cgroupDriver' -
systemd
https://kubernetes.io/ja/docs/tasks/administer-cluster/kubeadm/configure-cgroup-driver/ 辺りを見るとこれはデフォルトの挙動っぽい。
v1.22では、ユーザーがKubeletConfigurationのcgroupDriverフィールドを設定していない場合、kubeadmはデフォルトでsystemdを設定するようになりました。
containerdで使用されているcgroupも確認する
containerd
なぜかconfigが生えていない(なんで??)ので、生やす
$ ls /etc/containerd
config.toml.bak
$ containerd config default | sudo tee /etc/containerd/config.toml
これを覗いてみると、SystemdCgroup = false
という怪しげな一行が観測できる。
$cat /etc/containerd/config.toml
ShimCgroup = ""
SystemdCgroup = false
こいつを true
に書き換えて、systemctl restart containerd
で再起動させてやる。
参考
めちゃくちゃ参考になる記事が出てきた: Ubuntu 22.04でのKubernetesクラスター構築(ContainerdとSystemdCgroup)
kubeadm を再起動させる
削除
別にクラスタを消して困ることもないし、そもそもビルド && スクラップを雑にやりたいのが当初の目的だったので、sudo kubeadm reset && rm -rf ~/.kube
で諸々削除する
やり直し
をもう一度やる
確認
(RESTARTSの値がやばそうなのがいくつかあるけど)うまく動いていそう :tada:
$ k get po -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-5dd5756b68-2vvw4 1/1 Running 0 8m16s
coredns-5dd5756b68-8mnrp 1/1 Running 0 8m16s
etcd-hitode 1/1 Running 309 8m32s
kube-apiserver-hitode 1/1 Running 282 8m32s
kube-controller-manager-hitode 1/1 Running 19 8m30s
kube-proxy-9ffm5 1/1 Running 0 8m16s
kube-scheduler-hitode 1/1 Running 294 8m29s
RESTARTS の値は累計値とっているから??(pod NAMEが変わらないものは kubeadm reset
によって0にならないから??)
シングルノードクラスタ上にpodを展開する
コントロールプレーンが展開されているノードの taint の削除
コントロールプレーンの各種podが正しく展開されたのできちんと動きそうだけど、一応シングルクラスタノードとして動作するか検証する。
k8sはデフォルトでは、コントロールプレーンが展開されているノードにpodをスケジュールしてくれない。これはtaintによって制御されており、確かに確認できる
$ k get node
NAME STATUS ROLES AGE VERSION
hitode Ready control-plane 23m v1.28.2
$ k describe node hitode | grep -i taint
Taints: node-role.kubernetes.io/control-plane:NoSchedule
(taintの良い感じの確認方法がわからず、確認方法がすごい荒っぽい。。)
とりあえず外してあげる
$ k taint nodes --all node-role.kubernetes.io/control-plane-
node/hitode untainted
pod を展開する
ようやく hello-world ができる。
$ k run hello-world --image=hello-world --restart=Never
pod/hello-world created
$ k get po
NAME READY STATUS RESTARTS AGE
hello-world 0/1 Completed 0 3s
めでたい
結論
- Ubuntu 22.04上でkubeadmを用いてk8sクラスタを作成する際には、(デフォルトで??)kubeletとcontainerdで使用しているcgroupが異なるため、動作がものすごい不安定になる
- コントロールプレーンのほとんどのコンポーネントがCrashLoopBackOffあるいはrestartを繰り返す
- containerdのconfig(
/etc/containerd/config.toml
)の設定をいい感じにしてやると解決する