第3章 告警源接入:常见监控系统(Prometheus、Zabbix等)的对接

这一章我们聊聊告警源接入。说白了,就是让你的告警平台能听懂不同监控系统在说什么。

Prometheus、Zabbix 这些大家伙,各有各的脾气。我最早做接入的时候,以为随便配个 webhook 就行了,结果被重复告警报文淹了好几次。嗯,今天咱们就把这事掰开揉碎讲清楚。

3.1 为什么需要统一的告警源接入层?

你想想看,一个运维团队往往同时用着好几套监控。Prometheus 盯容器,Zabbix 看传统设备,可能还有自研监控。如果让它们各自直接发告警,格式五花八门——有的是 JSON,有的是 XML,有的直接塞一行文本。

统一接入层的作用就是:收口、解析、去重、打标签。收进来之后,所有告警长一个样,后端处置逻辑才能跑得顺。

个人习惯:我一般会在接入层做一次“告警指纹”计算。把告警类型、资源、时间窗口散列成一个 uid,用来判断是不是同一条告警的重复推送。这个在 Prometheus 的重复告警场景下特别管用。

3.2 Prometheus + Alertmanager 对接

Prometheus 本身不直接发告警,它把规则命中推给 Alertmanager。所以我们的对接点就是 Alertmanager 的 webhook receiver。

3.2.1 配置 webhook receiver

在 alertmanager.yml 里加一个 receiver,指定目标 URL。下面是一个我常用的模板:

# alertmanager.yml 片段
receivers:
  - name: 'ops-receiver'
    webhook_configs:
      - url: 'http://你的告警平台/api/v1/alerts'
        send_resolved: true
        http_config:
          basic_auth:
            username: 'admin'
            password: 'your-pass'
        # 注意:timeout 默认 10s,如果告警平台处理慢,调大
        timeout: 30s

这个配置会把所有告警(包括恢复告警)以 POST 请求发过来。send_resolved: true 这句我建议一直开着,不然告警恢复事件丢了,你的闭环就断了。

3.2.2 路由规则怎么设?

Alertmanager 的 route 规则很灵活。我一般按严重级别分流:

  • critical / warning 走不同 receiver 或者不同标签
  • 用 repeat_interval 控制重复推送频率,默认 4h 太长了,我通常改成 30m
  • 组告警(group_by)别设太细,否则同一个问题的多条告警变成一堆独立请求,后续去重很头疼
曾经踩过的坑:有一回我把 group_by 设成了 instance + alertname,结果同一个 IP 上的 CPU 和内存告警变成了两条独立告警,而且因为时间差它们各自走进了不同的告警组,导致告警平台收到了两条近乎一样的时间戳。后来改成 group_by: ['namespace'],问题解决。

3.3 Zabbix 对接

Zabbix 的告警推送主要通过 Actions -> Media types 做。早期版本只能用脚本,6.0 以后原生支持 webhook media type。

3.3.1 配置 Webhook Media Type

进入 Administration → Media types → Create media type,选 Type = Webhook。请求参数要自己构造:

  • URL: 你的告警平台接口
  • HTTP method: POST
  • Body 模板(用 Zabbix 的 macro):{ALERT.MESSAGE} {ALERT.SUBJECT} 等
  • Content-Type: application/json

我一般习惯把整个告警序列化成 JSON 发出去,方便后端直接用:

// Zabbix Webhook 的 Parameter 设置示例
key: "payload"
value: '{"eventid":"{EVENT.ID}","severity":"{EVENT.SEVERITY}","host":"{HOST.NAME}","trigger":"{TRIGGER.NAME}","time":"{EVENT.DATE} {EVENT.TIME}","message":"{ALERT.MESSAGE}"}'

注意:Zabbix 的 macro 解析是在发送时做的,所以参数值里不能用双引号包 macro,否则会报错。我以前调了半小时才发现。

3.3.2 动作绑定

然后去 Configuration → Actions → Create action,绑定这个 media type,并设定触发条件(比如 severity ≥ warning)。这样就实现了 Zabbix 告警到统一平台的推送。

3.4 两种方式对比

对比维度 Prometheus (+ Alertmanager) Zabbix
推送方式 原生 webhook,配置简单 脚本或 Webhook media type,6.0 后更易用
告警分组 内置 group_by, 重复抑制强 通过事件相关设置,稍显繁琐
恢复通知 自动发送 resolved 事件 需在 action 里单独配恢复操作
认证 支持 basic_auth / bearer 放在 URL 或 Header 中,需手动拼接
常见坑 重复告警、组内时序乱序 Macro 解析转义、触发频率控制

3.5 告警标准化——打通最后一公里

不管从 Prometheus 还是 Zabbix 进来的告警,到咱们平台后都应该变成统一结构。我通常定义一个标准告警模型:

  • source:识别是哪个监控系统
  • alert_name:告警标题
  • severity:严重等级,统一转成 P0/P1/P2/P3
  • resource:受影响的主机或服务
  • starting_time:告警产生时间
  • status:firing / resolved
  • raw_data:原始告警体,留着备查
小建议:在接入层做一次时区统一。有些监控用 UTC,有些用本地时间,如果你不把时间戳转成 UTC,后面做时间窗口去重会乱套。我个人习惯在接入层先把所有时间存为 Unix 时间戳,用的时候再转。

3.6 避坑指南(个人血泪史)

  • 重复告警:Prometheus 的 repeat_interval 和 Zabbix 的 escalation 都可能产生重复。我曾经在一个故障中收到了同一台机器 47 次 CPU 超限告警,因为两边的重复抑制没对齐。后来我在接入层加了 N秒内相同指纹去重。
  • 丢失恢复事件:Zabbix 默认 action 只发故障告警,不发恢复。需要在 action 里增加一个“恢复操作”。我团队一个新人没注意,结果告警一直处于开启状态,直到手动排查才发现。
  • 认证走漏:如果是公网环境下推,没加 basic_auth 或 ,别人就能伪造告警。至少加一层身份校验。
  • HTTPS 证书校验:如果你的告警平台用了自签证书,Alertmanager 默认会校验失败。可以配置 insecure_skip_verify: true,但生产环境不推荐,最好用可信证书。

好,接下来我们用一张图把整个流程串起来。

常见监控系统对接告警平台流程 告警源接入流程 Prometheus Zabbix 其他监控系统 webhook / Media Type / 脚本 推送告警报文 统一接入层(解析、去重、标准化) 告警管理平台 / 处置闭环 最终:统一告警格式、状态同步、历史归档

这张图展示了从 Prometheus、Zabbix 等监控系统发出告警,经过 webhook 推送进入统一接入层,然后标准化后流入告警管理平台的过程。嗯,关键就是那一层黄色的“统一接入”——它承上启下,把不同源告警拧成一股绳。

至此,告警源接入的核心内容就讲完了。你在生产环境落地时,可以先从一个源(比如 Prometheus)开始跑通,再逐步加其他源。记得把接入层日志打全,刚开始调试时很有用。