kubeadm手动签发自定义证书导致集群不可用故障排查
运行环境
- Kubernetes版本:v1.21.7
- 部署环境:本地自建(On prem)
- 操作系统:CentOS Linux 7 (Core)
- 部署方式:标准kubeadm集群
- 容器运行时:Docker
故障根因确认
核心故障点为手动签发的kube-apiserver服务端证书SAN(主体备用名称)列表缺失127.0.0.1、::1回环地址条目,直接触发连锁故障:
- kube-apiserver进程启动时TLS监听配置校验不通过,无法正常绑定6443端口对外提供服务,因此docker中只能看到apiserver的pause沙箱,无业务进程运行
- kube-controller-manager、kube-scheduler默认访问节点IP的6443端口、kubelet默认访问127.0.0.1:6443端口与apiserver通信,因6443端口无监听直接报连接被拒绝;kubelet无法向apiserver上报节点状态,就会抛出
node "<HOSTNAME>" not found错误 - 观察到的etcd日志报连接IP不匹配TLS校验错误,是因为apiserver使用的etcd客户端证书同样存在SAN配置缺失问题,apiserver连不上etcd也会进一步阻塞自身启动流程
- kubectl默认通过本地kubeconfig配置的apiserver地址访问6443,端口无监听直接返回连接拒绝报错
3500天有效期集群证书手动签发方案
前置准备
先全量备份原有集群配置,避免操作失误无法回滚:
cp -r /etc/kubernetes /etc/kubernetes.bak.$(date +%Y%m%d)
证书配置规范
所有服务端类证书必须在OpenSSL配置的v3扩展段中完整配置SAN列表,覆盖所有可能的访问地址,否则会触发TLS校验失败:
- kube-apiserver服务端证书必须包含的SAN条目:
- 回环地址:
127.0.0.1、::1 - 节点物理IP、集群kubernetes服务的ClusterIP(默认10.96.0.1,按实际集群Service网段调整)
- DNS域名:
kubernetes、kubernetes.default、kubernetes.default.svc、kubernetes.default.svc.cluster.local、当前节点主机名
- 回环地址:
- etcd服务端、peer对等证书必须包含的SAN条目:
- 回环地址:
127.0.0.1、::1 - 节点物理IP、节点主机名、
localhost
- 回环地址:
- 所有客户端证书(front-proxy-client、apiserver-kubelet-client、apiserver-etcd-client、admin、scheduler、controller-manager、kubelet对应的客户端证书)无需配置SAN,只需保证CN、O字段、extendedKeyUsage属性与默认证书一致即可,之前使用的front-proxy-client证书配置本身没有问题。
以kube-apiserver证书为例,正确的OpenSSL配置参考如下:
[ req ] default_bits = 2048 prompt = no default_md = sha256 distinguished_name = dn req_extensions = v3_ext [ dn ] CN = kube-apiserver [ v3_ext ] basicConstraints = critical,CA:FALSE keyUsage = critical,digitalSignature,keyEncipherment extendedKeyUsage = serverAuth subjectAltName = @alt_names authorityKeyIdentifier = keyid,issuer [ alt_names ] DNS.1 = kubernetes DNS.2 = kubernetes.default DNS.3 = kubernetes.default.svc DNS.4 = kubernetes.default.svc.cluster.local DNS.5 = <替换为当前节点实际主机名> IP.1 = 127.0.0.1 IP.2 = ::1 IP.3 = <替换为当前节点物理IP> IP.4 = <替换为kubernetes服务的ClusterIP,默认10.96.0.1>
签发注意事项
- 证书有效期直接在openssl x509命令中通过
-days 3500参数指定即可 - 必须使用对应归属的CA签发对应证书,禁止串用CA:
- apiserver、apiserver-kubelet-client证书使用
/etc/kubernetes/pki/ca.crt、/etc/kubernetes/pki/ca.key签发 - front-proxy-client证书使用
/etc/kubernetes/pki/front-proxy-ca.crt、/etc/kubernetes/pki/front-proxy-ca.key签发 - etcd相关所有证书(server、peer、healthcheck-client、apiserver-etcd-client)使用
/etc/kubernetes/pki/etcd/ca.crt、/etc/kubernetes/pki/etcd/ca.key签发
- apiserver、apiserver-kubelet-client证书使用
- 签发完成后注意检查所有证书、私钥文件权限为600,属主属组为root,避免kubelet读取文件失败
替换&生效操作
- 将签发完成的证书、私钥替换到
/etc/kubernetes/pki、/etc/kubernetes/pki/etcd的对应路径 - 同步更新
/etc/kubernetes路径下admin.conf、scheduler.conf、controller-manager.conf、kubelet.conf中嵌入的客户端证书、私钥内容,不要遗漏kubelet.conf,否则kubelet会因证书不匹配无法正常向apiserver注册 - 替换完成后直接执行
systemctl restart kubelet重启kubelet即可,kubelet会自动重建所有静态Pod,无需手动移动manifests目录 - 等待2-3分钟组件启动完成后,执行
kubectl get nodes、kubectl get cs验证集群状态,确认所有节点为Ready状态、控制面组件健康即操作完成
内容的提问来源于stack exchange,提问作者tuatara
相关产品推荐
相关产品推荐

