上周帮客户上线一套K8s集群,三台节点跑得好好的,突然kubectl连不上了,报错:x509: certificate signed by unknown authority。翻日志发现是apiserver证书里没包含新加的负载均衡VIP,kubelet也因为证书CN不匹配拒绝注册——这种问题在真实运维现场太常见了。
证书到底要配哪几处?
Kubernetes不是只靠一个ca.crt就完事的。核心组件间通信依赖三类证书:
- CA根证书(ca.crt/ca.key)——所有其他证书的签发者
- apiserver服务端证书(apiserver.crt/apiserver.key)——必须包含所有可访问地址:127.0.0.1、节点内网IP、VIP、域名
- kubelet客户端证书(kubelet.crt/kubelet.key)——CN字段得是节点名,且需被apiserver的client-ca-file信任
生成apiserver证书的关键一步
很多人用cfssl或openssl生成时漏掉SAN(Subject Alternative Name)。比如你用VIP 192.168.10.100做入口,但证书里只写了localhost和127.0.0.1,kubectl从外网连肯定失败。
用cfssl生成时,config.json里必须明确列出所有IP和域名:
{
"hosts": [
"127.0.0.1",
"192.168.10.10",
"192.168.10.11",
"192.168.10.12",
"192.168.10.100",
"k8s.example.com",
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster.local"
],
"CN": "kubernetes",
"key": {"algo": "rsa", "size": 2048}
}
kubelet证书不能只靠kubeadm自动生成
如果你用kubeadm init初始化集群,它会自动为每个节点生成kubelet证书,但默认CN是system:node:node1,而RBAC规则要求CN匹配system:node:<hostname>。结果就是节点状态卡在NotReady,日志里反复出现Unable to authenticate the request due to an error: x509: certificate is valid for system:node:node1, not system:node:node01。
解决方法:手动签发时确保CN与实际hostname一致,或者修改kubeadm配置中的nodeRegistration.name字段。
检查证书是否生效的土办法
别光看文件存不存在,直接用openssl验:
# 查看apiserver证书支持哪些IP和域名
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -text -noout | grep -A1 "Subject Alternative Names"
# 测试kube-apiserver是否接受该证书连接
curl --cert /etc/kubernetes/pki/apiserver.crt --key /etc/kubernetes/pki/apiserver.key \
--cacert /etc/kubernetes/pki/ca.crt https://192.168.10.100:6443/version
证书过期了怎么办?
kubeadm生成的证书默认一年有效期。到期前30天,kubectl get nodes可能开始报错,但集群还能跑;等真正过期,kubelet就无法上报心跳,节点变NotReady。
快速续期命令(适用于kubeadm集群):
kubeadm certs renew all
systemctl restart kubelet
注意:如果用了外部etcd,还得单独更新etcd证书;若apiserver证书是自己签的,记得同步替换/etc/kubernetes/manifests/kube-apiserver.yaml里挂载的证书路径。