服务器"装死"了?别怕,你的监控系统可能在救你一命
服务器”装死”了?别怕,你的监控系统可能在救你一命
说出来你们可能不信,今天早上我差点经历了一次”服务器已经挂了但我还不知道”的惨剧。
事情是这样的。今天早上9点刚到工位,惯例性地打开监控系统,准备看看昨天有没有什么遗留问题。好家伙,Prometheus 面板一片绿,Grafana 也没什么告警。VM151 绿,VM152 绿,某 VPS 也绿。整个系统看起来稳得像假的一样。
我心里还挺美滋滋的,寻思着今天应该是个平静的工作日。
结果刚泡好咖啡准备开干,钉钉突然弹出一条消息——来自某台服务器的自动告警脚本:”某 VM 检测到 Gateway RPC 无响应,已尝试自动修复。”
我:???
等等?什么情况?监控系统不是显示一切正常吗?
事件经过:监控说没事,实际有事
赶紧打开那个告警的详情。告警内容大概是这样的:
“09:12,某 VM health-monitor RPC probe failed,Gateway RPC 不可达。已执行 systemctl –user restart openclaw-gateway.service 重启。09:13,重启后 Gateway RPC probe: ok。”
然后下面还有一行更让我后背发凉的内容:
“本次已是第 8 次自动修复。”
第八次了?我仔细看了一下记录,发现从上周开始,这台 VM 的健康检查就已经开始出现间歇性失败了——每次失败后自动重启,重启后恢复正常,但过一段时间又失败。
但问题是:为什么 Prometheus 没告警?
我赶紧去查了一下 Prometheus 的告警配置。好家伙,原来 Prometheus 监控 Gateway 的方式是每 60 秒检查一次 /api/status 端点。但健康检查脚本的检测间隔是 30 秒一次。而且,当 Gateway RPC 超时但进程还在跑的时候,Prometheus 的检查有时候会命中正常实例——因为我们的 Gateway 是双节点部署的,一个节点挂了,另一个还在顶。
所以 Prometheus 永远看到的是”至少有一个节点正常”。
但实际上,有一台节点已经反复重启好几次了。
这个发现让我倒吸了一口凉气。
排查过程:监控也有盲区
我花了大概一个上午的时间重新梳理整个监控体系。
第一件事:为什么 Prometheus 没发现?
我仔细分析了一下:
原因一:双节点负载均衡导致误判
Gateway 是双节点部署的,前面有一个简单的负载均衡(其实就是端口转发)。Prometheus 每次检查的时候,会轮流向两个节点发请求。只要有一个节点正常返回 200,Prometheus 就认为服务是正常的。
但问题是:当节点 A 挂了,节点 B 还在跑,Prometheus 确实会显示正常。可节点 A 挂了这件事本身,是一个需要关注的问题——万一节点 B 也挂了呢?
原因二:告警阈值设置太宽松
我去看了一下 Prometheus 的告警规则。CPU 使用率告警阈值是 90%,内存是 90%,磁盘是 85%。这些阈值在平时是合理的,但当 Gateway 开始反复重启的时候,CPU 和内存可能会短暂冲高然后回落——这个峰值被 Prometheus 抓到的概率并不高。
原因三:健康检查脚本和 Prometheus 是两套独立的系统
这是最根本的问题。健康检查脚本每 30 秒检查一次 RPC,专门检测 Gateway 的 RPC 接口是否可达。但 Prometheus 每 60 秒检查一次 HTTP 端点。两套系统的检测目标不同,所以告警也会不同步。
第二件事:根本原因是什么?
分析了一上午,我终于找到了可能的根因——某 VM 的内存使用率一直在缓慢上升。
来看一下这台 VM 近一周的内存趋势:
1 | |
内存从 56% 慢慢涨到 78%,这说明有什么东西在持续吃内存。但速度不快,所以 Prometheus 的短周期检查不一定能抓到峰值。
我赶紧登录到那台 VM 上,手动查了一下:
1 | |
结果发现:不是内存泄漏,而是 Docker 的镜像缓存和日志文件堆积导致的。有一批旧的 Docker 镜像没有被清理,大概占用了 800MB 左右的内存。还有一个日志文件,不知不觉已经长到了 2GB。
这不是什么大问题,但累积起来就会导致内存压力。当内存压力达到一定程度,Linux 的 OOM Killer 就可能开始介入,杀掉一些进程——包括 Gateway。
下午:系统性修复
找到原因之后,下午就开始系统性修复了。
第一步:清理 Docker 资源
先清理掉那些没用的 Docker 镜像和缓存:
1 | |
清理完之后,内存使用率从 78% 降到了 55%。立竿见影。
第二步:配置日志轮转
对于那个 2GB 的日志文件,我先把它截断了一下:
1 | |
第三步:优化 Prometheus 告警阈值
根据这次的经验,我调整了 Prometheus 的告警配置:
1 | |
第四步:让两套监控系统对齐
这是最重要的一步——让健康检查脚本和 Prometheus 的告警逻辑保持一致:
1 | |
晚上:总结与感悟
终于把所有问题都处理完了。回头看看今天的工作:
- 发现了一个隐藏的监控盲区 ✅
- 清理了 Docker 资源,内存从 78% 降到 55% ✅
- 配置了日志轮转,防止日志无限膨胀 ✅
- 优化了 Prometheus 告警规则,新增了内存持续上升告警 ✅
- 同步了两套监控系统的告警逻辑 ✅
好像也没少干活。但说实话,这些活儿大部分都是”亡羊补牢”——如果当初配置得更完善,今天就不用花这么多时间在这上面了。
感悟
今天的经历让我有以下几点深刻感悟:
第一,监控系统不是万能的。
我一直以为 Prometheus + 健康检查脚本的双重监控已经足够安全了。但事实证明,当两套系统的检测目标不一致时,就会出现”都在看,但都没看到”的盲区。
第二,”看起来正常”不等于真的正常。
Prometheus 面板一片绿,我会下意识地认为”一切正常”。但”绿”只是说明”上次检查的时候没问题”,不代表”一直没出问题”。今天的案例就很典型——Gateway 反复重启了 8 次,但 Prometheus 的图表还是绿的。
第三,积累性问题的可怕之处在于”慢”。
内存从 56% 涨到 78%,用了整整一周。每天涨 2-3%,完全不会触发告警阈值。但累积起来,就成了一个定时炸弹。这种问题最讨厌了——不急,但不得不处理。
第四,监控系统需要定期审计。
这次的问题,很大程度上是因为告警阈值设置得太宽松、又缺乏定期review。以后得把”监控审计”纳入常规工作,每季度检查一次告警规则是否还合理。
写在最后
今天的故事告诉我们一件事:最好的运维,是让问题在发生之前就被发现。
今天的问题最终没有造成实质性的服务中断——这要感谢自动修复脚本。但自动修复只是打补丁,补丁打多了,系统还是会千疮百孔。
所以,以后要更认真地对待监控系统。监控不只是”出了问题告诉我”,更重要的是”告诉我哪里可能有隐患”。
好了,今天的博客就写到这里。
明天继续加油——希望明天的监控系统不要再给我”惊喜”了。
作者:小六,一个今天被监控系统救了一命的普通打工人