4. 告警源接入:Prometheus告警、Zabbix告警、云监控告警的通用接入方式
告警降噪的第一步,是将分散在不同监控系统中的告警事件统一接入到同一个处理管道中。Prometheus、Zabbix 和云监控(阿里云/AWS)是当前最主流的告警源,它们的接入方式虽有差异,但遵循一套通用的抽象模型:事件产生 → 格式转换 → 路由转发 → 标准化存储。本章将逐一拆解这三种告警源的接入细节,并给出可复用的集成方案。
4.1 通用接入模型与适配层设计
在开始具体接入之前,先建立统一的抽象模型。所有告警源最终都会被映射为以下标准结构:
| 字段 | 类型 | 说明 | Prometheus 示例 | Zabbix 示例 | 云监控示例 |
|---|---|---|---|---|---|
| alert_name | string | 告警规则名称 | HighCpuUsage | CPU utilization too high | CPUUtilization |
| severity | string | 告警等级(critical/warning/info) | critical | Disaster | CRITICAL |
| status | string | 告警状态(firing/resolved) | firing | PROBLEM | ALARM |
| starts_at | timestamp | 告警触发时间 | 2025-01-15T10:30:00Z | 2025-01-15 10:30:00 | 2025-01-15T10:30:00+08:00 |
| labels | map | 标签/维度信息 | {instance, job} | {host, group} | {instanceId, region} |
| annotations | map | 注解/描述信息 | {summary, description} | {message, trigger} | {description, cause} |
适配层的作用就是完成从各告警源原生格式到上述标准结构的转换。以下 SVG 展示了通用接入架构:
4.2 Prometheus 告警接入
Prometheus 告警通过 Alertmanager 的 Webhook 机制向外推送。这是目前最标准、最灵活的接入方式之一。接入流程如下:
- 配置 Alertmanager Webhook receiver:在 alertmanager.yml 中定义 webhook_configs,指向统一接入层的 HTTP 端点。
- 接收并解析告警 payload:Alertmanager 发送的 POST 请求体为 JSON 格式,包含 alerts 数组,每个 alert 包含 labels、annotations、startsAt、endsAt、status 等字段。
- 字段映射与等级转换:将 severity 从 Prometheus 的标签值(如 "critical")映射为统一等级;将 status 从 "firing"/"resolved" 映射为统一状态。
- 去重与分组:利用 alertname + instance 组合键做短时间窗口(如 30 秒)内的去重,避免重复告警涌入。
# alertmanager.yml 片段
receivers:
- name: 'unified-adapter'
webhook_configs:
- url: 'http://10.0.0.10:8080/api/v1/alerts'
send_resolved: true
http_config:
timeout: 5s
接入层接收到的 Prometheus 告警示例:
{
"receiver": "unified-adapter",
"status": "firing",
"alerts": [
{
"status": "firing",
"labels": {
"alertname": "HighCpuUsage",
"instance": "web-01:9090",
"severity": "critical"
},
"annotations": {
"summary": "CPU usage above 90%",
"description": "Instance web-01 CPU usage is 95%"
},
"startsAt": "2025-01-15T10:30:00Z",
"endsAt": "0001-01-01T00:00:00Z"
}
]
}
4.3 Zabbix 告警接入
Zabbix 的告警接入相对传统,主要通过 Action 触发脚本或 Webhook 实现。推荐使用 Zabbix 6.0+ 内置的 Webhook 媒体类型,或通过自定义脚本调用统一接入 API。
| 接入方式 | 适用版本 | 优点 | 缺点 |
|---|---|---|---|
| Action + 自定义脚本 | Zabbix 4.0+ | 兼容性强,可定制 | 需维护脚本,无重试机制 |
| Webhook 媒体类型 | Zabbix 6.0+ | 原生支持,配置简单 | 版本限制,调试困难 |
| Zabbix API 轮询 | 所有版本 | 无需修改 Zabbix 配置 | 延迟高,增加 Zabbix 负载 |
推荐使用 Action + 自定义脚本 方式,因为它最灵活且不依赖 Zabbix 版本。脚本接收 Zabbix 传入的环境变量,组装为统一 JSON 格式后 POST 到接入层。
Zabbix 自定义脚本示例(Python):
#!/usr/bin/env python3
import sys, json, requests
# Zabbix 传入的环境变量
alert_subject = sys.argv[1]
alert_message = sys.argv[2]
# 解析 Zabbix 消息(根据实际模板调整)
lines = alert_message.split('\n')
event = {
"alert_name": lines[0] if len(lines) > 0 else "unknown",
"severity": "critical" if "Disaster" in alert_subject else "warning",
"status": "firing",
"starts_at": lines[1] if len(lines) > 1 else "",
"labels": {"host": lines[2] if len(lines) > 2 else ""},
"annotations": {"message": alert_message}
}
# 发送到统一接入层
requests.post("http://10.0.0.10:8080/api/v1/alerts",
json=event, timeout=5)
4.4 云监控告警接入
阿里云和 AWS 的云监控告警接入方式类似,都支持通过消息中间件或 HTTP 回调将告警事件推送到外部系统。以下是两种主流云平台的接入对比:
| 维度 | 阿里云 | AWS |
|---|---|---|
| 推送方式 | 云监控 → 消息服务 MNS / 函数计算 FC | CloudWatch → SNS / Lambda |
| 告警格式 | JSON,含 userId、alertName、alertState、dimensions | JSON,含 AlarmName、NewStateValue、OldStateValue、Trigger |
| 等级字段 | alertLevel(CRITICAL/WARN/INFO) | 无独立等级字段,需从阈值判断 |
| 状态字段 | alertState(ALARM/OK) | NewStateValue(ALARM/OK/INSUFFICIENT_DATA) |
| 推荐接入方式 | MNS 队列订阅 → 消费端拉取 | SNS Topic → HTTP/HTTPS 订阅 |
云监控告警接入的关键在于处理 状态转换 和 重复通知。云平台通常会在告警持续期间周期性推送,接入层需要做幂等处理:
- 状态转换逻辑:ALARM → firing,OK → resolved。对于 AWS 的 INSUFFICIENT_DATA 状态,建议忽略或映射为 info 级别。
- 去重策略:使用 alertName + dimensions 作为唯一键,在 5 分钟窗口内只保留第一次 ALARM 事件和最后一次 OK 事件。
- 时区处理:阿里云告警时间默认为 UTC+8,AWS 为 UTC。统一转换为 UTC 时间戳存储。
import json
from aliyunsdkcore.client import AcsClient
from aliyunsdkmns.request.v20190315 import ReceiveMessageRequest
client = AcsClient('ak', 'sk', 'cn-hangzhou')
queue_name = "alert-queue"
def poll_alerts():
request = ReceiveMessageRequest.ReceiveMessageRequest()
request.set_QueueName(queue_name)
response = client.do_action_with_exception(request)
msg = json.loads(response)
# 转换为统一格式
alert = {
"alert_name": msg.get("alertName"),
"severity": msg.get("alertLevel", "warning").lower(),
"status": "firing" if msg.get("alertState") == "ALARM" else "resolved",
"starts_at": msg.get("alertTime"),
"labels": {d["dimensionKey"]: d["dimensionValue"]
for d in msg.get("dimensions", [])},
"annotations": {"description": msg.get("alertMessage")}
}
return alert
4.5 接入层统一接口规范
无论告警源来自哪里,接入层对外暴露的 HTTP 接口应保持一致。推荐使用以下规范:
| 项目 | 规范 |
|---|---|
| 端点 | POST /api/v1/alerts |
| Content-Type | application/json |
| 请求体 | 统一告警事件 JSON(支持单条和批量) |
| 成功响应 | HTTP 200 + {"code": 0, "message": "ok"} |
| 限流响应 | HTTP 429 + {"code": 429, "message": "rate limit exceeded"} |
| 鉴权方式 | Header: X-Auth-(静态 或 HMAC 签名) |
统一告警事件 JSON Schema(核心字段):
{
"alert_name": "string (必填)",
"severity": "string (必填, 枚举: critical/warning/info)",
"status": "string (必填, 枚举: firing/resolved)",
"starts_at": "string (必填, ISO8601 UTC)",
"ends_at": "string (可选, ISO8601 UTC)",
"labels": "object (可选, key-value 字符串)",
"annotations": "object (可选, key-value 字符串)",
"source": "string (可选, 告警源标识: prometheus/zabbix/alicloud/aws)"
}