第 3 章 告警源接入:Prometheus、Zabbix、CloudWatch

告警源是监控体系的“水源”。水不好,后面做再多规则也是白搭。我见过不少团队,告警规则写得天花乱坠,结果数据源连不上,或者指标定义错了——全白费。

这一章我们聊三种最常见的告警源:Prometheus、Zabbix、CloudWatch。它们代表了三种不同的生态:开源自建、传统IT监控、云原生。你想想看,一个搞Kubernetes的团队和一个管物理机房的团队,需求能一样吗?

但我个人习惯是——不管哪种源,接入标准必须统一。接口、格式、频率、标签规范,缺一不可。下面我把三种源的接入要点拆开讲。

3.1 Prometheus 告警源接入

Prometheus 自带 Alertmanager,但很多企业还是会把告警打到统一平台(比如我们自研的告警引擎)。为什么?因为Alertmanager 做分组、抑制、静默还行,但要做复杂的告警编排、告警降噪、多源聚合,就不太够用了。

我在项目中遇到过一个场景:业务告警由 Prometheus 产生,但还需要混合 Zabbix 的硬件告警。如果直接用 Alertmanager 收,两个体系的标签格式不统一,后面根本没法合并。所以我的做法是——先把 Prometheus 的告警事件以 HTTP Webhook 形式推送到统一网关。

接入步骤
  1. 在 Alertmanager 配置中设置 webhook_configs 指向统一推送接口。
  2. 统一网关接收 JSON Payload,并做格式转换。
  3. 告警引擎根据标签(alertname、instance、severity)做去重和关联。

下面是一个标准的 Alertmanager webhook 配置片段,我一般会加上 send_resolved: true——很多人会漏掉这个,导致告警恢复事件丢失。

receivers:
- name: 'to-unified-gateway'
  webhook_configs:
  - url: 'http://unified-gateway:8080/webhook/prometheus'
    send_resolved: true
    http_config:
      basic_auth:
        username: 'alert-user'
        password: 'alert-pass'

记得做好认证和重试。Prometheus 默认重试 3 次,间隔 5 秒,但如果你网关挂了,最好用消息队列缓冲一下。我吃过这个亏——有一次网关升级,告警丢了半小时,后来加了 Kafka 缓冲才解决。

3.2 Zabbix 告警源接入

Zabbix 是个老牌选手。很多传统企业还在用它监控网络设备、服务器硬件。Zabbix 的告警通过 Action 触发,支持多种媒介:邮件、短信、脚本、Webhook。

我个人觉得最稳妥的方式是走 Zabbix 的 Media Type:Webhook。Zabbix 6.0 以后原生支持 Webhook,可以直接把告警 JSON 发到你的网关。如果版本低,就用自定义脚本——我当年在 4.0 版本上干活,就是写了个 Python 脚本,调用 curl 推送。

我曾经踩过的坑: Zabbix 的告警等级(Information、Warning、Average、High、Disaster)和 Prometheus 的 severity(info、warning、critical)天然不对齐。如果不做映射,后面聚合时会出现“严重性混乱”——同一个规则可能既收到“High”又收到“critical”。我的做法是在网关上建一张映射表:
Zabbix 等级映射后 severity说明
Informationinfo无需立即处理
Warningwarning注意观察
Averagewarning可降级,避免过度告警
Highcritical需要立即响应
Disastercritical最高优先级

Zabbix 的告警内容里通常会带 triggerid 和 eventid。我建议保留这两个 ID 作为去重键的一部分——它们天然全局唯一,比直接用主机名+指标名靠谱。

3.3 AWS CloudWatch 告警源接入

CloudWatch 是 AWS 原生的监控告警服务。它支持 CloudWatch Alarm,也有 EventBridge 做事件路由。如果你在 AWS 上跑业务,那 CloudWatch 逃不开。

接入方式很灵活:

  • 首选:EventBridge → SNS → HTTP Endpoint。EventBridge 可以订阅所有 CloudWatch Alarm 状态变更事件,通过 SNS 发到你的统一网关。
  • 次选:CloudWatch Alarm 直接配置 SNS。但这种方式只能发严重等级变化,缺少细节。
  • 备选:AWS Lambda 拉取。如果网络隔离,可以定时跑 Lambda 拉告警列表,再推出去。

我个人比较推荐 EventBridge + SNS 的方案。因为 EventBridge 能拿到完整事件体(包括命名空间、指标、阈值、历史数据),而你写规则时经常会需要这些上下文。

{
  "source": ["aws.cloudwatch"],
  "detail-type": ["CloudWatch Alarm State Change"],
  "resources": ["arn:aws:cloudwatch:us-east-1:123456789012:alarm:MyHighCpuAlarm"]
}

这段 EventBridge 事件规则示例,匹配指定 Alarm 的状态变化。注意 detail-type 字段——很多人写成 Alarm State Change,缺了“CloudWatch”前缀,事件就收不到。

3.4 告警源接入的统一抽象层

讲了三种源,你有没有发现一个共同点?它们都需要:

  1. 一个统一接收端(HTTP 或 MQ)。
  2. JSON 格式的告警体。
  3. 标签/字段的映射和标准化。

所以我每次做项目,都会先设计一个 统一告警事件模型,然后把每种源的字段转换到这个模型上。模型长什么样?

字段类型说明
sourcestring来源:prometheus / zabbix / cloudwatch
alert_namestring告警规则名称
severitystringinfo / warning / critical
statusstringfiring / resolved
timestampint64Unix 毫秒
labelsmap[string]string标签,如 host、service
annotationsmap[string]string描述、链接等
raw_eventstring原始完整事件(用于排查时回溯)

这个模型我在多个项目中复用,接入新源时只用写一个适配器。嗯,省了不少事。

告警源接入统一抽象层流程 Prometheus Zabbix CloudWatch 适配器层 格式转换 标签映射 等级归一 统一告警模型 source / alert_name severity / status labels / annotations 告警引擎 / 规则编排 💡 关键点 每个源都经过适配器转为统一模型,下游不关心来源 新增源只需编写一个新适配器,无需改动规则引擎
总结一下:
  • Prometheus 走 Webhook,注意 send_resolved 和认证。
  • Zabbix 做好等级映射,保留 eventid 做去重键。
  • CloudWatch 用 EventBridge + SNS,拿到完整上下文。
  • 抽象出统一告警模型,各源写适配器就好。

我个人习惯是先花一天把模型定好,再挨个接源。不然后面改标签映射会改到崩溃——你想想看,几十条规则都依赖某个标签,源一升级,标签名变了,你一个个改?