Kubernetesクラスターでkubectlが通らなくなった【証明書期限切れ】
自宅サーバー(Proxmox)でHA構成のKubernetesクラスターを構築してから早一年が経ちました。 詳しくはこちらの記事でまとめています。
しかし、久しぶりに様子を見てみるとkubectlなどのコマンドが全く通らなくなってしまいました。今回はそのトラブルシューティングをまとめようと思います。
エラー内容
最初はk9sが落ちることに気づき、kubectlコマンドを実行してみてもtimeoutが生じていることが確認できました。
$ kubectl get nodes
E0613 09:31:17.589658 26729 memcache.go:265] couldn't get current server API group list: Get "https://192.168.1.90:6443/api?timeout=32s": net/http: TLS handshake timeout
E0613 09:31:32.139369 26729 memcache.go:265] couldn't get current server API group list: Get "https://192.168.1.90:6443/api?timeout=32s": read tcp 192.168.1.85:40754->192.168.1.90:6443: read: connection reset by peer - error from a previous attempt: EOF
再起動しても変わらず、control planeの前段にリバースプロキシを設置していたためそちらの問題かとも思いましたが、リバースプロキシ自体は問題なさそうでした。
また、今まで動いていたのが急に動かなくなったのも気になりました。 以前はcontrol planeのストレージ容量が無くなり落ちたことがありましたが、容量も問題なさそうでした。
原因
タイトルでお察しの通りだと思いますが、結局、原因はkubernetesクラスターの証明書が切れていたことが問題でした。
control planeに入って、証明書の期限を確認してみるととっくに期限が切れていることがわかりました。
$ sudo kubeadm certs check-expiration
[check-expiration] Reading configuration from the cluster...
[check-expiration] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[check-expiration] Error reading configuration from the Cluster. Falling back to default configuration
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
admin.conf Apr 06, 2024 16:36 UTC <invalid> ca no
apiserver Apr 06, 2024 16:36 UTC <invalid> ca no
apiserver-etcd-client Apr 06, 2024 16:36 UTC <invalid> etcd-ca no
apiserver-kubelet-client Apr 06, 2024 16:36 UTC <invalid> ca no
controller-manager.conf Apr 06, 2024 16:36 UTC <invalid> ca no
etcd-healthcheck-client Apr 06, 2024 16:36 UTC <invalid> etcd-ca no
etcd-peer Apr 06, 2024 16:36 UTC <invalid> etcd-ca no
etcd-server Apr 06, 2024 16:36 UTC <invalid> etcd-ca no
front-proxy-client Apr 06, 2024 16:36 UTC <invalid> front-proxy-ca no
scheduler.conf Apr 06, 2024 16:36 UTC <invalid> ca no
CERTIFICATE AUTHORITY EXPIRES RESIDUAL TIME EXTERNALLY MANAGED
ca Mar 18, 2033 05:46 UTC 8y no
etcd-ca Mar 18, 2033 05:46 UTC 8y no
front-proxy-ca Mar 18, 2033 05:46 UTC 8y no
証明書が切れていことで、クラスター内の通信がtimeoutしていたようです。
これは推測ですが、Kubernetesに載せているアプリケーション自体がずっと動いていたのは、既にnodeでstartしたpodは、他nodeとの通信がなくとも動き続けることができるからではないかと思います。
もしかしたらpodが落ちてしまったらrestartできないかもしれません。
対処法
対処法として、証明書を更新する必要があります。
まず、control planeに入って、以下を実行します。
$ sudo kubeadm certs renew all
[renew] Reading configuration from the cluster...
[renew] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[renew] Error reading configuration from the Cluster. Falling back to default configuration
certificate embedded in the kubeconfig file for the admin to use and for kubeadm itself renewed
certificate for serving the Kubernetes API renewed
certificate the apiserver uses to access etcd renewed
certificate for the API server to connect to kubelet renewed
certificate embedded in the kubeconfig file for the controller manager to use renewed
certificate for liveness probes to healthcheck etcd renewed
certificate for etcd nodes to communicate with each other renewed
certificate for serving etcd renewed
certificate for the front proxy client renewed
certificate embedded in the kubeconfig file for the scheduler manager to use renewed
Done renewing certificates. You must restart the kube-apiserver, kube-controller-manager, kube-scheduler and etcd, so that they can use the new certificates.
証明書の期限を確認してみると、確かに更新されていることがわかります。
$ sudo kubeadm certs check-expiration
[check-expiration] Reading configuration from the cluster...
[check-expiration] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[check-expiration] Error reading configuration from the Cluster. Falling back to default configuration
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
admin.conf Jun 14, 2025 14:26 UTC 364d ca no
apiserver Jun 14, 2025 14:26 UTC 364d ca no
apiserver-etcd-client Jun 14, 2025 14:26 UTC 364d etcd-ca no
apiserver-kubelet-client Jun 14, 2025 14:26 UTC 364d ca no
controller-manager.conf Jun 14, 2025 14:26 UTC 364d ca no
etcd-healthcheck-client Jun 14, 2025 14:26 UTC 364d etcd-ca no
etcd-peer Jun 14, 2025 14:26 UTC 364d etcd-ca no
etcd-server Jun 14, 2025 14:26 UTC 364d etcd-ca no
front-proxy-client Jun 14, 2025 14:26 UTC 364d front-proxy-ca no
scheduler.conf Jun 14, 2025 14:26 UTC 364d ca no
CERTIFICATE AUTHORITY EXPIRES RESIDUAL TIME EXTERNALLY MANAGED
ca Mar 18, 2033 05:46 UTC 8y no
etcd-ca Mar 18, 2033 05:46 UTC 8y no
front-proxy-ca Mar 18, 2033 05:46 UTC 8y no
しかし、kubectlで使用する証明書の期限を確認してみると、期限切れのままです(場合によってはyqコマンドのインストールが必要)。
$ yq -r '.users[0].user."client-certificate-data"' <.kube/config | base64 -d | openssl x509 -text
Certificate:
Data:
Version: 3 (0x2)
...
Validity
Not Before: Mar 21 05:46:30 2023 GMT
Not After : Mar 20 06:08:52 2024 GMT
どうやらこちらは手動で更新する必要があるようです。
sudo cp /etc/kubernetes/admin.conf ~/.kube/config
もう一度確認してみると正しく更新されていることがわかります。
$ yq -r '.users[0].user."client-certificate-data"' <.kube/config | base64 -d | openssl x509 -text
Certificate:
Data:
Version: 3 (0x2)
...
Validity
Not Before: Mar 21 05:46:30 2023 GMT
Not After : Jun 14 14:26:14 2025 GMT
これらを全てのcontrol planeで実行します。 場合によっては再起動が必要そうです。
また、手元からKubernetesクラスターにkubectlなどのコマンドを実行するためには、手元の証明書の更新も必要です。
次にControl Planeで以下を実行します。
$ kubectl config view --raw
出力内容を手元のMac上のこのファイルに書きます。
$ sudo vi $HOME/.kube/config
終わりに
なんで自動更新してくれないんだろうと思ったんですが、Kubernetesをupdateしたら自動で証明書も更新されるみたいです。
Kubernetesのupdateは頻繁なので、きっちりupdateしていれば問題ないよう…
今後はきちんとupdateしていきます。
Discussion