K3s 集群证书过期紧急轮换笔记
前言/背景
最近 Prometheus 突然弹出一个 warning 告警,把我吓了一跳。仔细一看是 KubeClientCertificateExpiration,提示 K3s 内置证书还有 7 天就要过期了!
告警主机是 10.196.69.1:6443 (k3s-01)。
emmm,看了一下集群的运行时间,确实快一年了(AGE 359d)。
[guolj@k3s-01 ~]$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k3s-01 Ready control-plane,master 359d v1.30.13+k3s1
k3s-02 Ready <none> 359d v1.30.13+k3s1
k3s-11 Ready <none> 359d v1.30.13+k3s1
排查过程
赶紧切到 root 用户下,用 K3s 自带的命令查一下证书状态:
k3s certificate check
输出结果满屏的警告,显示大量 client-admin.crt、serving-kube-apiserver.crt 等核心证书均将在 6 天后 (2026-06-18) 到期。哭死,还好有监控,不然下周集群直接原地升天。
分阶段操作步骤
1. Master 节点轮换操作 (k3s-01)
因为我这是单 Master 节点,直接停服务搞起:
# 1. 切换至 root 用户
su -
# 2. 停止 K3s 主服务
systemctl stop k3s
# 3. 执行证书轮换
k3s certificate rotate
# 4. 重新启动 K3s 服务
systemctl start k3s
2. Worker 节点同步 (k3s-02, k3s-11) 【必做】
💡 避坑提示:
很多人以为 K3s 有聪明的双向证书通道机制,Agent 就不需要重启了。确实,Agent 检测到服务端的 CA 没变,会自动下载同步新的服务端证书。
刚才在轮换完 Master 证书后,我用kubectl get nodes -w观察了一下,Worker 节点确实会在短暂的NotReady闪断后,自动恢复成Ready状态。
但是!在实际生产运维中,强烈建议显式地重启一次 Agent。
一是为了彻底刷新底层组件(如 containerd 或 kube-proxy)的证书缓存,二是为了让 Prometheus 监控指标连接立刻刷新,促使告警迅速恢复。
依次登录 k3s-02 和 k3s-11 执行:
sudo systemctl restart k3s-agent
总结/验证
1. 验证证书有效性
在 Master 节点上通过 openssl 和 K3s 内置命令进行双重验证,看看是不是真的续命成功了。
注意:这里的物理证书文件都在 /var/lib/rancher/k3s/server/tls/ 目录下,普通用户看不了(会报 Permission denied),必须在 root 下执行:
# 验证物理证书文件
for i in `ls /var/lib/rancher/k3s/server/tls/*.crt`; do echo $i; openssl x509 -enddate -noout -in $i; done
# 验证 K3s 内部状态
k3s certificate check
执行结果:
[root@k3s-01 guolj]# k3s certificate check
INFO[0000] Server detected, checking agent and server certificates
INFO[0000] client-scheduler.crt: certificate system:kube-scheduler (ClientAuth) is ok, expires at 2027-06-12T07:23:34Z
...
INFO[0000] serving-kube-apiserver.crt: certificate kube-apiserver (ServerAuth) is ok, expires at 2027-06-12T07:23:34Z
INFO[0000] serving-kube-apiserver.crt: certificate k3s-server-ca@1750225341 (CertSign) is ok, expires at 2035-06-16T05:42:21Z
漂亮!所有的 WARN 警告都变成了漂亮的 INFO [...] is ok,过期时间成功顺延一年至 2027 年 6 月。
2. 权限修复 (关键避坑)
这里有个大坑!轮换完证书后,我退回 guolj 用户习惯性地敲了个 kubectl get nodes,结果直接报错连不上!
查了一下 ~/.kube/config 发现文件不存在,才想起来我平时是在 .bashrc 里面通过环境变量引入的 KUBECONFIG:
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
看了一下文件权限:
[guolj@k3s-01 ~]$ ls -l /etc/rancher/k3s/k3s.yaml
-rw------- 1 root root 2969 Jun 12 15:23 /etc/rancher/k3s/k3s.yaml
原来 K3s 轮换证书后会重写这个文件,权限会被无情地还原为 600(仅 root 可读)! 导致普通用户直接抓瞎。
赶紧在 root 下用 ACL 重新刷一下权限(推荐这种方式,不破坏原本的安全限制):
setfacl -m u:guolj:r /etc/rancher/k3s/k3s.yaml
3. 最终验证
退回到 guolj 用户,再次执行:
kubectl get nodes
节点全绿,响应正常,告警闭环,完美搞定!下班!