首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >记一次K8s生产故障,从崩溃到恢复的全过程复盘总结

记一次K8s生产故障,从崩溃到恢复的全过程复盘总结

原创
作者头像
用户11081884
修改于 2026-10-08 16:39:11
修改于 2026-10-08 16:39:11
50
举报
文章被收录于专栏:科技专栏科技专栏
图片
图片

编者按:这是一份来自生产一线的真实故障复盘报告。隐去了公司信息,但保留了所有技术细节和心路历程。希望这份用停机时间换来的经验,能为你点亮一盏警示灯。


往期阅读>>

Kubernetes v1.35重磅发布

Kubernetes 10个守护集群安全技巧

Kubernetes Ansible 部署生产级别高可用的集群

Kubernetes 应用无损上下线

Kubernetes Ingress-Nginx mTLS配置安全加密

Kubernetes 重写Ingress Nginx URL的方法

Kubernetes Pod 删除的优先级机制

Kubernetes Ingress Nginx跨域配置

Kubernetes SecurityContext容器安全实践

Kubernetes 10个集群调试与诊断技巧

Kubernetes 开发自定义CRD资源

Kubernetes Pod资源调整:不重启实现垂直扩缩容

Kubernetes Deployment字段配置详解

Kubernetes Service字段配置详解

Kubernetes 设置Pod内存Limit和JVM限制

Kubernetes 获取PID及POD信息的方法

Kubernetes 中 ConfigMap 注入pod的三种方式

Kubernetes Pod分配和调度策略

Kubernetes 标签和选择器的用法

Kubernetes Pod退出状态码详解

Kubernetes中的Service与Ingress

kubernetes暴露服务的三种方式

一、暴风雨前的宁静:一个普通的周四下午

时间:2026年4月X日,15:30。地点:某互联网公司生产Kubernetes集群。集群规模:约80个节点,1200+个Pod,承载核心交易链路。状态:一切正常,监控大盘绿意盎然。团队正在规划下周的集群扩容方案,从80节点扩展到120节点,以应对即将到来的业务高峰。没有人意识到,一场因“未来规划”而埋下的隐患,正在悄然发酵。

二、崩塌:15分钟内的连锁雪崩

15:42 - 第一声警报:监控系统提示,etcd集群存储使用率超过85% 阈值。值班同学看了一眼,认为只是日常波动,未立即处理。因为历史数据表明,etcd使用率常在80%上下浮动。

15:47 - 诡异的延迟:有开发反馈,通过kubectl get pods查看某个命名空间下的Pod列表,响应时间从平时的1-2秒变成了10秒以上。同时,持续集成平台(CI/CD)开始零星报错:“Unable to connect to the server: net/http: request timed out”。

15:50 - 灾难开始:etcd使用率突破95% 告警升级为电话。值班同学试图登录Master节点检查,发现kubectl命令已完全卡死。监控大盘上,API Server的请求错误率瞬间飙升至40%。

15:52 - 雪崩效应:

  1. 控制平面失联:kubelet无法向API Server上报心跳,多个工作节点状态陆续变为 NotReady。
  2. 业务Pod被驱逐:由于节点NotReady,调度器开始将这些节点上的Pod标记为异常,并尝试在其他节点重建。但这需要API Server,而API Server已自身难保。
  3. 服务网格瘫痪:Sidecar代理(如Envoy)因无法从控制平面获取动态配置而开始报错。
  4. 用户影响:外部监控显示,核心交易接口成功率从99.99%骤降至75%,并持续下跌。客服电话开始响起。

15:57 - 全面失控:etcd监控最后一条数据:使用率100%。随后,etcd因为达到--quota-backend-bytes(默认2GB)限制,进入了只读模式。这意味着,整个Kubernetes集群的“大脑”停止了思考,无法再写入任何新的状态变更。集群彻底“脑死亡”。

从第一个预警到全面崩溃,只用了15分钟。

三、混乱与定位:在黑暗中寻找光

16:00 - 紧急响应启动。运维、SRE、基础架构团队被紧急拉入战时频道。最初的几分钟一片混乱:

  • “重启API Server试试?”
  • “是不是被攻击了?”
  • “快切流量到灾备集群!”

16:05 - 确立排查原则。团队负责人叫停所有盲目操作,定下基调:先定位,后行动;先恢复控制平面,再恢复业务。避免在故障之上制造二次故障。

16:10 - 找到关键线索。通过直接SSH登录到etcd节点,绕开崩溃的Kubernetes命令,我们发现了铁证:

代码语言:javascript
复制
# 检查etcd状态
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt \
  --key=/etc/kubernetes/pki/etcd/healthcheck-client.key \
  endpoint status --write-out=table

输出显示,DB SIZE已经达到2.0GB,触发了配额限制。同时,journalctl -u etcd 日志中刷满了 \"etcdserver: mvcc: database space exceeded\" 的错误信息。 Kubernetes ETCD故障恢复

根因瞬间清晰:etcd存储空间被写满,导致集群不可用。

16:15 - 追溯写入源头。空间为什么突然被写满?我们立刻排查了近期变更:

  1. 没有大规模部署。
  2. 没有启用新的Operator或控制器。
  3. 一个关键的线索:团队为了准备扩容,在下午14点左右,于测试命名空间部署了一个“集群压力测试工具”,该工具会疯狂地创建和删除大量的ConfigMap和Job对象,以模拟高负载。但该工具的清理逻辑有Bug,导致大量ConfigMap残留,且每个ConfigMap都包含了几百KB的模拟数据。

罪魁祸首:一个本该在测试命名空间运行的、有缺陷的压力测试工具,在短时间内向etcd灌入了海量的小对象,迅速耗尽了本就不宽裕的存储空间。

四、恢复:一场精细的外科手术

明确了原因,恢复方案就清晰了:必须立即为etcd扩容,并清理无用数据。但etcd处于只读模式,常规操作无法进行。

16:20 - 制定恢复方案:

  1. 紧急扩容:临时修改etcd启动参数,将--quota-backend-bytes从2GB增加到8GB,让etcd恢复写入能力。
  2. 数据清理:启用--auto-compaction-retention并执行一次手动压缩,清理历史版本。
  3. 业务恢复:控制平面恢复后,由节点NotReady而导致的Pod驱逐,需要结合业务优先级,分批手动重建或等待Deployment控制器自动恢复。

16:25 - 执行恢复(高风险操作):这是一次需要慎之又慎的操作,因为操作不当可能导致数据损坏。

  1. 依次停止三个etcd节点(确保每次只有一个节点下线,维持仲裁)。
  2. 在每个节点上,修改etcd的systemd服务文件(如/etc/systemd/system/etcd.service),在启动命令中添加 --quota-backend-bytes=8589934592 --auto-compaction-retention=2)。
  3. 重启etcd节点,并密切观察集群健康状态。
  4. 在etcd全部重启完成后,执行一次全量压缩: etcdctl --command-timeout=60s snapshot save snapshot.db etcdctl snapshot status snapshot.db

16:45 - 控制平面逐步恢复。etcd恢复写入后,API Server、Controller Manager、Scheduler等组件自动重连,错误日志开始减少。kubectl get nodes命令逐渐可以返回数据,NotReady的节点开始一个个恢复为Ready。

17:00 - 业务恢复。我们并没有急于重启所有业务Pod,而是按照事先定义的应用优先级列表,配合研发团队,逐个服务进行验证和重启。优先保障支付、下单等核心链路。

17:45 - 核心业务100%恢复。18:30 - 全部业务服务恢复,监控大盘全面转绿。

总停机时间:约2小时45分钟。

五、复盘:我们到底做错了什么?

事后,我们召开了长达4小时的深度复盘会。这不是追责会,而是学习会。我们梳理出以下几个致命的系统性缺失:

  1. 监控缺失与告警疲劳:
    • 缺失:我们监控了etcd使用率,但没有设置预测性告警(如“按当前增长速度,12小时后将写满”)。也没有对etcd的写操作频率(QPS)和对象数量进行监控。
    • 疲劳:85%的告警被当成了“狼来了”,未能引起足够重视。告警没有分级和明确的操作手册。
  2. 变更管控的致命漏洞:
    • 压力测试工具未经充分评审和测试就运行在了与生产环境共享控制平面的测试命名空间。测试环境应对集群资源有严格的隔离或限制。
    • 没有“爆炸半径”控制:一个测试工具竟能拖垮整个生产集群。
  3. 容量管理的盲目性:
    • 只知道业务需要扩容节点,却从未评估过控制平面(尤其是etcd)的容量。默认的2GB配额在千级别Pod、万级别Kubernetes对象的场景下,本身就是个隐患。
    • 没有定期进行etcd存储空间的使用分析和清理规划。
  4. 应急预案的纸上谈兵:
    • 虽然有灾备方案,但从未演练过“etcd磁盘满”这种具体场景。恢复过程中,临时查文档、试命令,浪费了宝贵时间。

六、我们做了什么(改进清单)

  1. 监控强化:
    • 新增etcd 对象数量(Key总数)、写QPS、存储增长趋势预测监控。
    • 设立不容忽视的告警升级策略:etcd使用率>80%发企业微信,>90%打电话,>95%自动拉群并@所有人。
  2. 架构加固:
    • 立即执行:参照最佳实践,将etcd的--quota-backend-bytes调整为8GB,并设置--auto-compaction-retention=8h。 Kubernetes 百级节点集群调优实战
    • 中期规划:将测试环境的控制平面与生产环境物理隔离,或使用独立的etcd集群。
  3. 流程封堵:
    • 制定《测试命名空间资源配额标准》,严格限制ConfigMap、Secret等对象的数量和大小。
    • 任何可能对控制平面产生压力的工具或部署,必须经过SRE团队审批,并附带监控和熔断方案。
  4. 预案演练:
    • 将“etcd空间满”、“API Server不可用”等场景加入季度故障演练(Chaos Engineering) 必选项。
    • 编写详细的《etcd故障应急操作手册》,包含命令、检查点和回滚步骤。
  5. 文化倡导:
    • 在团队内分享此次复盘报告,强调 “对控制平面保持敬畏”。
    • 推行 “你构建,你负责” 的理念,促使开发者在编写测试工具时也必须考虑其对集群的潜在影响。

七、写在最后

这次故障给我们上了沉重的一课。Kubernetes让我们能轻松管理数百个节点,但也将巨大的复杂性封装在了看似简单的kubectl apply之后。运维的成熟度,不在于平时有多顺,而在于故障时有多稳。

故障是系统脆弱性的显形,也是团队成长最好的催化剂。不要害怕复盘,要害怕在同一个地方跌倒两次。

希望我们的故事,能让你停下脚步,检查一下自己的集群:你的etcd,还剩多少空间?

“无他,惟手熟尔”!有需要的用起来!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、暴风雨前的宁静:一个普通的周四下午
  • 二、崩塌:15分钟内的连锁雪崩
  • 三、混乱与定位:在黑暗中寻找光
  • 四、恢复:一场精细的外科手术
  • 五、复盘:我们到底做错了什么?
  • 六、我们做了什么(改进清单)
  • 七、写在最后
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档