平台和 DevOps
x509: certificate signed by unknown authority(kubectl)怎么修
Unable to connect to the server: x509: certificate signed by unknown authorityUnable to connect to the server: x509: certificate signed by unknown authority 的意思是:kubectl 用 kubeconfig 里保存的 CA 验证不了 Kubernetes API Server 的证书。 大多数情况是 kubeconfig 过期(集群重装或 CA 轮换过)、指向了错误的集群,或者连接经过了出示别的证书的代理或负载均衡。
较新的 kubectl 会显示 tls: failed to verify certificate: x509: certificate signed by unknown authority,是同一个错误。
快速修复
kubeconfig 里的 CA 和 API Server 证书的签发者对不上时,修法是重新获取 kubeconfig。先对比两者:
# 当前 context 的 kubeconfig 里的 CA
kubectl config view --minify --raw -o jsonpath='{.clusters[0].cluster.certificate-authority-data}' \
| base64 -d | openssl x509 -noout -subject -fingerprint -sha256
# 服务器地址,以及它出示的证书链
kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}'; echo
openssl s_client -connect 203.0.113.10:6443 -showcerts </dev/null | grep -E 's:|i:'
如果服务器证书的签发者不是 kubeconfig 里的那张 CA,就重新获取 kubeconfig:
- kubeadm 集群: 从控制平面节点把
/etc/kubernetes/admin.conf复制到~/.kube/config。 - 托管集群: 到云厂商控制台或命令行工具里重新下载 kubeconfig。阿里云 ACK、腾讯云 TKE 都在集群详情的“连接信息”里提供 kubeconfig,注意区分公网和内网访问的两份配置。
- 手上只有 CA 文件: 把它嵌入 cluster 条目:
kubectl config set-cluster my-cluster --certificate-authority=ca.crt --embed-certs=true
原因
多数情况是集群重建或 CA 轮换后,kubeconfig 里还是旧的 CA。
1. 集群重建或 CA 轮换后 kubeconfig 没更新
- 确认: kubeconfig 里 CA 的指纹和服务器证书签发 CA 的指纹不一样,集群最近重装过。
- 修复: 按上面替换 kubeconfig。别忘了 CI 构建机、同事电脑上的 kubeconfig 也一起过期了。
2. context 选错,或合并的 kubeconfig 串了
一个文件里有多个集群,或者 KUBECONFIG 列了多个文件时,某个 cluster 条目可能带着另一个集群的 CA。
- 确认:
kubectl config current-context和kubectl config view --minify显示实际用的是哪个条目。 - 修复: 用
kubectl config use-context切换,或修正 cluster 条目。
3. 走了代理
kubectl 会读取 HTTPS_PROXY。解密 HTTPS 的公司代理会把 API Server 的证书换成自己的。
- 确认:
env | grep -i proxy;在同一个 shell 里执行openssl s_client,签发者是代理设备。 - 修复: 把 API Server 地址加进
NO_PROXY,让 kubectl 直连。
4. 负载均衡终结了 TLS
API Server 前面的负载均衡如果出示自己的证书,kubectl 看到的就不是集群 CA 签发的证书。
- 修复: 6443 端口改用四层(TCP)透传,让 API Server 自己的证书直达客户端;或者在 kubeconfig 里改用负载均衡的 CA(但此时经过终结 TLS 的负载均衡,客户端证书认证就无法使用)。自建集群用阿里云 SLB、腾讯云 CLB 做高可用时,应选 TCP 监听而不是 HTTPS 监听。
各环境修法
目标是让 kubeconfig 里的 CA 和 API Server 证书的签发者一致,各发行版的区别只在 CA 文件从哪里取。
kubeadm: 集群 CA 是 /etc/kubernetes/pki/ca.crt,admin.conf 里嵌入了它以及一张管理员客户端证书。
托管 Kubernetes: 用云厂商提供的工具重新生成凭证,不要手工改 CA 数据。
集群内的 Pod 和 Webhook: API Server 调用准入 Webhook 时报类似错误,说明 Webhook 的 caBundle 和它的服务证书对不上。由 cert-manager 管理时检查对应的 Certificate 资源,见 cert-manager 证书未就绪。
其他 Go 工具: Helm、k9s、Lens 以及 Terraform 的 Kubernetes provider 读的是同一份 kubeconfig,修一次全部生效。通用的 Go 报错见 x509: certificate signed by unknown authority。
不要这样做
下面的做法都会让 kubectl 把集群管理员凭据交给未经验证的服务器。
kubectl --insecure-skip-tls-verify,或在 kubeconfig 里写insecure-skip-tls-verify: true。 你的客户端证书或 Token 会交给任何应答的一方,而这些凭证通常就是集群管理员权限。- 删掉
certificate-authority-data,指望退回系统证书库。 集群 CA 是私有的,这样照样失败,还容易让人为内部地址去信任公网 CA。 - 为了省事在微信群、邮件里传同一份管理员 kubeconfig。 应该为每个人生成各自的凭证。
常见问题
kubectl 会用系统的 CA 证书库吗?
通常不会。kubeconfig 的 cluster 条目里有 certificate-authority-data 或 certificate-authority 时(这是常态),kubectl 只信任那一张 CA。把集群 CA 加进操作系统证书库没有用,要修的是 kubeconfig。
用 kubeadm 重建集群后 kubectl 就报错,为什么?
kubeadm reset 再 kubeadm init 会生成新的集群 CA,而你的 ~/.kube/config 里还是旧的。从控制平面节点复制新的 /etc/kubernetes/admin.conf 即可。
报错是 certificate is valid for 10.96.0.1, not 203.0.113.10,是同一个问题吗?
不是。那是名字不匹配:你访问用的地址不在 API Server 证书的 SAN 里。改用证书里列出的地址,或者把这个地址加进 API Server 证书的 SAN(kubeadm 的 apiServer.certSANs)并重新生成证书。用公网 IP 远程管理自建集群时最常遇到。
开发集群用 insecure-skip-tls-verify 可以吗?
不建议,开发集群也有风险:kubeconfig 会发送客户端证书或 Token,不校验服务器的话,路径上的任何人都能截获它并以集群管理员身份操作。取回正确的 CA 只要一分钟。