Kubernetes(k8s)クラスタでnodeが飛んだので復旧した話

ある日、こんなことが起きました。
いつも通りにRaspberry piのKubernetesクラスタを動かすと…
一つのnodeが上がりません;;
HDMIを接続して確認すると /が飛んでいる様ですw
なので再度nodeを一から作成しなおしました。

手順はシンプル

Raspberry piのnodeのインストールはすでに記事にしていますのでそれを参考にしました…

http://35.78.51.61/archives/2859

ここでは書いていませんがこのままだと動きません!

kubeが最新ではDocker問題で動きません。
なので動くバージョンを指定しました

wataru@k8s-worker1:~ $ sudo apt-get install -y kubelet=1.23.6-00 kubeadm=1.23.6-00 kubectl=1.23.6-00

join先のnodeを空ける

master側で現状を確認すると…

wataru@k8s-master:~ $ kubectl get node
NAME          STATUS     ROLES                  AGE    VERSION
k8s-master    Ready      control-plane,master   199d   v1.23.6
k8s-worker1   NotReady   <none>                 199d   v1.23.6
k8s-worker2   NotReady   <none>                 199d   v1.23.6
k8s-worker3   NotReady   <none>                 199d   v1.23.6
k8s-worker4   NotReady   <none>                 199d   v1.23.6
k8s-worker5   NotReady   <none>                 199d   v1.23.6
k8s-worker6   NotReady   <none>                 199d   v1.23.6
k8s-worker7   NotReady   <none>                 199d   v1.23.6

今回この中のk8s-woker1が飛んだので削除した方が良いです。
削除するとこんな感じになります

wataru@k8s-master:~ $ kubectl delete node k8s-worker1
node "k8s-worker1" deleted
wataru@k8s-master:~ $ kubectl get node
NAME          STATUS     ROLES                  AGE    VERSION
k8s-master    Ready      control-plane,master   199d   v1.23.6
k8s-worker2   NotReady   <none>                 199d   v1.23.6
k8s-worker3   NotReady   <none>                 199d   v1.23.6
k8s-worker4   NotReady   <none>                 199d   v1.23.6
k8s-worker5   NotReady   <none>                 199d   v1.23.6
k8s-worker6   NotReady   <none>                 199d   v1.23.6
k8s-worker7   NotReady   <none>                 199d   v1.23.6

はい、歯抜けになりました

相変わらずjoinで詰まる

最終的にkubectl joinすれば入ります。
kubectl joinのコマンドはこんな感じです

wataru@k8s-worker1:~ $ sudo kubeadm join 192.168.1.221:6443 --token <<トークン>> --discovery-token-ca-cert-hash <<hash>> 

これで!
前回joinしたコマンドを引っ張り出しましたがこれではエラーになってjoinできません…

wataru@k8s-worker1:~ $ sudo kubeadm join 192.168.1.221:6443 --token mehljf.kbpf7oazqxwhfft4         --discovery-token-ca-cert-hash sha256:20fbb36fde703aaba4d823e0a506c3866fe66f2c818c5685c52034bdc2c908ea 
[preflight] Running pre-flight checks
	[WARNING SystemVerification]: missing optional cgroups: hugetlb
error execution phase preflight: couldn't validate the identity of the API Server: cluster CA found in cluster-info ConfigMap is invalid: none of the public keys "sha256:e06d2713682eae1387b7c16a29b4e293b03d670914b9f0af349d096e690d473e" are pinned
To see the stack trace of this error execute with --v=5 or higher

原因を調査!とかいう前にトークンとhashが正しくないってのはすぐにわかります。

では、トークンとhashってどこで確認するのか?

joinするトークン

トークンはmaster側で管理していますので、token一覧を確認します…

wataru@k8s-master:~ $ sudo kubeadm token list

はい、トークンはありません…
なのでjoinコマンドは無効です

なのでトークンを作成します

wataru@k8s-master:~ $ sudo kubeadm token create
mehljf.kbpf7oazqxwhfft4
wataru@k8s-master:~ $ sudo kubeadm token list
TOKEN                     TTL         EXPIRES                USAGES                   DESCRIPTION                                                EXTRA GROUPS
mehljf.kbpf7oazqxwhfft4   23h         2022-12-02T01:45:54Z   authentication,signing   <none>                                                     system:bootstrappers:kubeadm:default-node-token

token createコマンドの標準出力でtokenは発行されますが、有効期限の確認はlistで行えます。
24時間くらいなので再セットアップが必要な場合は必ずトークンを作成する必要があると思っててもOKでしょう

hashを確認する

トークンは分かりましたので次にhashを確認します

答えから言いますと、コマンド一発で発行されます

wataru@k8s-master:~ $ openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | \
   openssl dgst -sha256 -hex | sed 's/^.* //'
e06d2713682eae1387b7c16a29b4e293b03d670914b9f0af349d096e690d473e

コマンドの解説は… いいや、コピペしてお使いください

joinコマンドではこのhashキーにsha256を付与して使ってください

sha256:e06d2713682eae1387b7c16a29b4e293b03d670914b9f0af349d096e690d473e

再度joinする

トークンとhashが分かりましたのでnodeをjoinさせます

wataru@k8s-worker1:~ $ sudo kubeadm join 192.168.1.221:6443 --token mehljf.kbpf7oazqxwhfft4 --discovery-token-ca-cert-hash sha256:e06d2713682eae1387b7c16a29b4e293b03d670914b9f0af349d096e690d473e
[preflight] Running pre-flight checks
	[WARNING SystemVerification]: missing optional cgroups: hugetlb
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
W1201 10:50:50.549680    5302 utils.go:69] The recommended value for "resolvConf" in "KubeletConfiguration" is: /run/systemd/resolve/resolv.conf; the provided value is: /run/systemd/resolve/resolv.conf
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

注意は無視してクラスタにjoinできました。

master側で確認してnodeが増えていることを確認します

wataru@k8s-master:~ $ kubectl get node
NAME          STATUS     ROLES                  AGE    VERSION
k8s-master    Ready      control-plane,master   199d   v1.23.6
k8s-worker1   NotReady   <none>                 25s    v1.23.6
k8s-worker2   NotReady   <none>                 199d   v1.23.6
k8s-worker3   NotReady   <none>                 199d   v1.23.6
k8s-worker4   NotReady   <none>                 199d   v1.23.6
k8s-worker5   NotReady   <none>                 199d   v1.23.6
k8s-worker6   NotReady   <none>                 199d   v1.23.6
k8s-worker7   NotReady   <none>                 199d   v1.23.6

はい、k8s-worker1が復活していることを確認できました。

しばらく放置すると…

wataru@k8s-master:~ $ kubectl get node
NAME          STATUS     ROLES                  AGE     VERSION
k8s-master    Ready      control-plane,master   199d    v1.23.6
k8s-worker1   Ready      <none>                 4m46s   v1.23.6
k8s-worker2   NotReady   <none>                 199d    v1.23.6
k8s-worker3   NotReady   <none>                 199d    v1.23.6
k8s-worker4   NotReady   <none>                 199d    v1.23.6
k8s-worker5   NotReady   <none>                 199d    v1.23.6
k8s-worker6   NotReady   <none>                 199d    v1.23.6
k8s-worker7   NotReady   <none>                 199d    v1.23.6

Readyになります

終いに

今回はk8sクラスタのnodeが吹っ飛んだので復旧方法をメモしておきました。

セットアップは別記事にしていましたが、バージョンを指定しないと動かないことと、joinのトークン周りを詳しく書いてみました。

ちゃんと普段から使わないとなw