事故复盘

一次服务器磁盘空间耗尽的事故复盘

从告警缺失到日志失控:时间线、根因、修复和长期行动项。

事件摘要#

这是一个经过脱敏的演练型复盘:凌晨磁盘使用率从 71% 上升到 100%,Nginx 无法写日志,PostgreSQL 临时文件创建失败,最终表现为文章页间歇性 500。恢复目标是先阻止继续写满,再释放可确认的数据,最后恢复服务。

时间线#

时间现象与动作结果
02:13首个 5xx 告警确认用户受影响
02:17df -h 显示根分区 100%排除 inode 问题
02:22定位 38 GB 容器 JSON 日志找到主要增量
02:30暂停异常任务并轮转日志写入恢复
02:41数据库、首页、登录验证通过结束应急阶段

证据收集#

bash
date -Is
df -hT
df -ih
du -xhd1 /var /www 2>/dev/null | sort -h
find /var/lib/docker/containers -name '*-json.log' -printf '%s %p
' | sort -nr | head
journalctl --since '02:00' --until '03:00' -p warning

根因链#

  1. 一个下游连接错误进入无退避重试。
  2. 应用每次重试打印完整堆栈。
  3. 容器未配置 max-size 与 max-file。
  4. 磁盘告警阈值只设为 95%,且没有增长速率告警。
  5. 根分区同时承载数据库与容器日志,故障域没有隔离。

修复与验证#

  • 停止异常重试任务
  • 配置容器日志轮转
  • 增加 70%/85% 分级告警和 6 小时增长预测
  • 将数据库数据卷迁移到独立磁盘
  • 编写只读磁盘排查 Runbook
bash
docker compose up -d --force-recreate app
curl -fsS https://blog.example.com/api/health
docker exec postgres pg_isready -U blog -d gkblog

复盘结论#

直接原因是日志无上限,系统性原因是没有容量预算和增长率监控。行动项必须有负责人、截止时间和验证证据;“加强监控”不是可验收的修复。

GK / OPS NOTES
把每一次变更写成可以复现的步骤

示例命令请先在测试环境验证,再根据自己的系统版本、网络和备份策略调整。

讨论区 56

分享你的经验、补充或不同观点。支持 Markdown 基础语法。

讨论区暂时为空,欢迎分享你的经验。