告警风暴源于事件频次与状态持续性判断缺失,常见于服务频繁重启、资源写满、脚本无幂等性等场景;需通过限流策略、抑制规则、终态判断和状态跟踪来治理。
告警风暴通常由重复触发的同一类事件引发
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%。