第 3 章 告警源接入:Prometheus、Zabbix、CloudWatch
告警源是监控体系的“水源”。水不好,后面做再多规则也是白搭。我见过不少团队,告警规则写得天花乱坠,结果数据源连不上,或者指标定义错了——全白费。
这一章我们聊三种最常见的告警源:Prometheus、Zabbix、CloudWatch。它们代表了三种不同的生态:开源自建、传统IT监控、云原生。你想想看,一个搞Kubernetes的团队和一个管物理机房的团队,需求能一样吗?
但我个人习惯是——不管哪种源,接入标准必须统一。接口、格式、频率、标签规范,缺一不可。下面我把三种源的接入要点拆开讲。
3.1 Prometheus 告警源接入
Prometheus 自带 Alertmanager,但很多企业还是会把告警打到统一平台(比如我们自研的告警引擎)。为什么?因为Alertmanager 做分组、抑制、静默还行,但要做复杂的告警编排、告警降噪、多源聚合,就不太够用了。
我在项目中遇到过一个场景:业务告警由 Prometheus 产生,但还需要混合 Zabbix 的硬件告警。如果直接用 Alertmanager 收,两个体系的标签格式不统一,后面根本没法合并。所以我的做法是——先把 Prometheus 的告警事件以 HTTP Webhook 形式推送到统一网关。
- 在 Alertmanager 配置中设置
webhook_configs指向统一推送接口。 - 统一网关接收 JSON Payload,并做格式转换。
- 告警引擎根据标签(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 等级 | 映射后 severity | 说明 |
|---|---|---|
| Information | info | 无需立即处理 |
| Warning | warning | 注意观察 |
| Average | warning | 可降级,避免过度告警 |
| High | critical | 需要立即响应 |
| Disaster | critical | 最高优先级 |
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 告警源接入的统一抽象层
讲了三种源,你有没有发现一个共同点?它们都需要:
- 一个统一接收端(HTTP 或 MQ)。
- JSON 格式的告警体。
- 标签/字段的映射和标准化。
所以我每次做项目,都会先设计一个 统一告警事件模型,然后把每种源的字段转换到这个模型上。模型长什么样?
| 字段 | 类型 | 说明 |
|---|---|---|
| source | string | 来源:prometheus / zabbix / cloudwatch |
| alert_name | string | 告警规则名称 |
| severity | string | info / warning / critical |
| status | string | firing / resolved |
| timestamp | int64 | Unix 毫秒 |
| labels | map[string]string | 标签,如 host、service |
| annotations | map[string]string | 描述、链接等 |
| raw_event | string | 原始完整事件(用于排查时回溯) |
这个模型我在多个项目中复用,接入新源时只用写一个适配器。嗯,省了不少事。
- Prometheus 走 Webhook,注意 send_resolved 和认证。
- Zabbix 做好等级映射,保留 eventid 做去重键。
- CloudWatch 用 EventBridge + SNS,拿到完整上下文。
- 抽象出统一告警模型,各源写适配器就好。
我个人习惯是先花一天把模型定好,再挨个接源。不然后面改标签映射会改到崩溃——你想想看,几十条规则都依赖某个标签,源一升级,标签名变了,你一个个改?