2、告警源接入:Prometheus告警接入、Zabbix告警接入、云平台告警接入

告警源接入,说白了就是让我们的监控平台能听懂各种系统说的话。你想想看,一个企业里可能有几十套监控工具,每套都有自己的告警格式。如果各自为政,运维人员就得盯着七八个屏幕,那画面太美我不敢看。

我个人习惯是把所有告警统一接入到一个中心平台。这样不仅方便管理,还能做关联分析。今天我们就聊聊三种最常见的告警源接入方式:Prometheus、Zabbix和云平台。

2.1 Prometheus告警接入

Prometheus现在几乎是云原生监控的事实标准了。它的告警机制设计得很优雅,但接入的时候有几个坑要注意。

Prometheus的告警流程是这样的:
采集指标 → 触发告警规则 → 发送到Alertmanager → 路由分发 → 通知接收人

我们主要关注怎么把Alertmanager的告警接到我们的统一平台。

2.1.1 Webhook接收器配置

Alertmanager支持多种接收器,其中webhook是最灵活的。我在项目中遇到过,很多团队直接用邮件接收告警,结果告警一多,邮箱直接炸了。

配置webhook很简单,在alertmanager.yml里加上:

receivers:
- name: 'webhook'
  webhook_configs:
  - url: 'http://your-platform:8080/api/v1/alerts'
    send_resolved: true

这里有个细节:send_resolved建议设为true。为什么?因为如果不发恢复通知,你的告警平台永远不知道问题解决了没有。我曾经因为这个踩过坑,半夜爬起来处理一个其实已经自动恢复的告警。

2.1.2 告警数据格式解析

Alertmanager发过来的告警是JSON格式的,结构如下:

{
  "receiver": "webhook",
  "status": "firing",
  "alerts": [
    {
      "status": "firing",
      "labels": {
        "alertname": "HighCPUUsage",
        "instance": "192.168.1.100:9090",
        "severity": "critical"
      },
      "annotations": {
        "summary": "CPU使用率超过90%",
        "description": "实例192.168.1.100的CPU使用率已达95%"
      },
      "startsAt": "2024-01-15T10:00:00Z",
      "endsAt": "0001-01-01T00:00:00Z"
    }
  ]
}

嗯,这里要注意。告警状态有firing和resolved两种。你的接入程序需要根据status字段来判断是新增告警还是恢复告警。

小技巧: 我建议在接入层做一层数据清洗。比如把labels里的severity映射成你平台自己的告警级别,把annotations里的描述信息标准化。这样后续处理会省很多事。

2.2 Zabbix告警接入

Zabbix虽然年头久了,但在传统IT监控领域还是扛把子。它的告警接入方式比较传统,但胜在稳定。

Zabbix支持多种告警媒介,包括邮件、短信、脚本等。我们一般用脚本方式接入。

2.2.1 告警脚本配置

在Zabbix的AlertScriptsPath目录下,创建一个脚本:

#!/bin/bash
# zabbix_alert_to_platform.sh

ALERT_SUBJECT="$1"
ALERT_BODY="$2"

# 构建JSON数据
JSON_DATA=$(cat <<EOF
{
  "source": "zabbix",
  "subject": "$ALERT_SUBJECT",
  "body": "$ALERT_BODY",
  "timestamp": "$(date +%s)"
}
EOF
)

# 发送到统一平台
curl -X POST -H "Content-Type: application/json" \
  -d "$JSON_DATA" \
  http://your-platform:8080/api/v1/zabbix/alerts

然后在Zabbix前端配置告警动作,选择这个脚本作为告警媒介。

避坑指南: 我曾经遇到过一个情况,Zabbix的告警脚本执行超时导致告警丢失。Zabbix默认的脚本超时时间是30秒,如果你的平台响应慢,记得调大这个值。在zabbix_server.conf里有个Timeout参数,建议设到60秒。

2.2.2 告警格式转换

Zabbix的告警格式比较自由,不像Prometheus那么规范。我建议在接入层做格式转换:

Zabbix原始字段 标准化字段 说明
ALERT.SUBJECT title 告警标题
ALERT.MESSAGE description 告警详情
ALERT.STATUS status PROBLEM或OK
ALERT.SEVERITY severity 映射成数字级别
ALERT.HOST source 告警来源主机

你想想看,如果不做这个映射,后面做告警聚合的时候,字段名都不统一,那得多痛苦。

2.3 云平台告警接入

现在大部分业务都跑在云上,AWS、阿里云、腾讯云都有自己的告警系统。云平台的告警接入,核心是调用它们的API。

2.3.1 阿里云告警接入

阿里云的告警可以通过云监控的Webhook回调来接入。在云监控控制台配置告警联系人时,选择Webhook回调:

# 阿里云告警回调示例
POST /api/v1/cloud/alerts HTTP/1.1
Host: your-platform:8080
Content-Type: application/json

{
  "traceId": "1234567890",
  "alertName": "CPU使用率过高",
  "alertState": "ALERT",
  "metricName": "cpu_utilization",
  "namespace": "acs_ecs",
  "instanceId": "i-12345678",
  "expression": "平均值 >= 90%",
  "triggerLevel": "CRITICAL",
  "timestamp": 1705305600000
}

这里有个关键点:云平台的告警状态字段各不相同。阿里云用ALERT和OK,AWS用ALARM和OK,腾讯云用Firing和Recovered。接入的时候一定要做好状态映射。

2.3.2 AWS CloudWatch告警接入

AWS的告警可以通过SNS(Simple Notification Service)转发到HTTP端点。配置步骤:

  1. 创建SNS主题
  2. 创建HTTP/HTTPS订阅,指向你的平台地址
  3. 在CloudWatch告警中配置SNS通知

AWS发过来的告警格式是这样的:

{
  "AlarmName": "HighCPUUtilization",
  "AlarmDescription": "CPU使用率超过80%",
  "AWSAccountId": "123456789012",
  "NewStateValue": "ALARM",
  "OldStateValue": "OK",
  "NewStateReason": "CPU使用率当前为95%",
  "StateChangeTime": "2024-01-15T10:00:00.000+0000",
  "Region": "us-east-1",
  "AlarmArn": "arn:aws:cloudwatch:us-east-1:123456789012:alarm:HighCPUUtilization"
}
核心要点: 云平台的告警接入,本质上是把云厂商的告警格式转换成你平台的统一格式。我建议在接入层维护一个云厂商映射表,把不同厂商的字段名、状态值、级别都映射成统一的格式。这样上层处理逻辑就不用关心告警是从哪个云来的。

2.4 告警去重与聚合

告警接入之后,第一件事就是去重。你想想看,一个服务挂了,可能同时触发CPU告警、内存告警、响应时间告警,如果不做去重,运维人员会被告警淹没。

我常用的去重策略:

  • 时间窗口去重: 同一告警源在5分钟内重复发送相同告警,只保留第一条
  • 指纹去重: 根据告警的labels或tags生成唯一指纹,相同指纹的告警自动合并
  • 关联去重: 如果多个告警指向同一个故障根因,只展示根因告警

嗯,这里要注意。去重不是简单的丢弃,而是合并。比如CPU告警连续发了10次,你应该展示为「CPU告警已触发10次,持续5分钟」,而不是只显示第一次。

个人经验: 我在做告警接入时,会保留原始告警的完整信息,包括重复次数、首次触发时间、最近触发时间。这样后续做告警分析和报表时,数据才够用。别为了省存储空间把原始数据丢了,到时候想查历史记录就抓瞎了。

好了,告警源接入这块就聊这么多。记住一个原则:接入是手段,不是目的。我们做告警接入,最终是为了让告警管理更高效,让运维人员少熬夜。下一章我们聊聊告警分级和优先级,那才是真正考验设计能力的地方。