本流程默认先做“新旧 CA 并存”的过渡,再移除旧 CA。不要在未验证的情况下直接覆盖唯一的 CA 文件;CA 私钥损坏且没有备份,往往意味着集群重建。
sudo kubeadm certs check-expiration
sudo find /etc/kubernetes/pki /var/lib/kubelet/pki -type f \
\( -name '*.crt' -o -name '*.pem' \) -print
sudo openssl x509 -in <certificate> -noout \
-subject -issuer -dates -fingerprint -sha256 -text
同时检查 kubeconfig、Webhook 的 caBundle、Ingress Secret、服务网格、客户端信任库和可能固定证书指纹的系统。只盘点服务端证书,漏掉客户端和信任库,是轮换后大面积失败的主要原因。
判断轮换类型。CA 仍可信、只是叶子证书到期时,优先用原 CA 重签;根 CA 到期、私钥泄露或算法不合规时,必须做完整 CA 轮换。完整轮换要假设旧链不再可信,准备新旧并存的信任包,并确认所有使用方都能接受多根证书。
核对证书属性。新证书的 SAN、EKU、KeyUsage、链长度、有效期和密钥用途必须覆盖原场景;服务端证书要有正确的 DNS/IP SAN,客户端证书要有 clientAuth,etcd peer 证书要能被成员间互相验证。不要只复制 subject,忽略扩展字段。
备份 CA 和配置。备份 /etc/kubernetes/pki、*.conf、/var/lib/kubelet/pki、Webhook caBundle、Ingress Secret 和内部 CA 的离线密钥;目录权限收紧到最小范围,备份完成后做一次恢复演练。CA 私钥不要分发到普通节点,也不要在临时目录留下副本。
准备灰度与回滚。选择测试集群、一个非关键节点、一个命名空间或一个 Ingress 作为首批;明确批次大小、观察时间、回滚负责人和停机窗口。轮换期间暂停证书自动续期和自动签发,避免自动化与手工操作竞争。
检查时间和监控。用 timedatectl 确认时间同步;证书的 notBefore/notAfter 对时钟敏感。准备好 TLS 握手错误、证书剩余天数、API /readyz、节点 Ready、etcd 健康和业务错误率看板。证书已经过期时,先按应急流程恢复,不要在故障中直接做 CA 轮换。
kubectl get nodes -o wide > /backup/nodes-before.txt
kubectl get --raw='/readyz?verbose' > /backup/readyz-before.txt
sudo kubeadm certs check-expiration > /backup/certs-before.txt
记录当前 CA 指纹、叶子证书指纹、各组件信任的 CA 和所有待替换的 Secret。后续每一步都用同一组指标对比。
只轮换叶子证书时,生成新私钥和 CSR,交给现有 CA 按原模板签发。CSR 必须保留 SAN 和扩展字段:
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out leaf-new.key
openssl req -new -key leaf-new.key -out leaf-new.csr \
-subj "/CN=api.internal" \
-addext "subjectAltName=DNS:api.internal,DNS:api.internal.svc"
openssl req -in leaf-new.csr -noout -text
完整 CA 轮换时,新建根 CA 或“新根 + 新中间 CA”,把旧根和新根一起放进信任包。签发和分发都要保留旧链,直到所有叶子证书都换完:
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out ca-new.key
openssl req -x509 -new -key ca-new.key -sha256 -days 3650 \
-subj "/CN=Internal Root CA" -out ca-new.crt \
-addext "basicConstraints=critical,CA:TRUE" \
-addext "keyUsage=critical,keyCertSign,cRLSign"
cat ca-old.crt ca-new.crt > ca-bundle.crt
openssl verify -CAfile ca-bundle.crt leaf-old.crt
用 openssl x509 -req 签发叶子时,务必通过 -extfile 或 CA 模板带上 SAN、EKU 和 KeyUsage;默认签发可能丢掉这些扩展,导致 TLS 校验失败。有中间 CA 时,信任包放根证书,叶子下发时带上中间证书,验证命令用 -untrusted intermediate.crt 提供中间链。更稳妥的做法是让 cert-manager、Vault、step-ca 或现有内部 CA 服务按模板签发,再把证书和链导出。
完整 CA 轮换的第一步不是换叶子证书,而是让所有使用方同时信任新旧 CA。把 ca-bundle.crt 分发到控制面、节点、kubeconfig、Webhook caBundle、Ingress、服务网格和外部客户端,然后验证旧证书仍然可用:
openssl verify -CAfile ca-bundle.crt leaf-old.crt
openssl x509 -in ca-new.crt -noout -subject -dates -fingerprint -sha256
Kubernetes 中要区分“信任包”和“签发者证书”。ca.crt 可以作为多根信任包使用,但签发新证书时必须使用新 CA 的私钥和对应证书;不要把合并包直接当作签发证书。etcd、front-proxy 和 kubelet 各自有独立的信任位置,要逐个确认,不能只改 apiserver。
顺序建议是:一个测试节点或命名空间 → 一个控制面节点 → 其余控制面 → 节点池 → Ingress、Webhook 和内部服务 → 外部客户端。每批只改一个层次,观察后再继续。
控制面叶子证书用原 CA 续期时,可以执行:
sudo cp -a /etc/kubernetes/pki /etc/kubernetes/pki.bak.$(date +%Y%m%d%H%M)
sudo kubeadm certs renew all
sudo kubeadm certs check-expiration
kubeadm certs renew all 只更新磁盘文件,不会让运行中的静态 Pod 自动加载;要逐台重启 kube-apiserver、controller-manager、scheduler 和 etcd,并确认 quorum 与 /readyz 后再处理下一台。它只负责用当前 CA 重签叶子,不会生成、分发或切换 CA;完整 CA 轮换还要替换 CA、分发信任包并重签所有客户端证书。如果磁盘上仍是旧 CA,renew 仍会签出旧链。
kubelet 客户端证书启用自动轮换时,重启 kubelet 后会生成 CSR,需要及时批准:
sudo systemctl restart kubelet
kubectl get csr
kubectl certificate approve <csr-name>
如果证书已经过期,kubelet 无法用旧证书认证,也就无法提交 CSR。此时要从安全备份恢复一份未过期的 kubelet.conf,或用集群 CA 重新签发客户端证书:CN 使用 system:node:<node>,组使用 system:nodes,替换后先用 kubectl --kubeconfig 验证身份和权限,再重启 kubelet。服务端证书启用了 serverTLSBootstrap 时,对应 CSR 通常需要人工批准。
etcd 成员要逐台替换证书并重启,确认 etcdctl endpoint health --cluster、leader 和成员列表正常后再继续。Webhook 要同时更新 caBundle 和证书 Secret,确认 failurePolicy、超时和调用链;Ingress 和内部服务要处理连接复用和客户端缓存,避免旧连接继续使用旧证书。
所有叶子证书都换成新链,并且经过完整业务高峰后,才能从信任包中移除旧 CA。移除前搜索日志中的 unknown authority、certificate expired 和 TLS 握手失败,确认没有客户端仍在使用旧链。移除后再次滚动重启或重载相关组件,保留旧 CA 的离线备份和回滚材料。
kubeadm certs check-expiration 显示所有证书有效期符合预期,没有遗漏的 kubeadm 管理证书、etcd 或 front-proxy 证书。openssl verify -CAfile ca-bundle.crt <leaf> 对每个叶子证书都返回成功;openssl x509 -noout -subject -issuer -dates -text 中的 SAN 和用途正确。openssl s_client -connect <host>:<port> -servername <name> -showcerts </dev/null 返回新链,服务端证书的签发者和有效期正确。kubectl get --raw='/readyz?verbose'、kubectl get nodes、kubectl get csr 正常;etcd 全部成员健康,没有 leader 抖动。x509 错误;没有长期 Pending 的 CSR。新链不被信任。 最常见的原因是只替换了叶子证书,没有先分发合并信任包,或某个使用方仍只信任旧 CA。立即恢复旧+新合并包,确认旧 CA 仍在信任列表中;不要删除旧 CA 私钥和证书。
控制面重启后不可用。 停止后续批次,保留日志和证书文件。用备份恢复 /etc/kubernetes/pki 和 *.conf,逐台重启静态 Pod;如果 etcd 成员异常,先恢复 etcd 证书和 quorum,再处理 apiserver。不要在所有控制面节点同时替换证书。
kubelet 报 unknown authority 或 NotReady。 把合并信任包恢复到节点的 /etc/kubernetes/pki/ca.crt 和 kubelet 配置引用的位置,重启 kubelet;如果客户端证书已过期,重新签发或恢复备份。不要删除 /var/lib/kubelet/pki,否则会失去回滚材料。
Webhook 或 Ingress 中断。 恢复旧 caBundle/Secret 和旧证书,确认调用恢复后再排查新链;临时把 failurePolicy 改为 Ignore 只能作为受控应急手段,必须尽快恢复并记录审批。
证书已经过期。 回滚到过期证书不会恢复服务,只能向前修复:恢复未过期备份、用 CA 重签,或先恢复旧信任链再换新链。此时应转入证书过期应急流程,避免在服务不可用时扩大变更范围。
部分批次失败。 保持新旧 CA 并存,按相反顺序回滚已替换的叶子证书;在确认所有使用方恢复前,不要移除新 CA。记录失败的批次、指纹和日志,修复后在测试环境复现。
合上页面,先回答,再展开对照。
kubeadm certs renew all 能完成 CA 轮换吗?
小程序版
微信扫码,随时查命令