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 展示了通用接入架构:

告警源通用接入架构 Prometheus Alertmanager Webhook Zabbix Action → Script / Webhook 云监控 阿里云/AWS SNS/CMQ 统一适配层 格式解析 字段映射 等级归一化 去重过滤 速率限制 重试队列 标准化告警事件 JSON 统一格式

4.2 Prometheus 告警接入

Prometheus 告警通过 Alertmanager 的 Webhook 机制向外推送。这是目前最标准、最灵活的接入方式之一。接入流程如下:

  1. 配置 Alertmanager Webhook receiver:在 alertmanager.yml 中定义 webhook_configs,指向统一接入层的 HTTP 端点。
  2. 接收并解析告警 payload:Alertmanager 发送的 POST 请求体为 JSON 格式,包含 alerts 数组,每个 alert 包含 labels、annotations、startsAt、endsAt、status 等字段。
  3. 字段映射与等级转换:将 severity 从 Prometheus 的标签值(如 "critical")映射为统一等级;将 status 从 "firing"/"resolved" 映射为统一状态。
  4. 去重与分组:利用 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 的告警等级(Disaster/High/Average/Warning/Information)与 Prometheus 的 critical/warning/info 不直接对应。建议在适配层做显式映射:Disaster→critical,High/Average→warning,Warning/Information→info。不要使用默认的 1:1 映射,否则会导致告警等级失真。

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 时间戳存储。
阿里云 MNS 消费端核心代码:
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)"
}
生产建议:接入层应实现 健康检查端点(GET /health)和 指标暴露端点(GET /metrics),用于监控接入层自身的运行状态。同时,所有告警源接入后应先在测试环境运行 72 小时,确认字段映射和等级转换无误后再切换到生产。