告警风暴源于事件频次与状态持续性判断缺失,常见于服务频繁重启、资源写满、脚本无幂等性等场景;需通过限流策略、抑制规则、终态判断和状态跟踪来治理。

告警风暴通常由重复触发的同一类事件引发
Linux 系统中,systemd-journald、rsyslog 或监控代理(如 telegraf、zabbix-agent)在服务反复崩溃、磁盘写满、网络闪断等场景下,可能每秒生成数十甚至上百条相似告警。典型表现是:同一主机短时间内收到大量内容高度雷同的邮件/SMS/IM 通知,比如连续 50 条 "disk usage > 95% on /dev/sda1"。
根本原因不是告警工具本身有问题,而是缺乏对「事件频次」和「状态持续性」的判断。例如一个进程每 3 秒重启一次,monit 默认会每次启动都发告警,而不是“首次异常时告警,后续保持静默直到恢复”。
- 检查告警源头是否做了去重或抑制:比如
Alertmanager的group_by和mute_time_intervals配置是否生效 - 确认日志采集端是否启用了速率限制——
rsyslog可用$SystemLogRateLimitInterval和$SystemLogRateLimitBurst - 避免在 shell 脚本中用
curl直连告警接口而无失败重试退避逻辑,否则网络抖动会导致批量重发
systemd 服务频繁重启是常见风暴源头
当 systemd 中某个服务设置了 Restart=always 且启动即失败(如配置错误、依赖未就绪),它会在 StartLimitIntervalSec 时间窗内不断尝试重启,每次失败都会被 journald 记录,并可能被上层监控抓取为独立告警事件。
例如:myapp.service 因缺少 /etc/myapp/config.yml 启动失败,systemd 在 10 秒内重试了 8 次,监控脚本每 5 秒扫一次 journalctl -u myapp --since "1 hour ago" | grep "failed",结果每次扫出新日志就触发一次告警。
- 给关键服务设置合理的重启策略:
Restart=on-failure+StartLimitIntervalSec=60+StartLimitBurst=3,超出后自动停用 - 用
systemctl show myapp.service | grep -E "(StartLimit|Restart)"核实当前限流参数是否加载成功 - 不要在告警逻辑里直接解析 journal 日志做计数——改用
systemctl is-failed myapp.service判断终态,减少噪声
磁盘/内存等资源类告警容易误触发连锁反应
当 /var/log 分区写满,rsyslog 无法写入日志,继而 systemd-journald 切换到运行时日志模式,再触发 logrotate 异常退出……这一连串异常可能在 2 分钟内产生 20+ 个不同组件的告警,但根源只是最初那个 df -h /var/log 返回 100%。
这类场景下,告警系统若未定义依赖关系或抑制规则,就会把“症状”当成“病因”逐个上报,形成雪崩式通知。
- 在 Alertmanager 中为资源类告警添加
inhibit_rules:例如当node_filesystem_usage{mountpoint="/var/log"} > 0.95触发时,抑制所有node_systemd_unit_state{name=~"rsyslog|journald|logrotate"}的告警 - 对
df类检查,改用「持续 N 分钟超阈值」逻辑,而非单次采样——Prometheus 可用avg_over_time(node_filesystem_usage[10m]) > 0.9 - 定期清理旧日志不是靠
rm -f,而是确保logrotate的maxage和minsize参数匹配实际负载,避免轮转卡死
自定义脚本告警缺乏幂等性和状态跟踪
很多团队用简单 shell 脚本配合 mail 或 curl 发送告警,但没记录上次发送时间、没比对当前状态是否已恢复、也没加锁防止并发执行。结果一个临时网络抖动导致脚本每分钟跑一次,每次都在发“connect timeout”,收件人第 7 次看到时已经忽略。
这类脚本往往还硬编码了告警阈值和接收人,一旦要调整就得改多台机器,进一步加剧配置不一致带来的误报。
- 每次执行前先检查状态是否变化:用
stat -c "%Y" /tmp/mycheck.lastok判断上次成功时间,仅当距今超 5 分钟才允许再次告警 - 用文件锁避免并发:
flock -n /tmp/mycheck.lock -c "your_check_logic" - 把阈值、接收人、重试间隔等抽成变量或外部配置文件,别写死在脚本里
真正难处理的从来不是单点故障,而是多个看似无关的指标在特定条件下共振放大——比如 nginx 连接数飙升 → 触发 ulimit 报错 → 导致 systemd 服务重启 → 日志写满 → 告警通道自身失效。治理告警风暴,本质是给监控系统装上「因果推理」和「状态记忆」能力,而不是堆更多过滤规则。










