
做K8s运维这几年我见过各种花式翻车现场但最让人后背发凉的一类绝对是认证文件丢失。apiserver起不来、kubectl报unauthorized、node全部变成NotReady整个集群像被锁在门外——数据还在但就是摸不着。这篇不是新手部署入门是给已经在维护集群的兄弟们的一份急救手册覆盖从文件备份、应急恢复到常见坑排查的完整闭环。看完不说让你封神至少下次真遇到这类事故你能稳住不慌知道第一步该动哪里、哪条命令能救场。1. 认证文件丢失不是小概率事件先搞清楚影响面先说一个现实认证文件丢失这事儿在很多团队里不是“会不会发生”的问题而是“什么时候发生”的问题。经常出现的场景包括清理磁盘时误删了/etc/kubernetes/pki重装服务器前没做备份或者某个同事为了腾空间直接把目录删了。也有更隐蔽的情况——文件还在但权限被改了服务启动时读不了和丢失基本没区别。1.1 哪些文件算K8s认证文件K8s的认证体系是一整套 PKI不是单一一个文件。下面这张表基本覆盖了 kubeadm 部署方式下的核心认证文件文件路径用途丢失后的影响/etc/kubernetes/pki/ca.crt和ca.key集群根CA所有组件证书的签发源头集群身份体系崩盘几乎无法在不重建CA的前提下恢复/etc/kubernetes/pki/apiserver.crt和apiserver.keyapiserver对外提供HTTPS服务的证书apiserver启动失败kubectl无法访问/etc/kubernetes/pki/apiserver-kubelet-client.crt和.keyapiserver访问kubelet时用的客户端证书kubelet端拒绝连接日志抓不到exec进不了容器/etc/kubernetes/pki/etcd/下的ca、server、peer证书etcd集群的通信认证etcd起不来集群数据层直接瘫痪/etc/kubernetes/pki/front-proxy-ca.crt和.key聚合API扩展组件认证metrics-server、ingress controller等异常/etc/kubernetes/admin.conf等kubeconfig文件kubectl、kubelet、controller-manager等组件的连接凭证对应组件连接apiserver失败注意/etc/kubernetes/pki里还有 sa.pub 和 sa.key这是 ServiceAccount 的签发密钥。如果 sa.key 丢了旧的 ServiceAccount token 全部失效新token也签不出来这是另一个深坑。1.2 丢失后会发生什么影响面取决于丢的是哪一层。如果只是丢了admin.conf那影响相对可控——重新生成一个admin kubeconfig就行集群本身还能跑。但如果是整个pki目录被删那就是灾难级别kube-apiserver 组件本身是静态Pod或者systemd服务启动时会去加载证书文件不存在直接起不来。就算 apiserver 侥幸起来了etcd 那边认证过不去数据层还是废的。kubelet 已经注册到集群里的可能还残留在节点列表里但状态会迅速变成 NotReady新的kubelet想加入没有CA签发身份也进不来。整个集群对外表现就是kubectl 连不上、业务Pod状态异常、节点集体失联。这个场景和证书过期不一样。证书过期还能续期根CA私钥丢了等于整个集群的身份体系从根上断了。1.3 应急定级先判断还能不能救遇到认证文件丢失第一件事不是手忙脚乱找资料而是冷静做一次定级第一级只丢了某一个 kubeconfig比如 admin.conf 或 kubelet.conf。集群大部分组件还在正常工作恢复难度低。第二级丢了单个组件的证书和私钥比如 apiserver.crt 和 apiserver.key。服务无法启动但根CA完好可以通过重新签发或者kubeadm重建阶段解决。第三级根CA或者etcd的CA私钥丢了。这是最麻烦的情况。除非有完整备份否则想保留原集群身份几乎不可能通常要考虑重建集群或者至少重建整个PKI体系再逐个节点回归。定的级决定了后面要走哪条路。我的建议是先看备份有没有再决定是“恢复文件”还是“重建认证体系”不要一上来就重装集群那是最差方案。2. 防患于未然我最推荐的备份策略运维这行再好的应急都不如事前备份。认证文件不像业务数据那么占空间一个集群所有证书加一起也就几MB但丢一次就让你通宵。所以我一直主张证书备份是K8s集群维护的底线操作。2.1 备份清单只备份证书不够很多新手以为备份就是cp -r /etc/kubernetes/pki其实不够。除了PKI目录还要把这个文件一起纳入备份范围/etc/kubernetes/admin.conf /etc/kubernetes/kubelet.conf /etc/kubernetes/controller-manager.conf /etc/kubernetes/scheduler.conf /etc/kubernetes/kubeadm-config.yaml /var/lib/kubelet/kubeadm-flags.env特别是kubeadm-config.yaml它记录了集群初始化时的配置。后面如果用kubeadm init phase certs all --config重建证书必须依赖这个文件没有它新签出来的apiserver证书可能SAN不完整导致访问IP变化就报证书校验错误。etcd的证书和数据也要考虑。etcd的 pki 目录通常独立成子目录位于/etc/kubernetes/pki/etcd如果etcd 是独立部署不在 /etc/kubernetes 下还要根据实际路径备份。另外建议定期用etcdctl snapshot save做数据快照因为证书重建的最终目的还是保住数据数据没救回来等于白忙。2.2 一个可落地的备份脚本备份脚本没什么玄学关键是便于执行和轮转。我自己的备份脚本差不多长这样#!/bin/bash BACKUP_BASE/backup/k8s-pki DATE$(date %F) BACKUP_DIR$BACKUP_BASE/$DATE mkdir -p $BACKUP_DIR # 备份证书目录 tar czf $BACKUP_DIR/pki.tar.gz -C /etc/kubernetes pki # 备份所有kubeconfig和集群配置 tar czf $BACKUP_DIR/config.tar.gz -C /etc/kubernetes \ admin.conf \ kubelet.conf \ controller-manager.conf \ scheduler.conf \ kubeadm-config.yaml # 备份etcd证书如果路径存在 if [ -d /etc/kubernetes/pki/etcd ]; then tar czf $BACKUP_DIR/etcd-pki.tar.gz -C /etc/kubernetes/pki etcd fi # 清理7天前的备份 find $BACKUP_BASE -maxdepth 1 -type d -mtime 7 -exec rm -rf {} \;脚本本身工作量不大真正关键的是跑起来。在控制节点上加个 systemd timer每天凌晨执行一次几行配置的事# /etc/systemd/system/k8s-pki-backup.service [Unit] DescriptionBackup K8s PKI files [Service] Typeoneshot ExecStart/usr/local/bin/k8s-pki-backup.sh # /etc/systemd/system/k8s-pki-backup.timer [Unit] DescriptionRun k8s pki backup daily [Timer] OnCalendar*-*-* 02:17:00 [Install] WantedBytimers.target然后systemctl enable --now k8s-pki-backup.timer就行。这里有个细节随机选一个凌晨时间而不是整点避免和大量定时任务撞车尤其是数据库备份和高峰备份时段错开省得半夜磁盘I/O打架。2.3 备份安全策略加密、离线、权限备份做完不等于万事大吉。纯文本的证书压缩包如果被人拿到等于拿到了集群的控制权。建议备份目录权限设为600或700不要给默认644。用tar配合对称加密比如openssl enc -aes-256-cbc -salt -in pki.tar.gz -out pki.tar.gz.enc密码放在专门的密钥管理工具或密码管理器里。至少保留一份备份在集群之外比如对象存储或者另一台主机。原因很直接集群整体宕机时要能拿到备份如果备份就在出事的机器上可能跟着一起丢了。恢复时先验证备份的完整性解压前用gpg --verify或者直接tar -tzf 看一下文件列表不要等到恢复了一半才发现文件损坏。我在实际处理中还遇到过一个问题备份脚本本身没有加环境变量cron 里 PATH 不完整运行时tar和find命令找不到脚本静默失败。所以脚本里尽量写绝对路径或者至少明确定义PATH/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin。这也是为什么备份脚本要定期手动跑一次而不是写完就再也不管。3. 应急处理从故障到恢复的实操流程备份做得再好总有可能在第一次备份前就出事或者备份本身也丢了。所以应急流程还得按“有备份”和“没有备份”两种情况分别准备。3.1 有备份十分钟恢复路径假设你敢在故障后拍着胸脯说“备份肯定在”那恢复的路径非常明确先在出事的节点上看看/etc/kubernetes到底还剩什么ls -la /etc/kubernetes/ find /etc/kubernetes/pki -type f 2/dev/null把备份里的证书解压回去cd /etc/kubernetes tar xzf /backup/k8s-pki/2025-06-01/pki.tar.gz tar xzf /backup/k8s-pki/2025-06-01/config.tar.gz检查文件权限。证书目录通常是 644key 文件必须 600所有者 root。如果权限不对服务照样起不来chown -R root:root /etc/kubernetes/pki chmod 600 /etc/kubernetes/pki/*.key chmod 600 /etc/kubernetes/pki/etcd/*.key如果 kubeadm 部署的可以用 kubeadm 显式刷新一遍所有配置kubeadm init phase kubeconfig admin --config/etc/kubernetes/kubeadm-config.yaml重启 kubelet同时如果 apiserver 是静态Podkubelet 会自动把容器拉起来如果是二进制部署的服务直接systemctl restart kube-apiserver。用kubectl get nodes验证控制面恢复。这里提醒一句备份中如果只备份了证书没备份 kubeadm-config.yaml恢复后可能面临SAN问题所以第一步先确认这个配置文件在不在不在的话后续 apiserver 证书大概率要重建。3.2 没有备份用kubeadm重建认证体系没有备份就麻烦很多但也不是完全没救。对 kubeadm 部署的集群kubeadm 提供了按阶段生成证书的能力。先看一下现在的CA情况ls -la /etc/kubernetes/pki/如果ca.crt和ca.key都还在只是其他组件证书丢了可以直接用 kubeadm 重新生成缺失的证书kubeadm init phase certs all --config/etc/kubernetes/kubeadm-config.yaml这个命令会补齐 apiserver、apiserver-kubelet-client、front-proxy-client、etcd等组件的证书。它会读取配置里指定的SAN列表所以只要 kubeadm-config.yaml 还在问题就不大。生成完之后再重新生成各组件连接集群用的 kubeconfigkubeadm init phase kubeconfig all --config/etc/kubernetes/kubeadm-config.yaml最后重启 kubeletsystemctl restart kubelet如果ca.key本身也丢了但ca.crt还在理论上你还能用现有CA证书继续签但实际上ca.key丢失就无法用同一CA签发新证书。这种情况下kubeadm 也不会帮你凭空变出私钥通常只能通过kubeadm init phase certs all配合--config重新生成一套新的CA这意味着整个集群的信任关系变了所有存量组件都要重新认证。我实际处理过一个案例集群跑了一年多磁盘被人清理pki目录整个没了备份也没有。最后没办法只能新建一套CA和证书然后用kubeadm reset把所有节点重置再通过kubeadm join重新加入相当于整个集群重建了一遍。幸运的是业务数据都在etcd里而etcd数据目录没被删所以最后数据保住了。这种“身份全丢但数据还在”的情况处理起来特别考验思路没有备份真的会让运维人一夜白头。3.3 kubeconfig单独丢失最轻量级的恢复只丢admin.conf的情况恢复起来很轻量不需要动上面那些证书目录。kubeadm init phase kubeconfig admin --config/etc/kubernetes/kubeadm-config.yaml这条命令会根据根CA和apiserver的地址重新生成 admin.conf。生成后把它复制到本地~/.kube/config即可mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config如果 kubelet.conf 丢了同理执行kubeadm init phase kubeconfig kubelet --config/etc/kubernetes/kubeadm-config.yaml或者干脆用kubeadm init phase kubeconfig all一次性全部生成。有人可能问如果管理员本地的~/.kube/config也一起丢了呢这种情况可以通过 apiserver 的日志或者配置找回集群地址和CA串。就算没有现成的 admin 凭证只要能SSH到控制节点并且控制节点上 kubelet 还在正常跑都可以在节点上用kubectl --kubeconfig/etc/kubernetes/admin.conf get nodes来验证。3.4 worker节点认证文件丢失重新加入集群worker节点的认证文件主要是/etc/kubernetes/kubelet.conf和/var/lib/kubelet/pki/kubelet-client-current.pem。如果只是kubelet客户端证书过期或者丢失最快的办法是重新执行kubeadm join。控制面上先生成新的tokenkubeadm token create --print-join-command输出会直接包含kubeadm join apiserver:port --token token --discovery-token-ca-cert-hash sha256:hash。但在执行 join 之前先把节点上的旧身份清理掉kubeadm reset -f rm -rf /etc/kubernetes rm -rf /var/lib/kubelet然后执行控制面输出的 join 命令。注意kubeadm reset会删除节点上的kubelet配置和所有相关文件执行前确认这是一个可重建的节点不是承载无状态服务必须保留本机文件的特殊情况。如果发现节点上控制面无法访问检查 apiserver 地址、防火墙规则和token有效期。token 默认有效期24小时如果是很久之前生成的token建议重新用kubeadm token create生成。4. 手动签发证书的底层逻辑理解之后不会再慌kubeadm 封装了很多证书生成逻辑但真实生产环境有很多二进制部署的集群或者因为网络隔离、安全要求不能直接用 kubeadm。这种时候手动签发证书的能力就是保命技能。4.1 K8s的PKI体系是怎么串起来的K8s的认证体系很像一个公司内部的门禁系统。根CA是集团HR负责给每个员工发工牌apiserver是大门闸机需要验证来访者身份kubelet、controller-manager、scheduler是不同区域的员工手里拿着各自工牌。所有工牌都由同一个HR签发大家都认可这个HR的公章这就是为什么根CA是整个体系的核心。根CA有个自签名的证书对ca.crt是公钥ca.key是私钥。所有组件证书都以ca.crt为签发者。只要根CA不丢任何组件证书丢了都可以基于同一个根CA重新签一份老组件的高速缓存也能继续信任因为签发者没变。好基于这个逻辑手动签发apiserver证书就变得很清晰用已有的ca.crt和ca.key生成或重新生成某个组件的私钥然后用CA私钥给组件的证书签名。4.2 手动签发apiserver证书实操假设根CA还在apiserver.crt 和 apiserver.key 丢了需要手动签发。步骤如下先生成apiserver的私钥openssl genrsa -out apiserver.key 2048准备一个OpenSSL配置文件这里的关键是subjectAltName必须包含apiserver的几种访问地址[ req ] default_bits 2048 prompt no default_md sha256 distinguished_name dn req_extensions req_ext [ dn ] CN kube-apiserver [ req_ext ] subjectAltName alt_names [ v3_ext ] authorityKeyIdentifierkeyid,issuer basicConstraintsCA:FALSE keyUsage digitalSignature, keyEncipherment extendedKeyUsage serverAuth subjectAltName alt_names [ alt_names ] DNS.1 kubernetes DNS.2 kubernetes.default DNS.3 kubernetes.default.svc DNS.4 kubernetes.default.svc.cluster.local DNS.5 localhost IP.1 127.0.0.1 IP.2 192.168.1.10这里的192.168.1.10要替换成你的 apiserver 对外访问地址如果是云环境还应该把负载均衡器地址加进去。漏了任何一个访问地址都会导致那个地址访问时报证书校验失败。生成证书签名请求openssl req -new -key apiserver.key -out apiserver.csr -config openssl.cnf用根CA签发证书openssl x509 -req -in apiserver.csr \ -CA ca.crt -CAkey ca.key -CAcreateserial \ -out apiserver.crt -days 3650 \ -extensions v3_ext -extfile openssl.cnf把签好的证书放到对应目录设置好权限install -m 644 apiserver.crt /etc/kubernetes/pki/apiserver.crt install -m 600 apiserver.key /etc/kubernetes/pki/apiserver.key签发其他组件的证书也是同一个套路区别在于extendedKeyUsageapiserver的证书需要serverAuthapiserver访问kubelet的客户端证书需要clientAuth而kubelet自己的服务端证书一般两者都带。4.3 证书SAN缺失是改完之后最常见的坑手动签发证书时最容易踩的坑就是SAN没写全。K8s的apiserver对外访问方式很多样本地回环、集群IP、Service名称、集群外部的负载均衡IP、域名。只要有一个访问地址没放进SAN客户端从那个地址访问时就会提示证书信任失败。报错信息通常长这样x509: certificate is valid for 10.96.0.1, 192.168.1.10, not 172.20.0.5解决办法也很直接重新生成apiserver证书把报错里提到的IP或者域名加入alt_names再替换证书并重启apiserver。这种问题不需要重建集群但如果不理解原因很容易折腾半天找不到方向。5. 恢复过程中的常见坑和排查技巧实际操作中认证文件恢复并不总是顺顺利利很多坑是文档里不会写的。我总结了一些高频问题和排查思路。5.1 常见报错速查表报错或现象可能原因排查与处理x509: certificate has expired or is not yet valid证书过期或服务器时间不对先确认时间同步再看证书有效期kubeadm可以直接续期x509: certificate is valid for ..., not ...apiserver证书SAN缺地址重新签发apiserver证书补充SANcertificate signed by unknown authority客户端不信任签发证书的CA或者CA换了检查是不是根CA被替换把新CA加入受信任列表kubelet报403 Forbiddenapiserver的 client certificate 没权限检查 apiserver-kubelet-client 证书和RBAC绑定etcd报证书错误etcd peer证书/server证书丢失或过期如果是etcd独立部署用etcdctl检查和重新签发Unable to connect to the server: x509kubeconfig里的CA数据和新CA不一致重新生成admin.confkubeadm init phase certs all生成后apiserver还是起不来证书权限或路径不对用journalctl -u kubelet或查看静态Pod日志5.2 用openssl快速判断证书状态判断证书能不能用openssl是最趁手的工具。三个命令搞定大部分问题# 查看证书有效期和主题信息 openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -dates -subject -issuer # 验证证书与私钥是否匹配 openssl x509 -noout -modulus -in /etc/kubernetes/pki/apiserver.crt | openssl sha256 openssl rsa -noout -modulus -in /etc/kubernetes/pki/apiserver.key | openssl sha256 # 验证证书是否由当前CA签发 openssl verify -CAfile /etc/kubernetes/pki/ca.crt /etc/kubernetes/pki/apiserver.crt前两条命令输出的哈希一致说明证书和私钥是配套的。第三条命令输出OK说明证书链信任没问题。这套检查基本能把认证问题锁定在“证书自身问题”还是“组件配置问题”上。我用这套组合排查过好几次集群故障包括一次apiserver反复崩溃的现场最后发现是apiserver.crt和apiserver.key不匹配估计是之前某次操作混用了新老文件。5.3 最后的兜底干脆重建集群如果根CA私钥彻底丢失且没有任何备份同时还涉及etcd证书丢失就不建议继续在原集群废墟上折腾了直接重建可能更快。具体路径用etcdctl snapshot save或从磁盘数据目录尽量导出已有的etcd数据快照。记录当前业务命名空间里的Deployment、Service等对象清单有条件的直接导出为YAMLkubectl get deploy,svc,cm,secret -n namespace -o yaml backup.yaml。在新机器上初始化一个新集群重新生成整套PKI。把旧etcd快照恢复到新集群的etcd里这一步操作要非常谨慎版本不匹配会连环报错。用导出的YAML重新创建业务资源。这个方案损失的时间最多但胜在不会在旧集群上越修越乱。尤其是证书体系和etcd全部丢失的情况硬修往往比重建更花时间。6. 最后说几句实在话做运维这么多年我越来越觉得认证文件这类东西有点像家门钥匙你在家的时候不会觉得它重要哪天出门倒垃圾被风把门带上才会意识到问题有多严重。K8s集群不像单机服务牵一发动全身证书丢失的影响是链式的apiserver挂掉导致kubectl各种报错kubelet接二连三掉线etcd也开始报警整个群乱成一锅粥。我自己的体会是遇到这类事故最重要的不是背几条命令而是先建立一套恢复顺序先判断根CA是否还在再判断有没有备份最后才决定走哪条恢复路径。无脑重启那是最低效的做法。另外我强烈建议找个周末拿一台测试集群把pki目录打包挪走然后按本文的流程走一遍恢复。真演练过之后你会发现生产环境再次遇到这个问题时手是完全不抖的。很多事情看着简单真正在限时故障、业务方连环催的情况下操作完全是另一回事。这就是为什么我一直强调演练哪怕只是在自己的笔记本虚拟机上跑一遍也行。