エラーメッセージ
Unable to connect to the server: tls: failed to verify certificate: x509: certificate is valid for 10.96.0.1, 192.168.1.10, not 127.0.0.1
アドレスの一覧は、証明書と kubeconfig から取得されたものです。DNS 名の場合、メッセージは「x509: certificate is valid for kubernetes, kubernetes.default, …, not k8s.example.com」となります。
kubectl (client-go) — the API server address in the kubeconfig is not among the API server certificate's SANs
このエラーの意味
API サーバーの証明書は信頼されています(クラスターの CA までチェーンがつながっています)が、kubeconfig のサーバー URL にあるアドレスは、証明書のサブジェクト代替名に含まれる名前や IP のいずれでもありません。Go は、見つかった IP SAN と、求めていたアドレスを列挙します。kubeadm は API サーバーの証明書を、サービス IP、ノードのアドレス、いくつかの DNS 名に対して発行します。それ以外の方法でアクセスする場合は、追加の SAN が必要です。
発生する理由
ロードバランサーやパブリック IP 経由でのアクセス
よくあるコントロールプレーンの前段にあるロードバランサー、フローティング IP、NAT アドレスのうち、kubeadm init の実行時に追加の SAN として渡されていないものが該当します。
SSH トンネルとポートフォワード
よくあるトンネル経由で https://127.0.0.1:6443 として API サーバーにアクセスすると、照合の対象は 127.0.0.1 になりますが、証明書にはこのアドレスが含まれていません。
ノードの IP アドレスが変わった
ときどきDHCP を使うシングルノードのクラスターや、別のネットワークに移動した VM では、古いアドレス向けの証明書がそのまま残ります。
修正方法
- 1.
証明書の SAN を一覧表示する
kubeconfig のサーバー URL と比較してください。
bash # On a control-plane node: the names and addresses the API server certificate covers sudo openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -ext subjectAltName - 2.
追加の SAN を含めて API サーバーの証明書を再生成する
kubeadm init phase certs apiserver に --apiserver-cert-extra-sans を指定すると、新しい証明書が発行されます。事前に古い証明書と鍵のペアを別の場所へ移動しておく必要があり、新しい証明書を読み込ませるには kube-apiserver を再起動しなければなりません。
bash # kubeadm: add the missing address/name to the API server certificate sudo mv /etc/kubernetes/pki/apiserver.{crt,key} /root/ sudo kubeadm init phase certs apiserver --apiserver-cert-extra-sans=203.0.113.20,k8s.example.com # then restart the kube-apiserver static pod (e.g. move its manifest out of /etc/kubernetes/manifests and back) - 3.
トンネル:tls-server-name を設定する
kubectl の tls-server-name を使うと、insecure-skip-tls-verify に頼らずに、トンネルのアドレスに接続しながら、証明書が実際にカバーしている名前で検証させることができます。
bash # Through a tunnel or port-forward: keep verifying the name the certificate has kubectl config set-cluster my-cluster --server=https://127.0.0.1:6443 --tls-server-name=kubernetes