告警发出来之后,自动查根因的神器来了
❝
TL;DR:大多数监控系统只负责告诉你”坏了”,但真正耗时的是后面的根因排查。catpaw 想补上的不是又一套 dashboard,而是另一段链路:插件发现异常,事件引擎做去重和告警控制,AI 在告警触发后自动调用 70+ 诊断工具做第一轮根因分析,再把结构化报告跟告警一起送到你的值班链路里。
catpaw 新鲜开源,项目地址:https://github.com/cprobe/catpaw 欢迎关注收藏。
如果想加入微信交流群,可以加我好友:
picobyte,我拉你进群。不过大概率是不需要的,因为 AI 时代了,让 AI 探索一下代码,可以回答任何你想问的问题。
凌晨 3 点,你收到一条再普通不过的告警
手机亮了。
[Critical] disk::space_usage target=/ disk usage 97.2% >= critical threshold 95.0%
这条告警当然有用。至少你知道根分区快满了。
但它只解决了值班流程里最容易的一步:发现有问题。
真正耗时的部分是后面这些:
-
是哪个目录涨起来了? -
是日志没轮转,还是 core dump 堆积? -
inode 也快满了吗? -
这是一次性峰值,还是会持续恶化? -
我现在该先删文件、先扩容,还是先止血?
于是你开始 SSH 上机:
df -hdf -idu -sh /* 2>/dev/null | sort -rh | headdu -sh /var/* 2>/dev/null | sort -rh | headlsof +L1 | head
如果这是磁盘问题,还算有路径。
如果告警换成 conntrack usage 92%、ListenOverflows持续增长、CLOSE_WAIT破千,排查链路会更长,命令也更散。更麻烦的是,很多时候值班的人并不是最熟 Linux 内核细节的那位。
大多数告警系统做到这里就停了。
它们负责把异常抛给你,却不负责把这条异常往根因推进一步。
一条告警,通常只完成了故障处理的前 20%
为什么值班体验常常很差?
不是因为没有告警。
而是因为告警和排障之间有一段没人接住的真空区。
可以把故障处理粗暴分成三层:
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
也就是说,很多系统其实只回答了:
❝
“是的,坏了。”
但值班时真正需要的是:
❝
“为什么坏?先查哪里?有没有明显的高概率根因?”
这不是吹毛求疵,而是 On-call 成本的核心。
一条没有上下文的告警,意味着:
-
值班人要自己补充上下文 -
经验不足的人会走很多弯路 -
交接时只能靠口头描述 -
告警越多,人越麻木
所以更合理的问题不是”要不要告警”,而是:
告警发出来之后,系统能不能顺手完成第一轮排查?
一个真正可用的告警闭环,至少要有 6 个环节
如果你想让监控系统不只会”报错”,而是能把人从机械排查里解放一点,它至少要补齐下面这条链路:
1. 先发现异常
这一步是传统监控的强项。
比如磁盘使用率超过阈值、conntrack 表快满、NTP 漂移过大、systemd 服务挂掉,先把这些异常稳定地发现出来。
2. 把异常变成标准化事件
如果每个插件、每个脚本、每个团队都输出自己的格式,后面根本无法做统一处理。
事件里至少要有:
-
check 是什么 -
target 是谁 -
当前值是多少 -
阈值是什么 -
严重级别是什么
3. 做掉那些会把人淹死的噪音
没有去重、抑制、聚合,AI 诊断也没法做。
因为同一个目标在几秒内可能连续打出多条关联告警:
-
磁盘空间高 -
inode 高 -
writable 失败 -
日志关键字异常
如果每条都单独跑一遍重诊断,只会放大噪声和成本。
4. 根据异常上下文自动选择诊断动作
磁盘告警该看目录占用、inode、日志、deleted-but-open file。
conntrack 告警该看当前计数、上限、丢包证据、相关内核参数。
ListenOverflow 告警该看 backlog、队列溢出计数、socket 分布、TCP 调优项。
这一步如果没有工具体系,AI 很容易沦为”会说话的猜测器”。
5. 产出结构化报告
不是一堆原始命令输出,而是能直接被人拿去决策的结果:
-
问题概要 -
高概率根因 -
关键证据 -
建议动作
6. 报告要回到值班链路里
如果诊断结论只躺在某个本地终端里,还是没有意义。
真正有用的方式是:告警发出去之后,诊断报告也作为新事件进入同一条通知链路。
这样值班人打开手机,不只看到”坏了”,还能看到”大概率为什么坏了”。
catpaw 补的,就是这段从告警到根因之间的链路
catpaw 的定位从一开始就不是指标采集器,而是一个轻量的 check 型 Agent,加上一段 AI 驱动的诊断闭环。
如果把链路画简单一点,大概是这样:
插件检查 -> 标准化事件 -> 告警判定/去重/重复控制 -> 发送通知 -> 触发 AI 诊断 -> 调用内置诊断工具 -> 生成结构化报告 -> 报告再次发送到通知渠道
这条链路里有几个点是比较关键的。
1. 检查插件负责”发现异常”
catpaw 现在已经有 25+ 个检查插件,覆盖的不是一堆泛泛的 metrics,而是更贴近故障的风险点:
-
disk:空间、inode、可写性 -
conntrack:连接跟踪表使用率 -
tcpstate:CLOSE_WAIT / TIME_WAIT -
sockstat:listen 队列溢出 -
sysctl:关键内核参数漂移 -
procfd/filefd:进程级和系统级 fd 耗尽 -
systemd:服务状态 -
redis:单机、主从、集群 Redis 的关键健康项
这和”先把所有指标采上来,回头再想怎么告警”是两种思路。
它更接近 SRE 真正在值班中关心的问题:有没有已经构成故障的信号。
2. 事件引擎负责”别把人和模型一起吵死”
告警不是直接裸发的。
catpaw 的事件引擎会先做一轮事件处理,包括:
-
标准化字段 -
计算 AlertKey -
for_duration持续确认 -
repeat_interval/repeat_number控制重复通知 -
恢复通知
这一步的价值很实际:
-
避免抖动告警频繁触发 -
避免同一个问题一分钟提醒十次 -
给后面的诊断环节一个相对稳定的触发点
3. 诊断前先做聚合,不是每条告警都单独查
catpaw 在告警真正送出后,才会判断是否触发 AI 诊断。
而且不是每来一条就立刻查一次,而是会把同一目标的多个关联告警放进一个短窗口里聚合,再统一提交给诊断引擎。
这非常重要。
因为真实故障往往不是单点症状:
-
某个盘满了,同时 inode 也高 -
某个服务连接泄漏,同时 CLOSE_WAIT 和 fd 使用率一起涨 -
某个节点网络出问题,同时 ping、TCP、日志关键字一起异常
聚合之后再诊断,模型拿到的是一组更接近真实故障面的上下文,而不是一条孤零零的告警。
4. AI 不是胡猜,而是调工具
这是 catpaw 和很多”AI 告警摘要”类产品最大的差别。
它不是把一条告警文本扔给模型,让模型凭空写一段漂亮但没证据的话。
它背后有一套 70+ 的诊断工具箱,覆盖:
-
CPU / 内存 / OOM / PSI -
磁盘空间 / I/O / block device / LVM -
DNS / ping / traceroute / TCP 状态 / 重传 -
进程线程 / open files / environment / cgroup -
dmesg / journald / 日志 grep -
conntrack / firewall / sysctl / SELinux / AppArmor -
Docker / systemd
如果你接了 MCP,还可以继续查 Prometheus、Jaeger、CMDB 这类外部上下文。
所以它做的是:
❝
告警触发 -> 带上下文调用工具 -> 基于证据生成第一轮诊断
而不是:
❝
看到告警文本 -> 语言模型自由发挥
用一个磁盘场景看,”闭环”到底长什么样
还是看那个最常见的场景:根分区满了。
传统告警通常停在这里
[Critical] disk::space_usage target=/ disk usage 97.2% >= critical threshold 95.0%
它告诉你现象,但没告诉你原因。
如果靠人工,通常要做这些
df -hdf -idu -sh /* 2>/dev/null | sort -rh | headdu -sh /var/* 2>/dev/null | sort -rh | headlsof +L1 | head
然后你再从这些原始输出里人工提炼判断。
catpaw 更理想的结果应该是这样
告警发出去后,再跟一份结构化诊断报告:
## 诊断报告### 问题概要/ 分区使用率 97.2%,超过 Critical 阈值 95.0%。### 高概率根因- /var/log/app/access.log 占用 25.3GB,最近持续增长- 目标路径未配置 logrotate- /tmp 下存在多个 core dump,共计 8.2GB### 关键证据- 根分区总量 50GB,已用 47GB- inode 使用率正常,不是小文件过多- 未发现明显 deleted-but-open file### 建议动作1. 先清理 core dump 和无用日志,尽快止血2. 为 /var/log/app/*.log 配置日志轮转3. 如果业务量持续增长,考虑把日志迁移到独立分区
这份报告未必 100% 正确,但它已经把值班动作从:
❝
“我要先想想该跑什么命令”
推进成了:
❝
“我先验证这几个高概率点”
这对值班效率的提升非常实在。
再看一个更典型的 SRE 场景:conntrack 表快满
磁盘满的问题,大多数人多少还有经验。
conntrack 就不一样了。
很多团队线上出了问题,第一反应还是:
-
服务是不是挂了 -
网络是不是抖了 -
对端是不是超时了
但 conntrack 满的时候,真实现象常常是:
-
新连接静默失败 -
客户端看到的是 timeout -
服务端进程一脸无辜 -
Grafana 四大金指标一片正常
如果告警只写:
[Critical] conntrack::usage target=host nf_conntrack usage 92% >= 90%
那接下来还是得靠值班人自己联想:
-
当前条目数和上限分别是多少 -
最近是不是已经出现过 dropped packet -
机器角色是不是 NAT 网关 / K8s 节点 / 高并发入口 -
是不是应该立刻提 nf_conntrack_max
这就是为什么我觉得 SRE 更应该关心的,不是”AI 会不会写报告”,而是:
系统能不能把排障路径往前推一段。
对于 conntrack 这种问题,哪怕只帮你自动补出下面这些证据,价值都很高:
-
当前 nf_conntrack_count / nf_conntrack_max -
是否接近硬上限 -
是否出现 table full, dropping packet -
近期网络超时是否和该节点集中相关
对值班人来说,这已经不是”文案优化”,而是实际减少误判。
这件事为什么以前难做
看起来像一句很自然的话:
❝
“告警之后顺手查一下不就好了。”
但工程上真做起来并不简单。
1. 不是每条告警都值得深查
如果没有聚合、冷却、并发控制,系统很容易在告警风暴里把自己拖死。
catpaw 这里有几层保护:
-
聚合窗口:把同一目标的关联告警合起来 -
cooldown:同一目标短时间内不要重复诊断 -
并发上限:同时跑的诊断数量可控 -
工具超时:避免单个工具卡死整个流程
2. 没有工具体系,AI 很容易幻觉
只给模型一条告警文本,生成出来的大概率只是”看起来合理”。
真正可靠的是:
-
给它明确的工具目录 -
给它具体的告警上下文 -
限制它通过可复现的工具拿证据
3. 诊断动作必须安全
值班诊断不等于自动修复。
大部分诊断动作应该是只读的;如果真要执行 shell,也应该先征得确认。
否则系统很容易从”自动排障”滑向”自动闯祸”。
4. 结果必须回到同一条值班链路
如果告警在 PagerDuty,诊断报告在 SSH 终端,流程还是断的。
值班系统真正需要的是:
-
一条原始告警 -
一条可追溯的诊断报告 -
两者都能进入同一通知渠道
只有这样,闭环才成立。
在 catpaw 里,最小化体验这件事并不复杂
如果你只是想感受一下”告警后自动诊断”是什么体验,最简单的方式就是用默认 console 通知加一个容易触发的插件先跑起来。
1. 先保留默认 console 输出
conf.d/config.toml默认已经开了:
[notify.console]enabled = true
这意味着你不需要先接 Flashduty、PagerDuty 或 WebAPI,就能在终端里看到事件。
2. 打开 AI 诊断
可以先按最小配置开启:
[ai]enabled = truemodel_priority = ["gpt4o"]aggregate_window = "2s"[ai.models.gpt4o]base_url = "https://api.openai.com/v1"api_key = "${OPENAI_API_KEY}"model = "gpt-4o"
3. 选一个适合演示的插件
比如 disk插件本身就很适合展示”从告警到根因”:
[[instances]][instances.space_usage]warn_ge = 90.0critical_ge = 99.0[instances.alerting]for_duration = 0repeat_interval = "5m"repeat_number = 3[instances.diagnose]enabled = true
如果你更想展示 Linux 内核层问题,也可以直接用 conntrack:
[[instances]][instances.conntrack_usage]warn_ge = 75.0critical_ge = 90.0interval = "30s"[instances.alerting]for_duration = 0repeat_interval = "5m"repeat_number = 0
4. 先在测试机上故意制造一个容易触发的场景
比如:
-
把某个阈值临时调低 -
或在测试环境制造少量磁盘占用
然后启动:
./catpaw run
你看到的就不应该只是一条原始异常,而应该是:
-
原始告警事件 -
稍后跟上的诊断报告事件
如果你愿意进一步验证工具层的可靠性,还可以直接跑:
./catpaw selftest
这会对本地诊断工具做一轮冒烟测试。
真正值得推广的,不是”AI”三个字,而是值班成本下降
我觉得 catpaw 如果要打动 SRE / DEV,重点不该是”我们用了 AI”。
因为 SRE 真正关心的从来不是模型名,而是这些更朴素的问题:
-
这东西能不能少让我 SSH 几次 -
能不能帮经验不足的人少走弯路 -
能不能把值班信息交接得更完整 -
能不能减少那种”知道坏了,但不知道先查哪”的空转时间
如果一套系统只能告诉你”磁盘 97%”、”CLOSE_WAIT 2000″、”conntrack 92%”,那它只是把问题转交给了人。
如果它还能把证据、上下文、第一轮根因判断一起发出来,它才开始真正参与故障处理。
告警不是终点。
对值班人来说,根因初筛才是真正开始产生价值的地方。
最后给一份可以带走的 checklist
如果你想判断自己的监控体系是不是还停留在”只会报警”阶段,可以快速过一遍这几个问题:
-
告警触发后,值班人是否还要手工补齐大部分上下文? -
同一故障是否会在几秒内打出多条互相有关但彼此割裂的告警? -
你的值班通知里,是否只有”现象”而几乎没有”证据”? -
遇到内核层、网络层、fd、队列、sysctl 这类问题时,是否仍严重依赖少数资深同学? -
你们的值班链路里,是否还缺少”异常发现之后的第一轮根因分析”?
如果这些问题里有几个答案是”是”,那你缺的可能就不是更多 dashboard,而是这段从告警到根因之间的闭环。
夜雨聆风