Margrop
Articles320
Tags481
Categories7

Categories

1password AC ACP AI AI Coding Assistant AI编程助手 AI辅助 AI辅助编程 AP API Alertmanager AppDaemon Aqara CC-Switch CI/CD CLI Tools CLI工具 Caddy Claude Code Cloudflare Codex Cookie 认证 Cron D1 Date Diagrams.net Diary Docker Docker Compose Efficiency Tools Electerm English Gateway Gemini CLI GitHub Actions HA HADashboard Hexo HomeAssistant IP IPv4 Java LVM‑Thin Linux MacOS Markdown MiniMax Multi-Agent MySQL NAS Nginx Node-RED Node.js OOM OpenAI OpenClaw OpenCode OpenResty OpenWrt PPPoE Portainer PostgreSQL ProcessOn Prometheus Proxmox VE RPC SOCKS5 SSL Session Shell Subagent TTS TimeMachine UML Uptime Kuma VPN VPS Web WebSocket Windows Workers activate ad adb adblock agent aligenie aliyun alpine annotation aop authy autofs backup baidupan bash bitwarden boot brew browser caddy2 cdn centos cert certbot charles chat chrome classloader client clone closures cloudflare cmd command commit container crontab ctyun ddsm demo dependency deploy developer devtools dll dns docker domain download draw drawio dsm dump dylib edge exception export fail2ban feign firewall-cmd flow frp frpc frps fuckgfw function gcc gfw git github golang gperftools gridea grub gvt-g hacs havcs heap hello hexo hibernate hidpi hoisting homeassistant hosts html htmlparser https iKuai idea image img img2kvm immortalwrt import index install intel io ios ip iptables iptv ipv6 iso java javascript jetbrains jni jnilib jpa js json jsonb jupter jupyterlab jvm k8s kernel key kid kms kodi koolproxy koolproxyr kvm lan lastpass launchctl learning lede letsencrypt linux live low-code lvm lxc m3u8 mac macos mariadb markdown maven md5 microcode mirror modem modules monitor mount mstsc mysql n2n n5105 nas network nfs node node-red nodejs nohup notepad++ npm nssm ntp oop openfeign openssl os otp ovz p14 packet capture pat pdf pem perf ping pip plugin png powerbutton print pro proxy pve pvekclean python qcow2 qemu qemu-guest-agent rar reboot reflog remote remote desktop renew repo resize retina root route router rule rules runtime safari sata scipy-notebook scoping scp server slmgr so socks source spk spring springboot springfox ssh ssl stash string supernode svg svn swagger sync synology systemctl systemd tap tap-windows tapwindows telecom template terminal tls tmux token totp tvbox txt ubuntu udisk ui undertow uninstall unlocker upgrade url v2ray vhd vim vlmcsd vm vmdk web websocket wechat windows with worker wow xiaoya xml yum zip 中国电信 云电脑 交换机 人机协作 代理 优化 体检 值班 健康检查 光猫 公网IP 内存 内存优化 内网 内网IP 内网渗透 写作 升级 协作 博客 反向代理 启动 告警 告警优化 周一 周一焦虑 周五 周末 夏令时 多智能体 多节点 多节点管理 天猫精灵 天翼云 安全 安装 定时任务 容器 容器网络 导入 小米 工作感悟 常用软件 广告屏蔽 序列号 应用市场 异常 心智成长 心跳 心跳检查 性能优化 感悟 打工 打工人 技术 抓包 排查 描述文件 故障 故障排查 效率 效率工具 旁路由 无服务器 日记 时区 显卡虚拟化 智能家居 智能音箱 服务器 服务管理 架构 梯子 模块 流程 流程图 浏览器 漫游 激活 火绒 焦虑 玄学 生活 电信 画图 监控 监控系统 直播源 直觉 磁盘 端口 端口冲突 端口扫描 管理 续期 网关 网络 网络风暴 群晖 脚本 脚本优化 腾讯 自动化 自动恢复 虚拟机 认证 证书 语雀 超时 路由 路由器 软件管家 软路由 运维 运维监控 连接保活 连接问题 通信机制 通知 部署 配置 钉钉 镜像 镜像源 门窗传感器 问题排查 防火墙 阿里云 阿里源 集客 飞书

Hitokoto

Archive

OpenClaw 告警疲劳与通知优化实践:从"狂轰滥炸"到"精准打击"

OpenClaw 告警疲劳与通知优化实践:从"狂轰滥炸"到"精准打击"

前言

运维工程师最怕什么?不是服务器宕机,而是半夜被一堆无意义的告警叫醒

凌晨三点,你的手机疯狂震动。睡眼惺忪地抓起手机一看:

  • “服务器 CPU 使用率超过 80%”
  • “服务器 CPU 使用率超过 85%”
  • “服务器 CPU 使用率超过 90%”
  • “服务器内存使用率超过 85%”
  • “服务器内存使用率超过 90%”
  • “服务器内存使用率超过 95%”

你从床上跳起来,冲到电脑前,准备处理一场重大事故。

结果发现——服务器好好的,CPU 刚才飙了一下,现在已经正常了。内存也是,刚才有个批处理任务跑了一下,现在已经释放了。

你被”狼来了”叫醒了。

这就是告警疲劳(Alert Fatigue)。

今天这篇文章,我们来聊聊如何优化告警通知,让真正重要的问题能够及时通知,同时过滤掉那些”噪音”告警。

问题背景:告警疲劳的典型场景

场景一:阈值触发导致的告警风暴

某个服务的 CPU 使用率告警阈值设置为 80%。当服务负载升高时,CPU 从 75% 逐渐上升到 85%,这个过程可能持续几分钟到几十分钟。

在这段时间内,监控系统会持续发送告警:

  • CPU > 80% → 告警
  • CPU > 82% → 告警
  • CPU > 85% → 告警
  • CPU > 87% → 告警
  • CPU > 90% → 升级告警

五分钟后,CPU 恢复正常,告警又来一波”恢复通知”。

一个持续五分钟的负载峰值,产生了十几条告警通知。

这不是在告警,这是在轰炸。

场景二:服务重启导致的暂时性告警

某个服务需要重启。重启过程中:

  • 服务暂时不可用 → 触发”服务不可用”告警
  • 健康检查失败 → 触发”健康检查失败”告警
  • 进程重新启动 → 再次触发”服务启动”告警
  • 服务恢复正常 → 触发”恢复”告警

一个正常的重启操作,产生了四条以上的告警。

场景三:网络抖动导致的误报

某节点因为网络设备偶发性抖动,短暂失去了连接。丢包率从 0% 跳到 5%,延迟从 50ms 跳到 200ms。

这个抖动持续了 30 秒,然后网络就恢复正常了。

但告警系统已经向你的手机发送了:

  • “节点连接异常”
  • “延迟过高”
  • “丢包率异常”
  • “连接恢复”

四条告警,但你什么事都不用做,因为网络自己好了。

这就是告警疲劳。

告警疲劳的危害

告警疲劳不只是让人烦,它有几个实际的危害:

1. 错失真正重要的告警

当你的告警列表里有大量”无意义”的告警时,真正重要的告警可能会被淹没在里面。

你会习惯性地忽略告警,因为”大部分时候都是误报”。然后某天真正出问题的时候,你也会习惯性地忽略它。

这是最危险的。

2. 影响睡眠和休息

凌晨三点被叫醒,如果告警是有意义的,那叫醒得有价值。如果告警是误报,那这一晚上的睡眠就废了。

第二天工作状态差,效率低,容易出错。出错之后又要花更多时间来弥补。

恶性循环。

3. 降低团队士气

频繁的告警轰炸会让团队成员产生”告警不敏感”。大家会觉得”告警嘛,反正都是误报,不用管”。

这种心态一旦形成,真正的告警就会被忽视。

千里之堤,毁于蚁穴。

告警优化策略

策略一:合理设置告警阈值

告警阈值不是”越小越好”。阈值设置太低,会产生大量误报。阈值设置太高,可能会错过真正的问题。

建议:设置”有意义的阈值”

什么叫”有意义的阈值”?就是当告警触发时,确实需要人工介入。

比如 CPU 使用率:

  • 60% 以下:正常,不用管
  • 60%-80%:关注,但不用处理
  • 80%-90%:告警,需要检查
  • 90% 以上:紧急,需要立即处理

但这个阈值不是死的,要根据实际情况调整。如果你的服务平时 CPU 就很高(比如 70%),那 80% 的阈值就会频繁触发。如果你的服务平时 CPU 很低(比如 20%),那 80% 的阈值就很合理。

优化方法:观察历史数据,找到”异常值”和”正常值”的分界线。

策略二:使用”for”参数避免瞬时波动

Prometheus 的告警规则支持 for 参数,意思是”持续多久才触发”。

1
2
3
4
5
6
7
8
9
10
11
groups:
- name: example
rules:
- alert: HighCPU
expr: cpu_usage > 80
for: 5m # CPU 持续 5 分钟高于 80% 才触发
labels:
severity: warning
annotations:
summary: "CPU 使用率过高"
description: "CPU 使用率已持续 5 分钟超过 80%"

这样可以过滤掉瞬时波动,只保留真正持续异常的情况。

原理:真正的问题会持续,瞬时的抖动会自动恢复。

策略三:设置告警恢复延迟

告警恢复时,不要立即发送”恢复通知”。因为有些问题可能会”好了又犯”。

1
2
3
4
5
6
7
- alert: HighCPU
expr: cpu_usage > 80
for: 5m
labels:
severity: warning
# 恢复后持续 10 分钟正常才发送恢复通知
resolve_timeout: 10m

这样可以避免”告警-恢复-告警”的震荡。

策略四:告警聚合

当多个指标同时触发告警时,不要分别发送通知,而是聚合成一个通知。

比如:

  • “服务器 A CPU 使用率 > 90%”
  • “服务器 A 内存使用率 > 90%”
  • “服务器 A 磁盘使用率 > 85%”

应该聚合为:

  • “服务器 A 多项指标异常:CPU 91%,内存 93%,磁盘 87%”

这样可以减少通知数量,同时让运维人员对整体情况有更清晰的认识。

策略五:分级通知

不是所有告警都需要立即处理。根据严重程度,设置不同的通知方式:

紧急(Critical)

  • 立即发送通知(电话、短信)
  • 持续通知,直到有人响应
  • 升级机制:5 分钟无人响应,自动升级

警告(Warning)

  • 发送普通通知(钉钉、邮件)
  • 不持续通知
  • 可以稍后处理

信息(Info)

  • 记录日志
  • 不发送即时通知
  • 可以周报统计
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- alert: ServiceDown
expr: up == 0
for: 1m
labels:
severity: critical
annotations:
summary: "服务不可用"
description: "服务已停止运行超过 1 分钟"

- alert: HighMemory
expr: memory_usage > 85
for: 10m
labels:
severity: warning
annotations:
summary: "内存使用率偏高"
description: "内存使用率持续偏高,建议关注"

OpenClaw 通知优化配置

配置通知静默规则

OpenClaw 支持设置静默规则,在特定时间段内不发送某些告警:

1
2
3
4
5
6
7
8
notification:
silence:
# 维护时间段内静默告警
- name: maintenance-window
start: "2026-05-15 22:00:00"
end: "2026-05-16 06:00:00"
match:
severity: warning # 只静默 warning,不静默 critical

配置告警聚合规则

1
2
3
4
5
6
7
8
notification:
group:
# 按标签聚合,同一个实例的告警聚合在一起
group_by: ['alertname', 'instance']
# 聚合间隔:5分钟内相同告警只发送一次
group_interval: 5m
# 初始通知等待时间
initial_interval: 30s

配置分级通知渠道

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
notification:
routes:
# critical 告警发送给所有人
- match:
severity: critical
receiver: 'critical-team'
continue: true # 继续匹配后续规则

# warning 告警只发送给值班人员
- match:
severity: warning
receiver: 'oncall-team'

# info 告警只记录,不通知
- match:
severity: info
receiver: 'log-only'

receivers:
- name: 'critical-team'
webhook:
- url: 'http://notification-service/critical'
send_resolved: true

- name: 'oncall-team'
webhook:
- url: 'http://notification-service/oncall'
send_resolved: true

- name: 'log-only'
# 不发送通知,只记录

实战:告警优化配置示例

示例一:CPU 告警优化

原始配置

1
2
3
4
5
- alert: HighCPU
expr: cpu_usage > 80
for: 0m # 立即触发
labels:
severity: warning

优化后

1
2
3
4
5
6
7
8
- alert: HighCPU
expr: cpu_usage > 80
for: 5m # 持续 5 分钟才触发
labels:
severity: warning
annotations:
summary: "CPU 使用率偏高"
description: "CPU 使用率已持续 5 分钟超过 80%,当前值:{{ $value }}%"

优化效果

  • 过滤掉瞬时波动(比如 30 秒的峰值不会触发告警)
  • 只保留真正”持续”的问题

示例二:服务健康检查告警优化

原始配置

1
2
3
4
5
- alert: HealthCheckFailed
expr: health_check_status == 0
for: 0m
labels:
severity: warning

优化后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- alert: HealthCheckFailed
expr: health_check_status == 0
for: 2m # 持续 2 分钟才触发
labels:
severity: warning
annotations:
summary: "健康检查失败"
description: "健康检查持续失败,可能服务存在异常"

# 新增:服务启动中的静默规则
- alert: ServiceStarting
expr: health_check_status == 0 and uptime < 5m
for: 0m
labels:
severity: info # 降级为信息级别
annotations:
summary: "服务启动中"
description: "服务刚启动,健康检查尚未通过,这是正常的"

优化效果

  • 服务重启时不会触发告警(因为有 for: 2m,但重启只需要几秒钟)
  • 如果服务真的出问题,2 分钟后才会告警

示例三:网络延迟告警优化

原始配置

1
2
3
4
5
- alert: HighLatency
expr: latency > 1000
for: 0m
labels:
severity: warning

优化后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- alert: HighLatency
expr: latency > 1000
for: 3m # 持续 3 分钟才触发
labels:
severity: warning
annotations:
summary: "延迟过高"
description: "网络延迟持续超过 1 秒,可能存在网络问题"

- alert: LatencySpike
expr: latency > 2000
for: 0m # 瞬时高延迟还是要告警
labels:
severity: critical
annotations:
summary: "延迟骤增"
description: "延迟突然升高到 2 秒以上,可能是网络故障"

优化效果

  • 普通的延迟波动会被过滤(3 分钟持续高延迟才会告警)
  • 严重的延迟骤增会立即告警(2 秒以上说明问题很严重)

一键优化脚本

为了方便快速优化告警配置,我写了一个一键检查脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#!/bin/bash
# alert-optimization-check.sh

echo "=== OpenClaw 告警优化检查脚本 ==="
echo ""

# 检查告警规则数量
echo "1. 检查告警规则数量..."
ALERT_COUNT=$(find /etc/openclaw/rules -name "*.yml" -exec grep -l "alert:" {} \; 2>/dev/null | wc -l)
echo " 告警规则文件数:$ALERT_COUNT"
echo ""

# 检查告警的 for 参数
echo "2. 检查缺少 for 参数的告警..."
MISSING_FOR=$(grep -r "alert:" /etc/openclaw/rules/ 2>/dev/null | awk '/alert:/{p=1} p && /for:/?{next} /---/{p=0} p' | grep -v "for:" | head -5)
if [ -z "$MISSING_FOR" ]; then
echo " ✓ 所有告警都配置了 for 参数"
else
echo " ✗ 以下告警缺少 for 参数:"
echo "$MISSING_FOR"
fi
echo ""

# 检查告警阈值分布
echo "3. 检查告警阈值分布..."
grep -r "expr:" /etc/openclaw/rules/ 2>/dev/null | awk -F'>' '{print $NF}' | sed 's/[[:space:]]//g' | sort | uniq -c | sort -rn | head -10
echo ""

# 检查通知配置
echo "4. 检查通知静默配置..."
SILENCE_COUNT=$(grep -c "silence:" /etc/openclaw/notification.yml 2>/dev/null || echo "0")
echo " 已配置的静默规则数:$SILENCE_COUNT"
echo ""

# 检查告警聚合配置
echo "5. 检查告警聚合配置..."
GROUP_INTERVAL=$(grep "group_interval:" /etc/openclaw/notification.yml 2>/dev/null | head -1)
if [ -z "$GROUP_INTERVAL" ]; then
echo " ✗ 未配置告警聚合,建议添加 group_interval"
else
echo " ✓ $GROUP_INTERVAL"
fi
echo ""

# 提供优化建议
echo "=== 优化建议 ==="
echo ""
echo "1. 如果告警数量过多,建议:"
echo " - 提高告警阈值,减少误报"
echo " - 增加 for 参数,过滤瞬时波动"
echo " - 设置告警聚合,减少通知数量"
echo ""
echo "2. 如果告警通知太频繁,建议:"
echo " - 配置静默规则,在维护时间不通知"
echo " - 配置告警聚合,合并同类告警"
echo " - 设置分级通知,区分紧急和一般告警"
echo ""
echo "3. 推荐的告警配置:"
echo " - for: 5m(持续 5 分钟才触发)"
echo " - group_interval: 5m(5 分钟内同类告警合并)"
echo " - resolve_timeout: 10m(恢复后 10 分钟才发恢复通知)"
echo ""

echo "=== 检查完成 ==="

常见问题解答

Q:告警太多了,怎么快速定位哪些是”噪音”?

A:观察历史告警数据,统计每个告警的触发频率和持续时间。频繁触发但持续时间短的告警,大概率是误报。

Q:for 参数设置多长比较合适?

A:取决于指标特性。CPU、内存建议 5 分钟;网络延迟建议 3 分钟;服务健康检查建议 2 分钟。

Q:有些告警是”正常操作”导致的,比如服务重启,怎么避免?

A:配置”白名单”规则。比如服务刚启动时(uptime < 5m)的健康检查失败,不算真正的告警,可以降级为信息级别。

Q:告警恢复通知要不要发?

A:建议发,但要有延迟(resolve_timeout)。这样可以避免”告警-恢复-告警”的震荡。

Q:告警太多处理不过来怎么办?

A:分级处理。critical 立即处理,warning 可以稍后处理,info 记录日志即可。

最佳实践总结

1. 告警阈值设置原则

  • 宁可少报,不要误报:误报会让人忽视真正的问题
  • 设置有意义的阈值:触发时必须需要人工介入才告警
  • 观察历史数据:根据实际情况调整阈值

2. 告警触发配置原则

  • 使用 for 参数:避免瞬时波动触发告警
  • 合理设置 for 时长:5 分钟是经验值,可根据实际情况调整
  • 区分严重程度:critical 立即触发,warning 可以等待

3. 通知管理原则

  • 告警聚合:同类告警合并发送,减少通知数量
  • 分级通知:critical 电话通知,warning 钉钉通知,info 仅记录
  • 静默规则:维护时间段内静默告警

4. 持续优化原则

  • 定期回顾告警数据:识别噪音告警,持续优化配置
  • 收集反馈:如果运维人员反馈”这个告警不用管”,那就优化它
  • 保持简单:告警规则不是越复杂越好,简单易懂才是王道

经验总结

  1. **告警的价值在于”准确性”,不在于”数量”**:一百条无意义的告警不如一条真正有用的告警
  2. 告警疲劳比告警本身更可怕:宁可少报,不要误报
  3. for 参数是过滤噪音的神器:合理使用可以大幅减少误报
  4. 告警聚合让通知更有价值:合并同类告警,让运维人员看到整体情况
  5. 分级通知让资源用在刀刃上:不是所有告警都需要立即处理

结语

告警优化的目标是:让真正重要的问题及时通知,让无意义的噪音消失不见。

好的告警系统不是”让你看到所有问题”,而是”让你只看到需要处理的问题”。

当你优化完告警配置,发现半夜的手机终于安静了,运维人员的脸上终于有微笑了,那就说明优化成功了。

告警优化的最高境界:无事发生时悄无声息,有事发生时一击必中。

希望这篇文章能帮你打造一个”精准”的告警系统。

如果你有更好的实践经验,欢迎在评论区分享。


作者:小六,一个今天终于让告警系统安静下来的技术博主

题图:Picsum Photos,授权可商用

Author:Margrop
Link:http://blog.margrop.com/post/2026-05-15-openclaw-alert-fatigue-and-notification-optimization/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可