K8s证书过期不用慌:kubeadm集群一键续期脚本实操指南 简介面向Kubernetes集群运维人员与管理员这份体积仅3KB的压缩包提供单个update-kubeadm-cert.sh脚本用于自动化完成证书备份、过期检测、重新生成、配置更新与组件重启等全流程解决手动更新繁琐易错的问题。脚本适合证书即将过期或已过期的集群环境要求具备sudo权限及kubeadm/kubectl基础。资源包共1个文件类型为shell脚本可直接查看或按需修改阈值与路径。已有470人学习下载。通过阅读脚本内容可理解K8s各类证书apiserver、etcd、kubelet等的更新逻辑掌握在测试环境验证后再上生产的排错思路有效避免因证书过期导致的服务中断是日常证书巡检和批量续期的实用工具。1. 证书过期往往比磁盘满更先找上门这份脚本把续期变成一件事某个周一早上你像往常一样敲下kubectl get nodes结果回了一串Unable to connect to the server: x509: certificate has expired or is not yet valid。集群挂了一半排查半天最后发现是 k8s 证书过期了时间不等人。如果你用的还是 kubeadm 部署的集群那你一定会遇到这个时刻——证书有效期的倒计时从第一天就在走只是你通常不会去看它直到它真的炸了。这份 k8s 证书一键续期脚本解决的就是这件事把原本要逐台登录、挨个敲命令、还要记得备份的流程收拢成一次检测、一步续期、一次分发。适合跑在 kubeadm 部署的集群上也适合那些“知道该续期但每次都靠记忆力”的运维同学。2. 先搞清楚证书是谁签的、存在哪续期之前必须看的三个目录2.1 kubeadm 集群的证书体系不止是 apiserver 那张很多人一听到“续期 k8s 证书”第一反应是/etc/kubernetes/pki/apiserver.crt但 kubeadm 生成的证书远不止这一张。kubeadm init的时候它会一口气生成一套 PKI 体系包括/etc/kubernetes/pki/下的 CA 证书和各组件证书ca.crt、apiserver.crt、apiserver-kubelet-client.crt、front-proxy-ca.crt、front-proxy-client.crt、etcd/ca.crt等/etc/kubernetes/下的 kubeconfig 文件admin.conf、kubelet.conf、controller-manager.conf、scheduler.conf它们里面内嵌了客户端证书的 base64 内容另外还有etcd/healthcheck-client.crt这类健康检查专用的客户端证书容易被忽略但它过期了一样会引发 etcd 健康检查失败。这些证书的有效期默认是一年。也就是说一个 kubeadm 集群从初始化那天起365 天之后就会进入证书倒计时。如果是二进制方式部署的集群证书有效期往往更长但那不是这份脚本的适用对象。脚本面向的是 kubeadm 管理的主节点尤其是那些已经吃过一次过期亏、不想再手动量天数的集群。2.2 脚本怎么判断“快到期了”openssl 解析加天数计算脚本的第一件事不是闷头续期而是先体检。它会遍历/etc/kubernetes/pki下所有.crt文件逐个解析证书的notAfter字段算好剩余天数再和你设定的阈值比较。这里有一个关键点证书的剩余时间计算不能靠“肉眼猜”要用openssl x509的-enddate参数拿到标准的时间字符串再转成时间戳做差值。下面我拆一段核心检测逻辑常见做法是写成这样的函数# 检测单个证书的剩余天数输入为证书路径 check_cert_expiry() { local cert_path$1 local end_date end_date$(openssl x509 -in $cert_path -noout -enddate 2/dev/null | cut -d -f2) if [ -z $end_date ]; then echo $cert_path 无法解析 return 1 fi local end_epoch remain_days end_epoch$(date -d $end_date %s) remain_days$(( (end_epoch - $(date %s)) / 86400 )) echo $remain_days }date -d $end_date %s是把证书到期时间转成 Unix 时间戳再用当前时间戳做差除以 86400 得到剩余天数。注意date -d在大多数 Linux 发行版上是 GNU date在 macOS 上要写成date -j -f脚本作者一般直接声明“仅支持 Linux”这一点在使用时心里有数即可。2.3 阈值设多少合适30 天还是 7 天脚本里通常会有一个EXPIRY_THRESHOLD变量默认值设在 30 天比较稳妥。理由是如果你发现所有证书还剩 3 天说明你已经错过了最佳操作窗口此时续期动作本身很简单但组件的滚动重启、kubelet.conf 分发到所有节点这些步骤很容易出岔子留 30 天量你还能从容验证。我一般会把阈值做成可传参的EXPIRY_THRESHOLD${1:-30}这样既能用默认值跑也能在人工检查时临时设一个更小的值比如bash renew-k8s-certs.sh 7看看哪些证书撑不过下周。这个参数的使用频率很高尤其是你想在“只提醒不动手”的巡检模式里用的时候。3. 备份、续期、重建 kubeconfig脚本里最值钱的三步3.1 带时间戳的整目录备份是后悔药续期之前必须先备份这条几乎算血泪经验。为什么备份不能简单cp -r因为/etc/kubernetes下既有证书又有配置文件如果直接原地覆盖一旦新证书有问题你连回滚的原始文件都没有。脚本的备份策略一般是把整个/etc/kubernetes目录打成 tar 包文件名加上日期时间戳BACKUP_DIR/root/k8s-backup/$(date %Y%m%d-%H%M%S) mkdir -p $BACKUP_DIR tar czf $BACKUP_DIR/kubernetes-etc.tar.gz /etc/kubernetes这样做的好处是你回滚的时候不用去猜“昨天备份的是哪一份”目录名本身就是时间线。注意压缩包里面包含的是/etc/kubernetes的完整路径结构回滚时用tar xzf解包到对应目录即可。备份完成之后建议顺手做一次完整性校验tar tzf看一眼文件数量是否对得上tar tzf $BACKUP_DIR/kubernetes-etc.tar.gz | wc -l如果和备份前的文件数不一致说明备份过程有问题后续操作立刻停止。3.2 续期命令版本差异kubeadm certs renew 与 kubeadm alpha certs renew到提权续期这一步很多老运维会踩一个坑——命令在版本之间换了名字。旧版 kubeadm 用的是kubeadm alpha certs renew all新版直接就是kubeadm certs renew all。如果你在网上复制的命令还是 alpha 开头新版 kubeadm 会直接拒绝执行并提示你命令已变更。脚本里一般会做一次版本判断if kubeadm certs renew --help /dev/null 21; then kubeadm certs renew all else kubeadm alpha certs renew all firenew all会遍历所有由 kubeadm 管理的证书并统一续期这一步执行完/etc/kubernetes/pki下的证书文件时间都会刷新。但注意renew all不负责重新生成 kubeconfig 文件里的客户端证书内容这一步必须单独做。很多版本里renew all会连带更新一部分 kubeconfig但你最好不要赌它全做了后面还要自己确认一遍。3.3 重建 admin.conf 与 kubelet.confkubeconfig 不会自己跟上证书续期后/etc/kubernetes/admin.conf、/etc/kubernetes/kubelet.conf等文件里的client-certificate-data仍然是旧证书的 base64 编码。你必须重新生成 kubeconfig 文件才能让 kubectl、kubelet 拿到新证书。常见做法是用 kubeadm 的 phase 命令重建kubeadm init phase kubeconfig admin --config/etc/kubernetes/kubeadm-config.yaml kubeadm init phase kubeconfig kubelet --config/etc/kubernetes/kubeadm-config.yaml这里的--config参数指向初始化集群时用的 kubeadm 配置文件。如果机器上没有这份文件脚本一般会退而求其次直接用kubeadm init phase kubeconfig all生成一套默认配置但这样生成的 kubeconfig 里 apiserver 地址可能不对需要人工确认。重建之后和 apiserver 交互的admin.conf在你的控制端也要同步更新。脚本一般会输出一个提示让你在需要执行 kubectl 的机器上替换这个文件。另外controller-manager.conf和scheduler.conf通常不需要手动更新因为它们在每次组件重启时会被相应组件读取但为了保险脚本也会一起重建。4. 续期只是上半场节点侧分发与重启顺序决定成败4.1 先理解证书是什么时候被加载的进程启动时才读盘为什么总是强调“续期后必须重启”因为 kube-apiserver、kube-controller-manager、kube-scheduler 都是 static pod由 kubelet 拉起进程在启动时才读取证书文件。你执行renew all只是更新了磁盘上的文件运行中的进程依然持有旧证书。要让它用上新证书必须让对应 pod 重建。在 master 节点上最常见的做法是直接删除 apiserver 等 static pod 的 manifest 文件触发重建或者用kubectl delete pod -n kube-system kube-apiserver-node让它因 pod 被删除而重建。但生产环境里直接 delete 静态 pod 有点心理负担更稳妥的做法是通过kubectl rollout restart或者逐个 delete 并观察 kubelet 日志。我一般会提醒不要三台 master 同时重启 apiserver先重启一台确认kubectl get nodes正常再继续下一台。原因是如果新证书有问题至少还有一台 master 在正常服务你能拿它当排查跳板。4.2 kubelet.conf 不只是 master 有worker 节点也要更新很多人在 master 上做完续期和重启发现kubectl get nodes正常了就以为大功告成。过几天某个 worker 节点突然 NotReady日志里写着certificate has expired or is not yet valid这才想起来 worker 节点的 kubelet 也有自己的 kubeconfig。脚本在处理 worker 节点时一般会这样走# 生成节点 kubelet.conf 后分发到目标节点 scp /etc/kubernetes/kubelet.conf rootworker-ip:/etc/kubernetes/kubelet.conf ssh rootworker-ip systemctl restart kubelet分发之后 worker 节点上的 kubelet 会重新读取 kubelet.conf 里的客户端证书完成与 apiserver 的认证。这个过程里有个小坑kubelet.conf 里的 server 地址必须和 worker 节点能访问到的 master 地址一致如果 apiserver 走的是负载均衡地址那这份配置在 master 上生成时就得确认好。4.3 重启顺序etcd、apiserver、controller-manager、scheduler、kubelet如果续期涉及 etcd 证书重启顺序就变得敏感了。先重启 etcd再重启 apiserver最后是 controller-manager 和 scheduler这是比较公认的顺序。你可以在 master 节点这样操作for pod in $(ls /etc/kubernetes/manifests/); do crictl stopp $(crictl ps | grep ${pod%.yaml} | awk {print $1}) done这是比较原始的做法实际执行时我建议逐个处理先观察 etcd 健康状态再碰 apiserver。etcd 是集群的数据底座它起不来后面所有组件都是白搭。有些人不重启 etcd 也跑得好好的那是因为 etcd 的证书没有在续期列表里被更新或者 etcd 进程自己做了热加载。但你不能赌看日志才是真的。4.4 一张表说清重启后的验证点位组件验证命令预期结果etcdetcdctl endpoint health --cacert...healthykube-apiserverkubectl get pods -n kube-systemapiserver pod 状态 Runningkube-controller-managerkubectl logs -n kube-system查 cert 相关报错无 x509 报错kubeletsystemctl status kubeletactive无证书报错kubeconfigkubectl config view证书有效期已更新所有节点kubectl get nodes全部 Ready这张表适合打印出来贴在工位上每次续期完照着走一遍比凭感觉靠谱得多。5. 避坑清单证书续期时四个高频翻车现场5.1 只有 master 续期worker 节点没处理现象续期后 master 状态正常过几天某个 worker 节点 NotReadykubelet 日志报x509: certificate has expired or is not yet valid。原因kubeadm 的renew all只处理了 master 节点上的证书worker 节点上的 kubelet.conf 不会自动更新。解决脚本里必须带上分发和重启 kubelet 的步骤否则你就是白做了三分之二的工作。5.2 etcd 健康检查证书被 renew all 漏掉现象续期后 apiserver 起来了但 etcd 健康检查一直失败日志出现etcd cluster is unavailable or misconfigured。原因renew all在某些版本下并不会全量覆盖 etcd 的所有证书尤其是etcd/healthcheck-client.crt。解决续期后单独确认 etcd 目录下的证书时间戳必要时单独执行一次kubeadm certs renew etcd-healthcheck-client然后重启 apiserver 让它重新建立健康检查连接。5.3 备份不完整回滚时才发现少文件现象新证书有问题想回滚结果恢复完备份后 kubectl 还是报错。原因备份时只拷贝了/etc/kubernetes/pki漏掉了/etc/kubernetes/*.conf和/etc/kubernetes/manifests。解决统一采用整目录 tar 打包的方式别手动挑文件。回滚之后要对所有节点执行同样的分发不然 master 回滚了worker 还是新证书又是一轮新问题。5.4 忘了更新本机的 ~/.kube/config现象集群里所有操作都正常但你自己电脑上的 kubectl 还是连不上报Unable to connect to the server。原因你本机的~/.kube/config是从旧的admin.conf复制过去的里面内嵌的客户端证书已经过期或即将过期。解决把 master 上新生成的admin.conf覆盖到本机~/.kube/config。具体做法是scp rootmaster-ip:/etc/kubernetes/admin.conf ~/.kube/config替换后先执行kubectl cluster-info验证连通性。注意覆盖前把旧配置备份一份。6. 进阶把检测做成巡检习惯别等它变成故障续期脚本再顺手也不能让它变成一个“想起来才跑一次”的一次性工具。我现在的做法是把它拆成检测和执行两个模式。检测模式只有一个check参数只遍历证书、输出剩余天数不做任何写操作执行模式才走备份、续期、重建 kubeconfig、分发这套完整流程。这样我可以把它放进 crontab 每两周跑一次检测结果发到告警群里只有剩余天数低于 30 才会提示人工介入。检测部分的输出长这样/etc/kubernetes/pki/apiserver.crt 剩余 342 天 /etc/kubernetes/pki/etcd/server.crt 剩余 342 天 /etc/kubernetes/pki/etcd/peer.crt 剩余 342 天 /etc/kubernetes/pki/etcd/healthcheck-client.crt 剩余 342 天 /etc/kubernetes/admin.conf 剩余 342 天从这能看到的不只是“还有多久过期”更重要的是证书体系的完整性——如果某个证书在列表里消失说明对应的组件可能就没有正常加载它。持续观察这份清单你会对集群的证书状态有一种直觉哪天多了一个证书或今天少了一个一眼就能看出问题。验证部分我通常会再做一步确认新证书的签发者和有效期确实指向正确。用一句简单的命令openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -subject -issuer -dates输出里的 issuer 应该是集群自己的 CAdates 里的 notAfter 相比之前推进了一整年。这个检查能防止“证书续期了但 CA 变了、导致其他组件不信任它”这种隐蔽问题。从那以后我每次做完证书续期都会强制自己走一遍检测模式输出清单、核对时间戳、看两个关键 pod 的日志、再从 worker 节点登录一次执行 kubectl 访问 apiserver。这套流程看着简单但每次都帮我避开了不少冷门问题。希望帮到你。本文还有配套的精品资源点击获取