[控场AI]
· 7 分钟阅读· 3,539 字

凌晨3点告警:用分级监控与自愈脚本构建免打扰系统

凌晨3点告警:用分级监控与自愈脚本构建免打扰系统

用分级校准与自愈脚本,让监控系统在无人值守时安静运行。

文章从一次凌晨3:17的ZFS告警切入,指出大多数监控失效并非工具问题,而是校准失效——告警太多导致人学会忽略。作者提出用一个问句「忽略8小时最坏情况是什么」将告警分为L1唤醒、L2醒时处理、L3仅记日志三档,并据此删掉约60%的告警。在工具层面,他用Uptime Kuma、Netdata、Scrutiny和ntfy搭建零运营成本的自托管栈,强调告警必须自带级别与建议动作。自愈脚本遵循「一个检查、一个动作、失败升级」的约束,看门狗已静默恢复仪表盘崩溃11次。最终以「每月被迫起床次数」作为运维质量指标,连续四个月为零。

凌晨3:17,手机震动。屏幕亮得刺眼:「ZFS 池降级——磁盘3校验和错误增加,建议 scrub。」我看了四秒,放下手机继续睡。早上喝完咖啡跑了个 scrub,池子没事,磁盘进了周观察列表。

这个故事之所以无聊,恰恰是因为系统被设计成让告警变得无聊。一年前,我可能要等到池子进入严重降级状态才会知道出事了——那会是完全不同的凌晨体验。

作者的核心洞察是:大多数监控失效不是监控工具的问题,而是校准失效。系统监控一切、告警一切,结果就是一切都不重要。你开始忽略告警,然后错过真正重要的那一条。

rss source: The 3am Problem: Building Systems That Don't Need You Awake

告警分级:一个问句解决80%的噪音

修复校准只靠一个问题:如果这事我忽略8小时,最坏情况是什么? 这个问题几乎能把所有告警分进三个桶。

L1 — 立刻唤醒我。 数据丢失风险(多盘故障导致 ZFS 池降级)、安全入侵指标(异常外连、可疑IP的认证失败)、有真实外部暴露的服务(定时自动化流水线中断)。这些通过 ntfy 高优先级推送,真正会叫醒我。这样的告警总共大概五条。

L2 — 醒着的时候告诉我就行。 降级但稳定:单盘校验和错误升高、容器崩溃后自动重启成功、尚未影响服务的错误率上升、磁盘健康趋势恶化。普通优先级推送,不吵醒我,配咖啡时处理。

L3 — 只记日志,不告警。 其余所有:备份完成、cron 执行结果、健康检查成功、例行 scrub 结果。这些只进日志,永远不进推送通知。

作者第一次应用这个框架时,删掉了大约60%的现有告警。响应质量上升,告警疲劳下降,睡眠质量随之改善。这个数字值得留意——多数人的告警列表里,六成是噪音。

告警疲劳(Alert Fatigue) 是监控领域的经典失效模式:当告警数量超过人的处理能力时,接收者会逐渐对所有告警脱敏,包括真正关键的那一条。研究显示,ICU等高压场景中告警疲劳会显著延长响应时间。在SRE实践中,衡量指标之一是「告警信噪比」——可行动告警占总告警的比例。行业经验值通常认为,一个值班人员每班次能有效处理的告警不应超过个位数;超过这个量级,人就会开始批量划掉通知。作者用「忽略8小时最坏情况」做分级,本质上是在人为压低告警量、提高每条告警的信息密度,从而逆转脱敏过程。

自托管监控栈:零运营成本

作者的监控组合全部跑在自托管基础设施上,没有云依赖,没有 SaaS 费用:

  • Uptime Kuma 负责服务可用性,按计划检查每个服务,宕机告警自带足够上下文,不登录也能判断严重程度。
  • Netdata 负责系统指标,CPU、内存、ZFS 池健康、网络吞吐实时可见。
  • Scrutiny 负责磁盘健康,聚合 SMART 数据并做趋势化,在故障发生前看到退化。
  • ntfy 负责推送,通知里包含告警级别、受影响服务、一行建议操作。

这套组合的关键不在于工具多先进,而在于告警自带决策上下文。如果一条告警需要你登录后台才能判断严不严重,那它本身就是设计失败。

ntfy 是一个开源的自托管推送通知服务,通过HTTP PUT/POST即可向手机或桌面客户端发送消息,支持优先级(min/low/default/high/urgent)、标签和点击跳转链接。与邮件或Slack相比,它的优势在于可以绕过应用层静音策略实现「真正叫醒」的高优先级推送,同时数据不出自己的服务器。作者在L1/L2/L3分级中,正是利用ntfy的优先级字段把「唤醒」与「不唤醒」在传输层就区分开,而不是依赖人去看通知内容再判断——这减少了半夜决策的认知负担。

自愈脚本:一个检查、一个动作

心态转变比工具更重要:别问「坏了我怎么修」,要问「我怎么让它自己修自己」。第二个问题的答案,往往就是二十行 bash——检查一个条件,执行一个动作,写一次日志,失败则升级。写一次,cron 永远跑。

作者 NAS 上实际在跑的几个脚本:

ZFS 健康检查(每6小时)。 从 zpool status 读取校验和错误数,超阈值立即触发 scrub 并发送 L2 通知。scrub 完成后记录结果并跟进:错误清除则记日志,持续存在则升级为 L1。作者已经几个月没有手动发起过 scrub。

容器健康检查(每5分钟)。 检查所有 Docker 容器的 unhealthy 或 exited 状态,发现则按指数退避重启:等1分钟、5分钟、15分钟。连续三次失败后升级 L1 并停止重试。这既避免瞬时崩溃循环吵醒人,又不放过真实故障。

Ollama 推理检查(每10分钟)。 向推理端点发一个最小测试 prompt,连续三次失败触发容器重启,重启后再做端点健康验证才标记恢复。Ollama 已经是承重基础设施——支撑着半个自动化栈——静默失败不可接受。

n8n 工作流队列检查(每10分钟)。 队列深度超过阈值持续10分钟以上,就重启 n8n worker 并记录触发事件。没人注意到的流程积压,正是自动化流水线悄悄腐烂的方式。

所有脚本遵循同一结构:检查条件、只做一个动作、记录时间戳与结果、失败或窗口内第N次复现则通知。关键约束是「只做一个动作」——试图变聪明、走多条恢复路径的脚本会变得不可预测。一个检查,一个动作,不解决就升级。

作者最庆幸存在的脚本是一个每5分钟运行的小看门狗:检查仪表盘 node 进程是否存活并在健康端点响应。不存活就做依赖检查、重启进程、记录恢复。部署以来,它已静默恢复仪表盘崩溃11次——这11次作者实时一个都没察觉,服务就一直在线。这是唯一重要的统计数字。

核心管理守护进程的看门狗则是另一种类型:每分钟检查,但不能自动恢复——重启它造成的问题比原故障更糟(作者踩过这个坑)。所以脚本不尝试修复,只做检测并立刻发 L1。对无法安全自愈的进程,快速检测就是全部的自愈策略。目标是从故障到告警两分钟内,实际稳定在90秒以内。

指数退避(Exponential Backoff) 是一种重试策略:每次失败后等待时间按倍数增长(如1分钟、5分钟、15分钟……),而非固定间隔重试。它的价值在于两点:一是避免瞬时故障引发「崩溃循环」(crash loop)——服务刚起来又挂、脚本反复重启,既消耗资源又制造告警风暴;二是给依赖系统留出恢复窗口。作者在容器健康检查中设置「连续三次失败后升级L1并停止重试」,是在退避基础上加上熔断(circuit breaker)思想:重试有上限,超过上限就把问题交给人,而不是无限重试掩盖真实故障。

多数监控指南漏掉的那一步

它们教你怎么装 Prometheus 和 Grafana,却不告诉你最难的不是埋点,是校准。校准工作需要花一周时间,认真观察哪些告警你真正会行动、哪些看都不看就划掉。这份工作比更好的仪表盘值钱得多。未经校准的告警系统比没有告警更糟:告警太多,你学会忽略,最后比没有还惨。先做校准,再装仪表盘。

睡眠就是指标

作者用一个月度数字衡量自己的运维质量:这个月为了 homelab 起床几次。现在是零,而且已经连续四个月为零——包括开篇那次 ZFS 校验和事件。每一次非零都是系统故障点的数据:要么 L2 事件被误分类成 L1,要么自愈脚本没触发,要么是真正的 L1 事件、本该在白天就被自动化掉。

顺序很明确:先建自动化,再调校准。没有告警的自动化是瞎子,没有自动化的告警只是把你叫醒来做 bash 脚本能做的事。两者结合并校准正确,才是一个自己运行、只告诉你必须知道之事的系统。睡眠就是指标,四个月,还在继续。

背景补充

看门狗(Watchdog) 模式源自嵌入式系统:一个独立的定时器不断被主程序「喂狗」,若主程序卡死未能按时喂狗,看门狗就触发复位。在运维语境中,它指一个与被监控进程解耦的独立检查器,专门检测「进程还在但已无响应」这类静默失败。作者特别指出核心管理守护进程的看门狗「不能自动恢复」,这对应看门狗设计中的一个关键原则:复位能力只应授予那些复位后状态确定、幂等的组件。对有状态或承担编排职责的进程,盲目重启可能引发级联故障,此时看门狗退化为纯检测器,把决策权交还给人。

#告警分级#监控校准#自愈脚本#自托管监控#告警疲劳#homelab运维#ZFS监控#自动化运维
分享:

相关推荐