记一次K8s证书过期导致控制平面组件反复 Unauthorized 的排查与修复
故障现象
- 通过
kubectl create deployment创建应用后,Pod 一直未被创建,Deployment 一直处于 NotReady 状态。 - 查看 kube-system 命名空间下的 kube-controller-manager Pod,发现日志反复报错:
1 | E0513 02:21:45.091033 leaderelection.go:332] error retrieving resource lock kube-system/kube-controller-manager: Unauthorized |
- 稍后发现 kube-scheduler 也出现了类似问题,集群整体不可用。
环境信息
- Kubernetes 版本:1.28(但远端提示较新,不影响)
- 部署方式:kubeadm
- 集群节点:单 master 节点
- 证书过期时间:系统显示 controller-manager 证书已过期(2026-04-21),而当前时间为 2026-05-13
错误的排查方向(易错点)
起初通过 kubectl config view 检查 /etc/kubernetes/controller-manager.conf 内嵌的客户端证书时,证书有效期竟然显示为 2027 年。
这误导我们认为证书没有过期,于是排查了:
- CA 指纹比对(一致)
- API Server 的
--client-ca-file参数(正确指向/etc/kubernetes/pki/ca.crt) - RBAC ClusterRole
system:kube-controller-manager的权限(发现缺少 configmaps/endpoints 的写权限,修复后仍报错) - 网络连通性(curl api-server 正常)
- API Server 日志级别(开启
--v=4后捕获到真实报错)
以上调试几乎走遍了认证、授权、网络三个方向,但问题并未根治。
真正原因
最终通过提升 apiserver 日志级别(--v=4),在 authentication.go:70 中捕获到关键日志:
1 |
|
这说明:controller-manager 实际使用的客户端证书并未更新,仍然是过期的那一份。
为什么证书看起来很新,但实际使用时却已过期?
kubeadm certs renew all确实更新了/etc/kubernetes/pki/下的证书文件和/etc/kubernetes/*.conf中内嵌的证书数据。- 但 kube-controller-manager 是一个静态 Pod,kubelet 仅当 Pod 重新创建时才会重新读取 manifest 和相关的证书/配置文件。
- 如果证书续期后没有强制重启 controller-manager 的 Pod(或者重启 kubelet 时,kubelet 仍然使用了旧的镜像或证书缓存),Pod 内存态仍会使用旧证书。
- 特别是一些集群在 controller-manager 的 manifest 中使用了独立的证书文件(如
--client-certificate=/etc/kubernetes/pki/controller-manager.crt),而不是仅通过 kubeconfig 内嵌证书。这种情况下,即使 kubeconfig 文件已更新,只要 .crt/.key 文件仍是旧的,组件就会一直使用过期证书。
虽然 /etc/kubernetes/controller-manager.conf 中的证书已经更新,但 Pod 启动时可能从某个地方加载了旧的证书路径,导致实际发起请求时携带的是过期证书。
最终解决方案
解决问题的核心:强制让 kube-controller-manager 和 kube-scheduler 的静态 Pod 以全新的状态重建,从而加载已更新的证书。
具体操作步骤
临时移走静态 Pod 的 manifest 文件
这样 kubelet 检测到 manifest 丢失,会自动停止并删除对应的 Pod。1
mv /etc/kubernetes/manifests/kube-controller-manager.yaml /root/
确认 Pod 已彻底消失
1
2kubectl get pod -n kube-system -l component=kube-controller-manager
# 应无结果输出将 manifest 文件移回原位
1
mv /root/kube-controller-manager.yaml /etc/kubernetes/manifests/
此时 kubelet 发现新 manifest 会立刻创建全新的 Pod,Pod 启动时会读取已更新的 kubeconfig 或证书文件,从而使用新证书。
对 kube-scheduler 执行相同的操作(因为 scheduler 同样基于静态 Pod,且也出现了相同问题)
1
2
3
4mv /etc/kubernetes/manifests/kube-scheduler.yaml /root/
# 确认 pod 删除
kubectl get pod -n kube-system -l component=kube-scheduler
mv /root/kube-scheduler.yaml /etc/kubernetes/manifests/验证修复
- 查看 controller-manager 日志不再出现 Unauthorized:应显示 successfully acquired lease。
1
kubectl logs -n kube-system -l component=kube-controller-manager --tail=10
- 创建一个测试 Deployment 并观察 Pod 状态:Pod 应能顺利 Running。
1
2kubectl create deployment test-ok --image=nginx --replicas=1
kubectl get pods -w
- 查看 controller-manager 日志不再出现 Unauthorized:
经验总结
- 证书过期后,更新文件 ≠ 立刻生效
静态 Pod 需要重建才能加载新证书,直接 systemctl restart kubelet 不一定能保证清理所有旧状态(例如旧容器未被彻底销毁)。移走 manifest → 确认删除 → 移回 是一个更可靠的方式。 - 善用 API Server 的高级日志
当组件报 Unauthorized 且基本排查无果时,务必开启 –v=4 或更高日志级别,直接查看 apiserver 的认证/授权拒绝详情,能瞬间缩小问题范围。 - 注意控制器组件的证书加载方式
如果 manifest 中同时使用了 –kubeconfig 和 –client-certificate / –client-key,需要确保所有引用的证书文件都被更新,否则仍会使用旧证书。 - 不要忽略 scheduler 等其它静态 Pod
当 controller-manager 出现证书问题时,通常 scheduler 也面临相同问题,应一并处理,避免集群长时间不可用。
拓展:自动化预防建议
- 配置
kubeadm certs check-expiration的定时监控,提前预警证书到期。 - 编写更新脚本,在
kubeadm certs renew all后,自动执行静态 Pod 的重建流程(移走 manifest + 移回)。 - 对于生产集群,建议使用 kubeadm 的证书自动轮换功能,或提前规划证书续期窗口。
免责声明:本文所述操作均在测试环境中验证,生产环境操作前请充分评估影响并做好备份。