JOTO
联系我们
← AI 智库
AI 硬件

AIOps落地:告警降噪到底怎么做?我落地了一套方案

2026 年 8 月 13 日

本文提出告警降噪“四板斧”方案:第一板斧是写对PromQL与阈值,强调平滑、for分级和相对阈值;第二板斧用Alertmanager分组与抑制规则收敛告警;第三板斧通过标签建依赖实现上下游事件聚合;第四板斧才引入AI聚类,仅处理critical级别告警,依赖标签上下文与结构化system prompt输出根因判断与处置建议。

告警降噪 90% 的工作是规则、分组、抑制,剩下 10% 才轮到 AI。今天这篇文章跟大家分享下我的方案四板斧,前三板斧跟AI没关系,全是工程事。

AIOps落地:告警降噪到底怎么做?我落地了一套方案

第一板斧:把 PromQL 和阈值写对

告警吵,一半是因为规则写得烂。三个最常见的毛病:没做平滑、没加 for、阈值拍脑袋。

拿 CPU 告警举例。磁盘使用率是"水位",慢慢爬,很少剧烈波动,设个阈值基本够用。但 CPU 是"流量",一秒一个值,瞬时冲到 90% 再掉下来是常态。直接拿原始值判断,误报能把人烦死。

看一段我改过的 CPU 告警:

groups:
  - name: node_alerts
    rules:
      - alert: CpuUsageCritical
        expr: avg by (instance) ((1 - rate(node_cpu_seconds_total{mode="idle"}[1m]) - rate(node_cpu_seconds_total{mode="iowait"}[1m])) * 100) > 95
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "{{ $labels.instance }} CPU 使用率超过 95%"
      - alert: CpuUsageHigh
        expr: avg by (instance) ((1 - rate(node_cpu_seconds_total{mode="idle"}[5m]) - rate(node_cpu_seconds_total{mode="iowait"}[5m])) * 100) > 85
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "{{ $labels.instance }} CPU 使用率持续超过 85%"

三个关键点:

1. rate 窗口,级别越高窗口越短。

CPU 使用率是计数器派生的瞬时值,一秒一个样,必须用窗口算平均把尖峰抹平。但窗口不是越大越好:warning 用 5 分钟窗口看趋势,critical 用 1 分钟窗口抓突变。级别越高,窗口越短。

2. 排除 iowait,别把等待算成忙。

node_cpu_seconds_total 按 CPU 模式拆成多个序列,idle 是空闲占比。但直接 100 减 idle,会把 iowait 也当成 CPU 忙。磁盘慢的时候,CPU 大量时间在等 IO,iowait 能到 30%,这时候报"CPU 80%"就是误报。所以公式里把 idle 和 iowait 一起减掉,剩下的才是真忙。

3. for 分级,不是一刀切。

有人会问:CPU 真爆了,业务都挂了,还等 10 分钟?问得好。所以 for 要按级别分级,看上面两条规则:critical 用 1 分钟 for,冲到 95% 一分钟就告警,快速响应;warning 用 10 分钟 for,85% 持续十分钟才告警,过滤抖动。

一套规则两条腿走路:fast 负责抓真故障,slow 负责挡假报警。哪个都不能少。

相对阈值。

负载告警别用绝对值,用 load1 除以核数:

  - alert: LoadHigh
    expr: node_load1 / count(node_cpu_seconds_total{mode="idle"}) > 0.8
    for: 15m
    labels:
      severity: warning
    annotations:
      summary: "{{ $labels.instance }} 负载达到核数的 80%"

16 核和 4 核的机器,用同一个绝对值判断负载本来就不科学。除以核数之后,所有机器一套规则,不用每台单独调。

第二板斧:Alertmanager 分组 + 抑制

规则写对之后,还有一半告警是"一个故障炸出几十条"。靠 Alertmanager 解决。

分组配置:

route:
  receiver: default
  group_by: ['alertname', 'cluster']  ## 同一个告警名、同一个集群的告警,合并成一条通知。
  group_wait: 30s  ## 等 30 秒,把同一批故障的告警攒一起再发,不一条条炸。
  group_interval: 5m 
  repeat_interval: 4h  ## 告警持续期间,4 小时才重复提醒一次。不然你睡到半夜,手机每隔 5 分钟响一次。

抑制规则,这是降噪威力最大的一块:

inhibit_rules:
  # 主机挂了,抑制这台机器上所有非 critical 告警
  - source_matchers:
      - 'alertname="NodeDown"'
    target_matchers:
      - 'severity!="critical"'
    equal: ['instance']

解释一下:一台机器 down 了,node_exporter 抓不到数据,内存、磁盘、进程、服务健康检查全部一起告警,几十条。但你真正需要处理的只有一条"这台机器挂了"。这条抑制规则的效果:NodeDown 一旦触发,这台 instance 上所有非 critical 的告警全部闭嘴。

就这么一条规则,最狠的告警风暴直接按住。

第三板斧:用标签建依赖,把告警聚成事件

再往前走一步,是事件关联。

一个核心服务挂了,下游几十个服务跟着告警。你要做的不是去点几十条,而是让它们聚成一个事件。

实现方式不复杂,先给所有告警打上统一的 cluster 和 service 标签,然后在抑制规则里做上下游抑制:

  # 上游 service 挂了,抑制下游所有依赖它的告警
  - source_matchers:
      - 'alertname="ServiceDown"'
      - 'severity="critical"'
    target_matchers:
      - 'severity!="critical"'
    equal: ['service']

注意这里的 equal 用的是 service,不是 cluster。如果 equal 写成 cluster,同一集群里 A 服务挂了,B 服务的告警也会被一起误抑制。只有当你确认"集群内服务强依赖、挂了会一起挂",才用 cluster。

值日的人看到的就不再是"50 条告警",而是"1 个事件:XX 服务异常,连带 40 个下游告警已抑制"。

这一步做完,告警量基本能降八九成。

第四板斧:AI 聚类,最后才上

前三板斧做完,告警量已经降了八九成。剩下的漏网之鱼,才轮到 AI。

AI 干两件事:把长得不一样但本质同一个根因的告警聚成一类,再对每个事件给根因判断和处理建议。

但这里有个关键问题:告警怎么给到 AI?

事件驱动:让 Alertmanager 在告警触发时,通过 webhook 主动推给一个分析服务,告警一到就分析。数据流是这样的:

Alertmanager 触发 → webhook POST 到分析服务 → 格式化 → 调 LLM → 返回聚类结果

第一步,配 Alertmanager。 加一个专门的 webhook receiver,把告警路由到 AI 分析:

route:
  receiver: default
  group_by: ['alertname', 'cluster']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  routes:
    - matchers:
        - severity="critical"
      receiver: ai-analysis
receivers:
  - name: default
    webhook_configs:
      - url: http://your-ops/webhook/dingtalk
  - name: ai-analysis
    webhook_configs:
      - url: http://your-service:8080/webhook/alerts
        send_resolved: false

注意这里的路由只匹配 severity="critical",warning 不会喂给 AI。这是故意的:AI 分析要烧 token,warning 级别的漏网之鱼靠人工和报表兜底就行,不值得每次花这个钱。真正需要快速响应的,只有 critical。

这里有个巧妙的点:Alertmanager 的 group_wait 已经帮我们把同一批告警攒在一起了。它等 30 秒,把同组的告警聚成一批,一次性 POST 给 webhook。所以你的分析服务拿到的,天然就是"一个故障的一批告警",不用自己再做聚合。

第二步,写分析服务的 webhook。 收到 POST,格式化,调 LLM,把结果发到值班群:

from flask import Flask, request
import requests
app = Flask(__name__)

def send_to_dingtalk(content):
    # 发到钉钉值班群,换成你们自己的机器人地址
    requests.post(
        "https://oapi.dingtalk.com/robot/send?access_token=你的token",
        json={"msgtype": "text", "text": {"content": content}},
    )

@app.post("/webhook/alerts")
def handle_alerts():
    data = request.json
    firing = [a for a in data["alerts"] if a["status"] == "firing"]
    if not firing:
        return "ok", 200
    # 格式化告警成文本
    lines = []
    for i, a in enumerate(firing, 1):
        labels = a["labels"]
        lines.append(
            f"告警{i}:{labels.get('alertname')} | "
            f"级别:{labels.get('severity')} | "
            f"实例:{labels.get('instance')} | "
            f"集群:{labels.get('cluster')} | "
            f"服务:{labels.get('service')} | "
            f"开始:{a.get('startsAt')} | "
            f"描述:{a.get('annotations', {}).get('summary', '')}"
        )
    user_prompt = f"当前有 {len(firing)} 条告警正在触发:\n" + "\n".join(lines)
    # 调 LLM
    result = requests.post(
        "https://api.deepseek.com/v1/chat/completions",
        headers={"Authorization": "Bearer 你的key"},
        json={
            "model": "deepseek-chat",
            "messages": [
                {"role": "system", "content": SYSTEM_PROMPT},
                {"role": "user", "content": user_prompt},
            ],
            "temperature": 0.2,
        },
    )
    analysis = result.json()["choices"][0]["message"]["content"]
    send_to_dingtalk(analysis)
    return "ok", 200

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8080)

关键点:一定要把 labels 里的集群、服务、实例带上。 AI 聚类靠的就是这些上下文。没有集群和服务标签,AI 分不清哪些告警在同一条链路上,聚类就是瞎分。

System Prompt 是核心:

你是一个资深 SRE 告警分析师。我会给你一批当前正在触发的告警,每条包含告警名、级别、实例、集群、服务、开始时间和描述。

请执行以下分析:
1. 把这批告警聚类成事件,判断哪些告警属于同一个根因。
2. 对每个事件,给出最可能的根因判断,并说明推理依据。
3. 给出处理建议,按优先级排序。
4. 用 JSON 格式输出,包含字段:event_id、root_cause、alerts、severity、action。

AI 返回的 JSON 长这样:

{
  "events": [
    {
      "event_id": "event-1",
      "root_cause": "api 服务所在宿主机 CPU 饱和,导致健康检查超时",
      "alerts": ["CpuUsageHigh", "ServiceDown", "HealthCheckFailed"],
      "severity": "critical",
      "action": "先排查宿主机 CPU 占用进程,或对 api 服务扩容"
    }
  ]
}

这下值班的人看到的不是几十条告警,而是一个结论:根因是什么、先处理什么。

注意边界:AI 聚类基于的是 labels 和描述文本,它只能做"归类"和"根因推测",不能替代真实故障的最终判断。 但它能把几十条告警收敛成一个事件加一个建议,这就够了。

这里还有个天生短板:webhook 是按组触发的,同一批 group 内的告警能聚在一起,但跨组的关联它看不到。

比如磁盘慢导致 MySQL 慢查询超时,再导致订单服务告警,三组告警会分三次 POST 进来,各分析各的,聚不成一个根因。要跨组聚类,得定期全量拉一遍所有告警做二次聚合,代价是回到轮询。这就是事件驱动和完整聚类的取舍,先知道它做不到什么,才知道怎么用它。

告警降噪做到最后,你会发现 90% 是工程问题,AI 只负责最后 10%。先把规则写对,把分组配好,把抑制建起来。这些事不做,AI 救不了你。

JOTO 企业落地观察

  • 企业部署告警降噪系统时,必须将规则工程能力前置——PromQL编写质量、Alertmanager分组抑制策略、标签体系设计,构成AI介入前的刚性门槛。AI聚类无法弥补上游数据治理缺陷,团队需优先投入SRE规范建设而非直接采购AI模块。
  • 这类系统的取舍核心在于事件驱动与全量聚合的权衡:Alertmanager webhook机制天然支持低延迟、轻量级的单组告警分析,但无法跨组溯源;若强行要求完整根因链路,则需引入轮询+全量存储架构,显著增加运维复杂度与成本。企业应根据MTTR目标与故障模式分布选择折中点。
  • RAG知识工程在此场景中作用有限,因告警文本高度结构化且语义稀疏,LLM更依赖预定义标签(如cluster/service/instance)而非自然语言描述。企业若想提升AI分析准确率,应聚焦于标签治理体系标准化,而非堆砌文档向量库。
  • AI安全治理需关注LLM输出的可解释性边界:当前方案明确限定AI仅输出JSON结构化建议,不替代人工决策。企业须建立校验机制,例如将AI推荐action与CMDB拓扑、变更记录交叉比对,防止模型幻觉引发误操作。

立即咨询 JOTO

JOTO 提供覆盖企业智能体规划与搭建、AI 平台私有化部署、RAG 知识工程、AI 安全治理、FDE 驻场共创及持续运营优化的全周期 AI 落地服务,帮助企业把验证中的 AI 能力转化为安全、可控、可持续迭代的生产力。 联系 JOTO 获取 AI 落地咨询

想把这些做法用到你的业务里?

留下你的场景和痛点,我们帮你判断从哪一步开始。

联系我们
联系我们

开启企业级 AI 落地

留下你的行业、部门和当前痛点,我们会在 1 个工作日内与你联系,帮你判断适合先做什么、需要准备哪些数据、适合什么平台。

微信咨询
扫码添加,一对一沟通
JOTO 微信咨询二维码
发送邮件
jotoai@jototech.cn

填写需求单

收到你的信息后,我们将在 1 个工作日内与你取得联系。