第2章 告警源集成:Prometheus、Zabbix、Grafana 对接方法归纳总结

告警源集成,说白了就是把监控系统的告警事件“喂”给告警工单系统。这一步要是没做好,后面闭环做得再漂亮也是白搭。我早期接手的几个项目,问题都出在对接层——要么告警丢了,要么重复推送,要么字段对不上。

这一章,我把三种主流监控系统的对接套路拆开揉碎,讲清楚原理、配置和常见坑。你先看张总览图,心里有个脉络。

告警源对接核心知识体系 告警源对接 Prometheus Zabbix Grafana Alertmanager Webhook receiver Action + Script 自定义 Media Alerting → Webhook 统一告警接收服务(Webhook / API) 告警工单 → 闭环处理 💡 关键原则:统一告警格式、去重、字段映射、重试机制 告警源 → 标准化 → 工单系统,中间必须做一层适配层,否则后续维护会非常痛苦。 我个人推荐使用队列缓冲(如 Redis / Kafka)削峰填谷。

2.1 Prometheus + Alertmanager:Webhook 是标配

Prometheus 本身只负责采集和存储指标,告警规则定义在独立文件里。触发告警后,由 Alertmanager 负责路由、抑制、静默和发送。对接工单系统,最直接的方式就是使用 Alertmanager 的 Webhook receiver。

对接流程一句话:配置 alerting rule → Alertmanager 匹配路由 → 调用你的 Webhook URL → 解析 JSON 并创建工单。

核心配置示例

在 Alertmanager 的配置文件里加一个 receiver,指向你的告警接收服务。我在项目里是这样写的:

# alertmanager.yml 片段
route:
  group_by: ['alertname', 'instance']
  group_wait: 10s
  group_interval: 30s
  repeat_interval: 4h
  receiver: 'webhook-to-tickets'

receivers:
- name: 'webhook-to-tickets'
  webhook_configs:
  - url: 'http://your-ticket-service/api/v1/alert'
    send_resolved: true
    http_config:
      basic_auth:
        username: 'alertmanager'
        password: 'you-should-use-secret'

这里面有一个我踩过的坑:send_resolved: true 必须打开,否则恢复告警不会推送给工单系统,导致工单永远无法自动关闭。别问我怎么知道的……

我个人习惯:在 Webhook 接收端做一层简单的幂等校验。Prometheus 的告警可能在网络抖动时重复推送,利用 fingerprint 或 alertname+instance 作为唯一键,防止重复工单。

字段映射表

Prometheus 的告警 JSON 结构比较标准,你需要把以下字段映射到工单系统:

Prometheus 字段说明建议映射到工单字段
labels.alertname告警名称标题
labels.severity严重级别 (critical/warning/info)优先级
labels.instance实例标识资源名称
annotations.summary概要描述描述
annotations.description详细描述详情
startsAt触发时间发现时间
endsAt恢复时间(resolved 时有效)解决时间

注意:severity 字段的值通常是小写英文,工单系统里可能是中文或数字级别的,记得做一层映射。我曾经用 critical → P1、warning → P2、info → P3 来对应。

2.2 Zabbix:Action + Script 是最灵活的方式

Zabbix 的对接方式比 Prometheus 要多一些。官方支持 Webhook(6.0 以后),但很多老项目还在用 Action + Script 的方式。我个人更推荐后者,因为可定制空间大,而且不依赖 Zabbix 版本。

基本原理:Zabbix 触发告警时 → 执行 Action → 调用自定义脚本(如 Python 或 Shell)→ 脚本把告警信息 POST 到工单接口。

关键步骤:

  1. 在 Zabbix 前端创建 Action,触发器条件按需设置。
  2. Action 的 Operation 类型选“Remote command”,指定脚本路径。
  3. 脚本通过环境变量或参数接收告警信息。

脚本接收参数示例

#!/bin/bash
# alert_to_ticket.sh
# 接收 Zabbix 传过来的参数
ALERT_SUBJECT="$1"
ALERT_MESSAGE="$2"
ALERT_SEVERITY="$3"

# 构造 JSON
PAYLOAD=$(cat <<EOF
{
  "title": "$ALERT_SUBJECT",
  "message": "$ALERT_MESSAGE",
  "severity": "$ALERT_SEVERITY",
  "source": "zabbix",
  "trigger_time": "$(date -u +'%Y-%m-%dT%H:%M:%SZ')"
}
EOF
)

curl -X POST -H "Content-Type: application/json" \
  -d "$PAYLOAD" \
  http://your-ticket-service/api/v1/alert

避坑指南:我曾经在 Zabbix 5.4 里用 Webhook 原生功能,发现它不支持自定义 HTTP Header。后来改回 Action+Script,轻松解决了认证问题。所以你如果用的是老版本,别硬上 Webhook。

Zabbix 6.0+ 原生 Webhook 配置

如果你用新版本,可以直接用 Mediatypes 里的 Webhook 模板。我建议复制一份默认模板再改:

  1. Administration → Media types → Create media type
  2. Type 选 Webhook,填写你的告警 URL
  3. Parameter 设置:{ALERT.SUBJECT}, {ALERT.MESSAGE}, {ALERT.SEVERITY}
  4. Script 里用 JavaScript 拼接 HTTP 请求——Zabbix 内部用的是 Go 的 JS 引擎。

2.3 Grafana:Alerting 模块的 Webhook 集成

Grafana 8.0 之后重构了告警模块,现在叫 Grafana Alerting。它统一了来自 Prometheus、Loki、Tempo 等数据源的告警规则,然后通过“通知策略”发送。对接工单系统同样用 Webhook。

你想想看,如果你团队已经用 Grafana 做统一监控面板,那直接在 Grafana 里配告警,再推给工单系统,是最省事的。少维护一个中间件。

配置路径

  1. Alerting → Contact points → New contact point
  2. Type 选 Webhook,填写 URL
  3. 可选设置:Basic Auth、TLS、自定义 HTTP Header
  4. Notification policy 里选择该 contact point

Grafana 告警 JSON 示例(部分关键字段):

{
  "status": "firing",
  "labels": { "alertname": "HighCPU", "instance": "web-01" },
  "annotations": { "summary": "CPU > 90%", "description": "实例 web-01 的 CPU 已持续 5 分钟 > 90%" },
  "startsAt": "2025-01-20T10:00:00Z",
  "endsAt": "0001-01-01T00:00:00Z",
  "generatorURL": "http://grafana/explore..."
}

这个结构和 Prometheus 的相似,但多了 generatorURL,非常有用——你可以把它放进工单的“关联链接”里,工程师点一下就能跳到 Grafana 看当时的时序图。我每接手一个新项目,第一件事就是把这个链接补上,排查效率翻倍。

注意:Grafana Alerting 默认对同一个告警实例的重复通知有抑制,但如果你配置了多个通知策略,可能会收到重复工单。建议在工单接收端做去重,或者把 notification policy 的“分组”设置得严格一些。

2.4 三种对接方式对比

表格一看就清楚,哪种场景用哪种方案:

特性Prometheus + AlertmanagerZabbix Action+ScriptGrafana Alerting
配置复杂度低(标准 Webhook)中(需写脚本)低(UI 配置)
版本兼容所有版本所有版本(推荐)Grafana 8.0+
可定制性中等(JSON 固定格式)高(脚本任意改造)中等(模板有限)
数据处理能力Alertmanager 支持路由、抑制需自己处理去重内置分组、抑制
工单系统对接直接 POST JSON任意 HTTP 调用直接 POST JSON
社区成熟度极高极高中高

2.5 我在实践中总结的几条铁律

  • 统一告警格式:不管你接多少监控源,工单系统看到的字段结构必须一致。我自己的做法是做一个“告警数据清洗层”,把 Prometheus/Zabbix/Grafana 的 JSON 都转成统一的 schema,再塞给工单 API。
  • 一定要加 Unique ID:每个告警实例需要一个全局唯一 ID。Prometheus 用 fingerprint,Zabbix 用 event_id,Grafana 用 fingerprint 加时间戳。工单系统拿这个 ID 做幂等,重复推送不会产生重复工单。
  • 重试与超时:工单服务偶尔会挂,Webhook 发不出去怎么办?Alertmanager 默认会重试多次,但时间间隔不短。我建议在接收端用队列缓冲(比如 Redis List 或 Kafka),让告警先入队,再异步消费。这样哪怕工单系统重启,告警也不会丢。
  • 恢复告警闭环:一定要把“resolved”推送给工单系统。如果不推,工单永远处于“处理中”状态,闭环就是个笑话。嗯,这个前面提过,但值得再说一次。

关于告警风暴的处理:我曾经在双十一大促碰到告警风暴——几百个实例同时 CPU 飙高,Alertmanager 的 Webhook 瞬间被击穿,工单系统直接 502。后来我在 Webhook 前加了一层简单的限流:令牌桶算法,每秒最多 50 个请求进工单系统,其余的丢到队列里慢慢处理。虽然工单会延迟几分钟,但系统稳住了。这件事告诉我,对接层必须考虑限流和降级。