Сообщение об ошибке
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 кластера), но адреса из URL сервера в kubeconfig нет среди имён и IP-адресов в альтернативных именах субъекта (SAN) этого сертификата. Go перечисляет найденные записи IP SAN и адрес, который искал. kubeadm выпускает сертификат API-сервера для IP-адреса сервиса, адресов узлов и нескольких DNS-имён; для любого другого способа обращения к нему нужна дополнительная запись SAN.
Почему это происходит
Доступ через балансировщик нагрузки или внешний IP-адрес
частоПеред управляющим слоем стоит балансировщик нагрузки, плавающий IP-адрес или NAT-адрес, а при kubeadm init его не передали как дополнительную запись SAN.
SSH-туннели и проброс портов
частоЕсли обращаться к API-серверу через туннель по адресу https://127.0.0.1:6443, клиент ожидает в сертификате 127.0.0.1, а этого адреса в сертификате нет.
Изменился IP-адрес узла
иногдаУ одноузловых кластеров, получающих адрес по DHCP, и у виртуальных машин, перенесённых в другую сеть, остаётся сертификат для старого адреса.
Как исправить
- 1.
Выведите записи SAN сертификата
Сравните их с URL сервера в kubeconfig.
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.
Перевыпустите сертификат API-сервера с дополнительными SAN
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
Параметр tls-server-name заставляет kubectl при подключении к адресу туннеля проверять имя, которое в сертификате действительно есть, вместо того чтобы отключать проверку через 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