记一次生产环境事故
0x00 序
昨天吃过晚饭,我正躺在床上玩手机。
突然领导微信甩来一张截图:
怎么回事?线上系统无法登录?
我心里一登,意识到生产环境有情况!立马坐起来,赶紧远程到公司电脑,再通过 ssh 登录生产服务器。操作刚落,领导补充一句:
很多用户都反馈过来有这个问题
我再心想,不好,问题覆盖面很广。立刻回复领导:
是接口错误,我在紧急排查,请安抚一下用户
果然不一会,各个用户群消息此起彼伏起来。
首先查看报错信息,是 Redis 无法写入磁盘,立刻执行 df -h
查看剩余空间。果然!Use%
一列为 100%!好家伙,一点都没给我剩啊。
于是我需要排查究竟是什么东西占满了磁盘空间,输入命令 ncdu /var
查看大文件,目标锁定到一个 docker 容器的 json 日志,竟有 14G!龟龟,居然这么大,立刻删除,重启容器。再次检查剩余空间,这下终于可以了,翻看业务系统日志,已没有报错信息,用户可以正常登录。
抢修过程花费不到 5 分钟,还算及时。也还好该业务不涉及支付,并没有给用户和公司带来经济上的损失,实在万幸。
0x01 问题深挖
那么,我的疑问是,上线仅4个月,业务量不大的系统,怎么会有这么多的日志?
在紧急释放了空间后,我立刻追踪了该 docker 容器的日志:
1$ docker logs -f CONTAINER_NAME
一看,每秒都有 定时任务 在跑,还把跑的情况写日志了,这肯定是不行的啊!那么,为什么这个情况会存在于生产环境呢? 我询问了开发这部分功能的同事,他这么回答我:
当时需要调试,就打日志了,上线之后并不清楚会写到 docker 文件,以为是控制台日志不会留存。
而实际上,docker 的 json 文件日志就是业务系统的控制台日志。
这个时候,我突然记起,我在安装 docker 时,有配置过 日志大小限制 呀,怎么没有生效?我查看容器状况:
1$ docker inspect CONTAINER_NAME
看到 LogConfig
一项如下:
1{
2 "LogConfig": {
3 "Type": "json-file",
4 "Config": {}
5 }
6}
咋回事?我再查看全局配置: cat /etc/docker/daemon.json
1{
2 "log-opts": {
3 "max-size": "200m",
4 "max-file": "3"
5 }
6}
这不是有么?我蒙圈了。难道是没有生效?运行命令:
1$ systemctl daemon-reload
2$ systemctl restart docker
再次查看容器状况,还是没有。这真是奇了怪了。
于是我瞪着屏幕大概 10 分钟,终于发现端倪:我把 daemon.json
写成了 deamon.json
!
0x02 事后总结
这次生产事故反映出我司在下面 3 个方面仍有不足:
- 日志记录没有章法。在开发中,调试日志应用
Logger.LogDebug()
记录,这样,在生产环境按日志级别过滤不应记录的日志时,可以直接设置为Warn
级别;另外,后台任务这样的日志,也不应打印出来,容易淹没重要日志。 - 运维操作手动可耻。正因为我司仍没有自动化运维,生产环境初始化配置这一操作依旧手动,
daemon.json
这样的低级拼写错误是不应出现的。 - 生产环境监控与告警设施不完善。如果前两条都没有做到,但有正儿八经的监控告警,那么至少在剩余 20% 空间时,就应该通知到运维人员,这样就有足够时间进行情况处理,甚至是扩容。而不是等到用户投诉、领导反馈,再大难临头。
解决方案当然是有的:
- 加强 Code Review。对于日志记录的策略,实际上是对于代码的管控与审查。写代码随心所欲,导致发布到生产环境时没有和运维人员完全交底(因为自己都忘了这么写过),就会让这些潜在问题突然爆发。良好的代码审查,每次提交代码,都至少要过一遍代码是否合理,这里的合理,主要是指是否 按照编码规范编写,而审查是否会有内存泄漏这种不好看出来问题。
- 推进自动化运维。虽然在我的努力下,已经从刀耕火种的手动复制 Release 文件到服务器上的原始时代,过渡到
Git
提交触发Jenkins
自动 CI 发布的近现代。但是在服务器运维上,仍然缺少自动化工具。这一块其实我司并没有经验,而且我也没有精力去搞,还在忙着做业务。 - 推进基础设施监控与告警。
Prometheus
+Grafana
这一套其实已经足够,但说回来还是受限于人力,没有相关精力搞。
0x03 思考
生产环境紧急情况处理,是每个工程师都要面临的考验,而且对于不同情况的分析、处理,很多都是靠经验,在这件事情上,非常能甄别出经验丰富的工程师。 一个能 Hold 住突发情况的工程师,可以说是公司的救火队员,是救公司业务于危难时刻的关键人物。
曾经带我入行的师傅告诉我,遇到这样的情况,只给你 10 分钟分析问题,10 分钟内不能解决,必须 立刻 恢复生产系统正常运行,放弃事故现场,不要恋战。要成为对公司有价值的员工,什么是有价值?保障了公司业务正常运行不出错就是有价值。对于个人成长而言,你也从一个只会按照需求做业务功能的工程师,逐步成长为可以独当一面的工程师,你的临场分析判断力、临危不乱,是一种真正的个人能力。
实际上,谁都不希望出生产事故,这也是我们为什么要花力气去建设基础设施,做好监控告警,做好自动化,做好研发流程管控。未雨绸缪罢了。