事故级别:P0|影响范围:全量业务|恢复时长:4小时23分钟
故障突现:集群全面失联
监控系统在凌晨发出密集告警,提示Kubernetes API Server无响应、etcd健康检查失败以及所有业务Pod状态异常。这通常意味着底层核心组件出现了严重问题。
初步定位:聚焦etcd集群
通过SSH登录Master节点后,发现kubectl命令无法连接API Server。随即检查etcd服务状态,虽然进程仍在运行,但etcdctl endpoint health命令显示集群所有节点均处于unhealthy状态,且响应超时,这排除了简单的网络故障可能。
深度排查:揭露数据库空间危机
首先查看etcd服务日志,发现了关键错误信息:database space exceeded 和 mvcc: database space exceeded。
接着,通过etcdctl endpoint status命令查看集群详细信息:
$ etcdctl endpoint status --write-out=table --cluster
+------------------+------------------+---------+---------+-----------+-----------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM |
+------------------+------------------+---------+---------+-----------+-----------+
| 10.0.1.10:2379 | 8e9e05c52164694d | 3.4.13 | 8.2 GB | true | 5 |
| 10.0.1.11:2379 | 8e9e05c52164694e | 3.4.13 | 8.1 GB | false | 5 |
| 10.0.1.12:2379 | 8e9e05c52164694f | 3.4.13 | 8.3 GB | false | 5 |
+------------------+------------------+---------+---------+-----------+-----------+
数据显示每个节点的数据库文件大小异常膨胀至8GB以上,远超正常范围(通常为几百MB)。尝试执行etcdctl defrag命令进行碎片整理时失败,提示空间不足。
通过对比etcd中存储的实际有效数据量与数据库文件占用的磁盘空间,计算出了惊人的碎片化率:
- 实际有效数据量:约156 MB
- 数据库文件大小:8.4 GB
- 碎片化率 = (8.4 GB - 156 MB) / 8.4 GB ≈ 98.1%
etcd数据库已近乎完全被碎片占据,这是导致其性能急剧下降直至不可用的根本原因。对于此类核心组件的维护,建立系统的云原生/IaaS运维体系至关重要。
根因追溯:配置疏漏与异常流量
通过对历史日志和配置的分析,定位到以下几个主要原因:
- 自动压缩机制失效:etcd配置文件中
auto-compaction-retention 参数被设置为 "0",这等同于禁用了自动压缩历史数据的功能。
- 历史数据堆积:由于未压缩,etcd内部积累了超过184万个key的旧版本数据。
- 异常写入压力:排查发现某个应用存在缺陷,在过去一段时间内频繁重启,产生了超过284万次的Pod状态变更记录,这些大量的
PUT和DELETE操作加剧了数据碎片化。
- 空间配额触顶:配置的
quota-backend-bytes (8GB) 已被占满,触发了etcd的写保护机制。
恢复操作:四阶段紧急处置
阶段一:临时扩容配额(耗时约15分钟)
为避免空间不足导致恢复操作失败,首先临时提升数据库配额。
# 临时将后端存储配额提升至12GB
$ etcdctl put quota-backend-bytes 12884901888
# 重启etcd服务使配置生效
$ systemctl restart etcd
阶段二:手动压缩历史版本(耗时约45分钟)
执行压缩命令,清理旧版本数据,仅保留最近的1000个版本。
# 获取当前版本号(revision)
$ rev=$(etcdctl endpoint status --write-out="json" | jq '.[0].Status.header.revision')
# 执行压缩
$ etcdctl compact $((rev-1000))
阶段三:逐节点整理碎片(耗时约180分钟)
压缩后,数据库逻辑空间被释放,但物理磁盘空间仍未回收,需对每个节点依次进行碎片整理。
for endpoint in 10.0.1.10:2379 10.0.1.11:2379 10.0.1.12:2379; do
echo "正在对节点 $endpoint 进行碎片整理..."
etcdctl --endpoints=$endpoint defrag
# 整理后暂停片刻,避免对集群造成冲击
sleep 60
done
整理完成后验证,数据库大小成功从8GB+降至180MB左右。
阶段四:验证集群与服务(耗时约23分钟)
- 验证Kubernetes API Server恢复:
kubectl cluster-info 可正常输出。
- 验证所有Node状态:
kubectl get nodes 显示所有节点 Ready。
- 验证业务Pod:
kubectl get pods --all-namespaces 确认所有Pod均处于运行状态。
加固措施:从救火到防火
为防止问题复发,我们实施了以下永久性改进:
- 优化etcd配置:启用周期性的自动压缩。
auto-compaction-mode: periodic
auto-compaction-retention: "5m" # 每5分钟压缩一次历史版本
quota-backend-bytes: 8589934592 # 8GB
- 增强监控告警:在Prometheus中配置关键指标告警规则,如数据库空间使用率超过80%或碎片化率超过50%时提前预警。
- 制定自动化运维脚本:编写每日健康检查脚本,自动计算碎片化率并在超过阈值时触发整理。这属于运维/DevOps中提升效率与稳定性的关键实践。
- 完善云原生/IaaS监控体系:将对etcd性能指标(如读写延迟、wal日志同步时间)的监控纳入整体监控大盘。
经验总结与最佳实践
- 监控先行:对
etcd_mvcc_db_total_size_in_bytes、etcd_server_quota_backend_bytes等核心指标建立容量趋势监控与预警。
- 定期巡检:将碎片化率检查纳入日常或每周巡检清单。
- 规范配置:生产环境必须启用合理的
auto-compaction-retention策略。
- 控制变更:优化应用发布与自愈逻辑,避免产生大量密集的元数据写入操作。