エラーメッセージ
Unable to connect to the server: tls: failed to verify certificate: x509: certificate has expired or is not yet valid
Go は両方の時刻を付け加えます。「…: current time <client time> is after <notAfter>」(まだ有効になっていない証明書では「is before <notBefore>」)という形式で、どちら側が間違っているかがわかります。
kubectl (client-go) — the API server certificate (often after a year without kubeadm upgrades) is outside its validity period
このエラーの意味
API サーバーが提示した証明書は、kubectl のローカル時刻では有効期間外です。kubeadm のクラスターでは、コントロールプレーンの証明書は有効期間 1 年で発行され、自動的に更新されるのは kubeadm のアップグレード時だけです。そのため、1 年間手を加えていないクラスターは、まさにこのように失敗します。クライアントの時計が間違っている場合も、同じエラーになります。
発生する理由
kubeadm のコントロールプレーン証明書が 1 年で期限切れになった
よくあるapiserver、front-proxy、etcd の証明書(および admin.conf 内のクライアント証明書)の有効期間は、デフォルトで 1 年です。これらは kubeadm upgrade の実行時か、kubeadm certs renew で更新されます。
kubeconfig のクライアント証明書が期限切れになった
ときどきサーバー証明書を更新した後でも、期限切れのクライアント証明書を含む古い admin.conf を使っていると、認証に失敗します(メッセージは別のもので、「You must be logged in to the server (Unauthorized)」になります)。
時刻のずれ
ときどき完全なメッセージに「is before」が含まれている場合は、クライアントの時計が証明書の notBefore より遅れていることを示しています。
修正方法
- 1.
証明書の有効期限を一覧表示する
kubeadm certs check-expiration は、コントロールプレーンのすべての証明書を、有効期限までの残り期間とともに表示します。
bash # On a control-plane node sudo kubeadm certs check-expiration - 2.
証明書を更新してコントロールプレーンを再起動する
kubeadm certs renew all は新しい証明書を書き出します。それを読み込ませるには静的 Pod を再起動する必要があり、クライアント証明書を埋め込んだ kubeconfig も更新しなければなりません。
bash sudo kubeadm certs renew all # restart the control-plane static pods so they load the new certificates, # then refresh your kubeconfig (the embedded client certificate was renewed too): sudo cp /etc/kubernetes/admin.conf "$HOME/.kube/config" - 3.
クライアントの時刻を確認する
完全なメッセージに「is before」とある場合は、時計を同期してください。
bash date -u; timedatectl status | grep -i synchronized