0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Prometheus告警规则编写与Alertmanager通知配置实战

马哥Linux运维 来源:马哥Linux运维 2026-02-26 16:35 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

Prometheus告警规则编写与Alertmanager通知配置实战

一、概述

1.1 背景介绍

监控系统搭完了,指标也采集上来了,但如果没有告警,等于白搭。我见过不少团队Prometheus跑得好好的,Grafana大屏也挂在墙上,结果凌晨3点数据库磁盘写满了,第二天早上用户投诉才发现。监控不闭环,就是摆设。

Prometheus的告警分两部分:Prometheus Server负责根据PromQL表达式评估告警规则,触发后把告警推给Alertmanager;Alertmanager负责去重、分组、路由、静默,最终通过邮件、钉钉、企业微信、Webhook等渠道发出通知。这个分工设计得很合理——Prometheus专注数据采集和规则评估,Alertmanager专注通知管理,各司其职。

我们团队从2020年开始用这套告警体系,目前管理着600多条告警规则,覆盖主机、容器、中间件、业务四个层面,日均触发告警200-300条,通过分级策略和收敛机制,实际推送到人的不超过30条。

1.2 技术特点

PromQL驱动的告警规则:告警条件用PromQL表达式定义,能写出非常灵活的判断逻辑。比如"CPU使用率连续5分钟超过85%"、"磁盘空间按当前速率24小时内会写满"、"HTTP错误率突然飙升到正常值的3倍",这些用PromQL都能精确表达。

路由树+分组去重:Alertmanager的路由配置是树状结构,根据label匹配把告警分发到不同的接收器。同一组的告警会合并成一条通知发送,避免告警风暴。我们线上一次网络故障触发了80多条告警,经过分组后只发了3条通知。

抑制和静默机制:抑制(Inhibition)可以设置告警之间的依赖关系,比如节点宕机时自动抑制该节点上所有服务的告警。静默(Silence)可以在维护窗口临时屏蔽特定告警,避免计划内变更触发误报。

1.3 适用场景

基础设施告警:主机CPU、内存、磁盘、网络异常检测,服务进程存活监控,硬件故障预警。这是最基础的告警需求,覆盖面广,规则相对固定。

应用服务告警:HTTP接口的QPS、延迟、错误率监控,JVM内存和GC监控,数据库连接池和慢查询监控。需要和开发团队配合定义合理的阈值。

业务指标告警:订单量异常波动、支付成功率下降、用户注册量骤降。这类告警直接关联业务,阈值需要根据业务特征动态调整。

1.4 环境要求

组件 版本要求 说明
Prometheus 2.45+ 告警规则评估引擎,需要和Alertmanager版本匹配
Alertmanager 0.27+ 0.27版本修复了集群模式下的几个关键bug
操作系统 CentOS 7+ / Ubuntu 20.04+ Alertmanager资源消耗很低,1C1G就够
网络 内网互通 Prometheus到Alertmanager需要9093端口,Alertmanager集群间需要9094端口
通知渠道 邮件服务器/钉钉机器人/企微机器人 至少配一个通知渠道,建议配两个做冗余

二、详细步骤

2.1 准备工作

2.1.1 Alertmanager安装

# 创建用户
sudo useradd --no-create-home --shell /bin/falsealertmanager

# 下载Alertmanager
cd/tmp
wget https://github.com/prometheus/alertmanager/releases/download/v0.27.0/alertmanager-0.27.0.linux-amd64.tar.gz
tar xzf alertmanager-0.27.0.linux-amd64.tar.gz
cdalertmanager-0.27.0.linux-amd64

# 安装
sudo cp alertmanager /usr/local/bin/
sudo cp amtool /usr/local/bin/
sudo chown alertmanager:alertmanager /usr/local/bin/alertmanager
sudo chown alertmanager:alertmanager /usr/local/bin/amtool

# 创建配置和数据目录
sudo mkdir -p /etc/alertmanager
sudo mkdir -p /var/lib/alertmanager
sudo chown -R alertmanager:alertmanager /etc/alertmanager
sudo chown -R alertmanager:alertmanager /var/lib/alertmanager

# 验证
alertmanager --version

2.1.2 Systemd服务配置

sudo tee /etc/systemd/system/alertmanager.service > /dev/null << 'EOF'
[Unit]
Description=Alertmanager
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
User=alertmanager
Group=alertmanager
ExecStart=/usr/local/bin/alertmanager 
  --config.file=/etc/alertmanager/alertmanager.yml 
  --storage.path=/var/lib/alertmanager 
  --web.listen-address=0.0.0.0:9093 
  --web.external-url=http://alertmanager.example.com:9093 
  --cluster.listen-address=0.0.0.0:9094 
  --log.level=info 
  --data.retention=120h

Restart=always
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

参数说明

--data.retention=120h:告警数据保留5天,默认也是120h。这个数据是Alertmanager自己的状态数据(静默规则、通知记录等),不是Prometheus的监控数据。

--cluster.listen-address:集群通信端口,多实例部署时用。单机可以设成空字符串禁用。

--web.external-url:外部访问地址,告警通知里的链接会用这个地址。设错了点告警链接会404。

2.1.3 防火墙配置

# Alertmanager Web UI和API
sudo ufw allow 9093/tcp
# Alertmanager集群通信
sudo ufw allow 9094/tcp
sudo ufw allow 9094/udp
sudo ufw reload

2.2 核心配置

2.2.1 Alertmanager主配置文件

# 文件路径:/etc/alertmanager/alertmanager.yml
global:
resolve_timeout:5m
smtp_from:'alertmanager@example.com'
smtp_smarthost:'smtp.example.com:465'
smtp_auth_username:'alertmanager@example.com'
smtp_auth_password:'your_smtp_password'
smtp_require_tls:false

# 通知模板
templates:
-'/etc/alertmanager/templates/*.tmpl'

# 路由树配置
route:
# 分组依据,同一组的告警合并发送
group_by:['alertname','cluster','service']
# 新告警等待时间,等这么久再发送,让同组告警有机会合并
group_wait:30s
# 同一组告警的发送间隔
group_interval:5m
# 已发送告警的重复发送间隔
repeat_interval:4h
# 默认接收器
receiver:'default-webhook'

routes:
 # P0级别 - 核心服务宕机,立刻通知
 -match:
   severity:critical
  receiver:'critical-pager'
  group_wait:10s
  repeat_interval:1h
  continue:false

 # P1级别 - 性能告警,5分钟内通知
 -match:
   severity:warning
  receiver:'warning-dingtalk'
  group_wait:30s
  repeat_interval:4h
  continue:false

 # 数据库相关告警单独路由给DBA
 -match_re:
   job:'(mysql|redis|mongodb).*'
  receiver:'dba-dingtalk'
  group_wait:30s
  repeat_interval:2h
  continue:false

 # 业务告警路由给对应团队
 -match:
   team:'order'
  receiver:'order-team-webhook'
  continue:false

 -match:
   team:'payment'
  receiver:'payment-team-webhook'
  continue:false

# 抑制规则
inhibit_rules:
# 节点宕机时,抑制该节点上所有服务的告警
-source_match:
  alertname:'NodeDown'
 target_match_re:
  alertname:'.+'
 equal:['instance']

# critical级别告警触发时,抑制同指标的warning告警
-source_match:
  severity:'critical'
 target_match:
  severity:'warning'
 equal:['alertname','instance']

# 接收器配置
receivers:
# 默认接收器 - 企业微信
-name:'default-webhook'
 webhook_configs:
  -url:'http://localhost:8060/dingtalk/ops/send'
   send_resolved:true

# P0告警 - 电话+短信+钉钉
-name:'critical-pager'
 webhook_configs:
  -url:'http://localhost:8060/dingtalk/critical/send'
   send_resolved:true
  -url:'http://oncall-api.internal:8080/api/v1/alert'
   send_resolved:true
 email_configs:
  -to:'oncall@example.com'
   send_resolved:true
   headers:
    Subject:'[P0-CRITICAL]{{ .GroupLabels.alertname }}'

# Warning告警 - 钉钉群
-name:'warning-dingtalk'
 webhook_configs:
  -url:'http://localhost:8060/dingtalk/warning/send'
   send_resolved:true

# DBA告警
-name:'dba-dingtalk'
 webhook_configs:
  -url:'http://localhost:8060/dingtalk/dba/send'
   send_resolved:true

# 订单团队
-name:'order-team-webhook'
 webhook_configs:
  -url:'http://localhost:8060/dingtalk/order/send'
   send_resolved:true

# 支付团队
-name:'payment-team-webhook'
 webhook_configs:
  -url:'http://localhost:8060/dingtalk/payment/send'
   send_resolved:true

说明:group_wait设成30秒是经过权衡的。太短了同一批告警来不及合并,太长了延迟通知。P0级别的critical告警我们设成10秒,因为这类告警宁可多发也不能晚发。repeat_interval设4小时,避免同一个告警反复骚扰值班人员,但critical级别设1小时,确保持续关注。

2.2.2 告警规则文件 - 主机监控

# 文件路径:/etc/prometheus/rules/node_alerts.yml
groups:
-name:node_alerts
 rules:
  -alert:NodeDown
   expr:up{job="node-exporter"}==0
   for:2m
   labels:
    severity:critical
    team:ops
   annotations:
    summary:"节点{{ $labels.instance }}宕机"
    description:"节点已超过2分钟无响应,请立即排查"
    runbook:"https://wiki.internal/runbook/node-down"

  -alert:NodeCPUHigh
   expr:|
     1 - avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) > 0.85
   for:5m
   labels:
    severity:warning
    team:ops
   annotations:
    summary:"{{ $labels.instance }}CPU使用率{{ $value | humanizePercentage }}"
    description:"CPU持续5分钟超过85%,检查是否有异常进程"

  -alert:NodeMemoryHigh
   expr:|
     1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes > 0.90
   for:5m
   labels:
    severity:warning
    team:ops
   annotations:
    summary:"{{ $labels.instance }}内存使用率{{ $value | humanizePercentage }}"

  -alert:NodeDiskAlmostFull
   expr:|
     1 - node_filesystem_avail_bytes{mountpoint="/",fstype!="tmpfs"}
     / node_filesystem_size_bytes{mountpoint="/",fstype!="tmpfs"} > 0.85
   for:5m
   labels:
    severity:warning
    team:ops
   annotations:
    summary:"{{ $labels.instance }}磁盘使用率{{ $value | humanizePercentage }}"

  -alert:NodeDiskWillFull
   expr:|
     predict_linear(
      node_filesystem_avail_bytes{mountpoint="/",fstype!="tmpfs"}[6h], 24*3600
     ) < 0
        for:10m
        labels:
          severity:warning
          team:ops
        annotations:
          summary:"{{ $labels.instance }} 磁盘预计24小时内写满"
          description:"按当前写入速率推算,根分区将在24小时内耗尽"

      -alert:NodeNetworkErrors
        expr:|
          rate(node_network_receive_errs_total[5m]) > 10
     or rate(node_network_transmit_errs_total[5m]) > 10
   for:5m
   labels:
    severity:warning
    team:ops
   annotations:
    summary:"{{ $labels.instance }}网卡{{ $labels.device }}出现错误包"

  -alert:NodeLoadHigh
   expr:node_load15/countby(instance)(node_cpu_seconds_total{mode="idle"})>2
   for:10m
   labels:
    severity:warning
    team:ops
   annotations:
    summary:"{{ $labels.instance }}15分钟负载过高"
    description:"负载/CPU核数比值{{ $value }},超过2说明系统严重过载"

说明:for参数很关键,设太短容易误报,设太长又延迟告警。CPU和内存设5分钟是因为短暂的毛刺很常见,持续5分钟才说明真有问题。NodeDown设2分钟,因为网络抖动可能导致一两次采集失败,2分钟(约8次采集)能过滤掉大部分误报。

2.2.3 告警规则文件 - 应用服务监控

# 文件路径:/etc/prometheus/rules/app_alerts.yml
groups:
-name:app_alerts
 rules:
  -alert:ServiceDown
   expr:up{job=~"app-.*"}==0
   for:1m
   labels:
    severity:critical
   annotations:
    summary:"服务{{ $labels.job }}实例{{ $labels.instance }}不可达"

  -alert:HighErrorRate
   expr:|
     sum by(job) (rate(http_requests_total{status=~"5.."}[5m]))
     / sum by(job) (rate(http_requests_total[5m])) > 0.05
   for:3m
   labels:
    severity:critical
   annotations:
    summary:"{{ $labels.job }}HTTP 5xx错误率{{ $value | humanizePercentage }}"
    description:"错误率超过5%持续3分钟,检查应用日志"

  -alert:HighLatencyP99
   expr:|
     histogram_quantile(0.99,
      sum by(job, le) (rate(http_request_duration_seconds_bucket[5m]))
     ) > 2
   for:5m
   labels:
    severity:warning
   annotations:
    summary:"{{ $labels.job }}P99延迟{{ $value | humanizeDuration }}"

  -alert:QPSDropSudden
   expr:|
     sum by(job) (rate(http_requests_total[5m]))
     < sum by(job) (rate(http_requests_total[1h] offset 1d)) * 0.5
        for:10m
        labels:
          severity:warning
        annotations:
          summary:"{{ $labels.job }} QPS较昨日同期下降超过50%"
          description:"当前QPS {{ $value }},可能存在流量异常"

      -alert:JVMHeapHigh
        expr:|
          jvm_memory_used_bytes{area="heap"}
          / jvm_memory_max_bytes{area="heap"} > 0.85
   for:5m
   labels:
    severity:warning
   annotations:
    summary:"{{ $labels.instance }}JVM堆内存使用率{{ $value | humanizePercentage }}"

  -alert:JVMGCTimeHigh
   expr:|
     rate(jvm_gc_pause_seconds_sum[5m])
     / rate(jvm_gc_pause_seconds_count[5m]) > 0.5
   for:5m
   labels:
    severity:warning
   annotations:
    summary:"{{ $labels.instance }}GC平均耗时超过500ms"

2.2.4 钉钉通知模板配置

# 安装prometheus-webhook-dingtalk
cd/tmp
wget https://github.com/timonwong/prometheus-webhook-dingtalk/releases/download/v2.1.0/prometheus-webhook-dingtalk-2.1.0.linux-amd64.tar.gz
tar xzf prometheus-webhook-dingtalk-2.1.0.linux-amd64.tar.gz
sudo cp prometheus-webhook-dingtalk-2.1.0.linux-amd64/prometheus-webhook-dingtalk /usr/local/bin/
# 文件路径:/etc/prometheus-webhook-dingtalk/config.yml
targets:
ops:
 url:https://oapi.dingtalk.com/robot/send?access_token=YOUR_OPS_TOKEN
 secret:SEC_YOUR_OPS_SECRET
 message:
  title:'{{ template "ding.link.title" . }}'
  text:'{{ template "ding.link.content" . }}'
critical:
 url:https://oapi.dingtalk.com/robot/send?access_token=YOUR_CRITICAL_TOKEN
 secret:SEC_YOUR_CRITICAL_SECRET
warning:
 url:https://oapi.dingtalk.com/robot/send?access_token=YOUR_WARNING_TOKEN
 secret:SEC_YOUR_WARNING_SECRET
dba:
 url:https://oapi.dingtalk.com/robot/send?access_token=YOUR_DBA_TOKEN
 secret:SEC_YOUR_DBA_SECRET
# Systemd服务
sudo tee /etc/systemd/system/dingtalk-webhook.service > /dev/null << 'EOF'
[Unit]
Description=Prometheus Webhook DingTalk
After=network-online.target

[Service]
Type=simple
ExecStart=/usr/local/bin/prometheus-webhook-dingtalk 
  --config.file=/etc/prometheus-webhook-dingtalk/config.yml 
  --web.listen-address=0.0.0.0:8060
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl start dingtalk-webhook
sudo systemctl enable dingtalk-webhook

2.3 启动和验证

2.3.1 启动服务

# 检查Alertmanager配置语法
amtool check-config /etc/alertmanager/alertmanager.yml
# 输出:Checking '/etc/alertmanager/alertmanager.yml' SUCCESS

# 检查告警规则语法
promtool check rules /etc/prometheus/rules/node_alerts.yml
promtool check rules /etc/prometheus/rules/app_alerts.yml

# 启动Alertmanager
sudo systemctl start alertmanager
sudo systemctlenablealertmanager
sudo systemctl status alertmanager

# 重载Prometheus配置使告警规则生效
curl -X POST http://localhost:9090/-/reload

2.3.2 功能验证

# 验证Alertmanager健康状态
curl -s http://localhost:9093/-/healthy
# 输出:OK

# 查看当前告警规则
curl -s http://localhost:9090/api/v1/rules | python3 -m json.tool | head -40

# 查看活跃告警
curl -s http://localhost:9090/api/v1/alerts | python3 -m json.tool

# 用amtool查看Alertmanager状态
amtool --alertmanager.url=http://localhost:9093 config show

# 发送测试告警验证通知链路
curl -X POST http://localhost:9093/api/v2/alerts 
 -H'Content-Type: application/json'
 -d'[{
  "labels": {
   "alertname": "TestAlert",
   "severity": "warning",
   "instance": "test-node:9100"
  },
  "annotations": {
   "summary": "这是一条测试告警,验证通知链路"
  },
  "startsAt": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"
 }]'

# 等30秒后检查钉钉群是否收到通知
# 然后发送resolve清除测试告警
curl -X POST http://localhost:9093/api/v2/alerts 
 -H'Content-Type: application/json'
 -d'[{
  "labels": {
   "alertname": "TestAlert",
   "severity": "warning",
   "instance": "test-node:9100"
  },
  "endsAt": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"
 }]'

说明:每次改完告警规则或Alertmanager配置,一定要先用amtool和promtool做语法检查。我们有一次直接reload了一个有语法错误的规则文件,Prometheus没报错但那条规则静默失效了,直到出了故障才发现告警没触发。

三、示例代码和配置

3.1 完整配置示例

3.1.1 K8s集群告警规则集

# 文件路径:/etc/prometheus/rules/k8s_alerts.yml
groups:
-name:kubernetes_alerts
 rules:
  -alert:KubePodCrashLooping
   expr:|
     rate(kube_pod_container_status_restarts_total[15m]) * 60 * 5 > 0
   for:5m
   labels:
    severity:warning
   annotations:
    summary:"Pod{{ $labels.namespace }}/{{ $labels.pod }}频繁重启"
    description:"过去15分钟重启次数:{{ $value | humanize }}"

  -alert:KubePodNotReady
   expr:|
     sum by(namespace, pod) (
      max by(namespace, pod) (kube_pod_status_phase{phase=~"Pending|Unknown"}) * on(namespace, pod)
      group_left(owner_kind, owner_name) max by(namespace, pod, owner_kind, owner_name) (kube_pod_owner)
     ) > 0
   for:10m
   labels:
    severity:warning
   annotations:
    summary:"Pod{{ $labels.namespace }}/{{ $labels.pod }}超过10分钟未就绪"

  -alert:KubeDeploymentReplicasMismatch
   expr:|
     kube_deployment_spec_replicas != kube_deployment_status_ready_replicas
   for:10m
   labels:
    severity:warning
   annotations:
    summary:"Deployment{{ $labels.namespace }}/{{ $labels.deployment }}副本数不匹配"
    description:"期望{{ $labels.spec_replicas }},实际就绪{{ $labels.ready_replicas }}"

  -alert:KubeNodeNotReady
   expr:kube_node_status_condition{condition="Ready",status="true"}==0
   for:5m
   labels:
    severity:critical
   annotations:
    summary:"K8s节点{{ $labels.node }}NotReady"

  -alert:KubeContainerOOMKilled
   expr:|
     kube_pod_container_status_last_terminated_reason{reason="OOMKilled"} == 1
   for:0m
   labels:
    severity:warning
   annotations:
    summary:"容器{{ $labels.namespace }}/{{ $labels.pod }}/{{ $labels.container }}被OOM Kill"

  -alert:KubePVCAlmostFull
   expr:|
     kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes > 0.85
   for:5m
   labels:
    severity:warning
   annotations:
    summary:"PVC{{ $labels.namespace }}/{{ $labels.persistentvolumeclaim }}使用率超过85%"

3.1.2 中间件告警规则集

# 文件路径:/etc/prometheus/rules/middleware_alerts.yml
groups:
-name:mysql_alerts
 rules:
  -alert:MySQLDown
   expr:mysql_up==0
   for:1m
   labels:
    severity:critical
    team:dba
   annotations:
    summary:"MySQL{{ $labels.instance }}宕机"

  -alert:MySQLSlowQueries
   expr:rate(mysql_global_status_slow_queries[5m])>0.1
   for:5m
   labels:
    severity:warning
    team:dba
   annotations:
    summary:"MySQL{{ $labels.instance }}慢查询增多"
    description:"每秒慢查询数{{ $value }}"

  -alert:MySQLConnectionsHigh
   expr:|
     mysql_global_status_threads_connected
     / mysql_global_variables_max_connections > 0.8
   for:5m
   labels:
    severity:warning
    team:dba
   annotations:
    summary:"MySQL{{ $labels.instance }}连接数使用率{{ $value | humanizePercentage }}"

-name:redis_alerts
 rules:
  -alert:RedisDown
   expr:redis_up==0
   for:1m
   labels:
    severity:critical
    team:dba
   annotations:
    summary:"Redis{{ $labels.instance }}宕机"

  -alert:RedisMemoryHigh
   expr:|
     redis_memory_used_bytes / redis_memory_max_bytes > 0.85
   for:5m
   labels:
    severity:warning
    team:dba
   annotations:
    summary:"Redis{{ $labels.instance }}内存使用率{{ $value | humanizePercentage }}"

  -alert:RedisRejectedConnections
   expr:increase(redis_rejected_connections_total[5m])>0
   for:1m
   labels:
    severity:warning
    team:dba
   annotations:
    summary:"Redis{{ $labels.instance }}出现连接拒绝"

3.1.3 自定义钉钉通知模板

{{/* 文件路径:/etc/alertmanager/templates/dingtalk.tmpl */}}
{{ define"ding.link.title"}}
{{ifeq (index .Alerts0).Labels.severity"critical"}}[P0-严重]{{else}}[P1-警告]{{ end }} {{ .GroupLabels.alertname }} ({{ .Alerts |len}}条)
{{ end }}

{{ define"ding.link.content"}}
{{ifeq .Status"firing"}}** 告警触发**{{else}}** 告警恢复**{{ end }}

**告警名称**: {{ .GroupLabels.alertname }}
**告警级别**: {{ (index .Alerts0).Labels.severity }}
**告警数量**: {{ .Alerts |len}}条
**触发时间**: {{ (.Alerts.Firing | first).StartsAt.Local.Format"2006-01-02 1505"}}

{{range.Alerts }}
---
**实例**: {{ .Labels.instance }}
**摘要**: {{ .Annotations.summary }}
**详情**: {{ .Annotations.description }}
{{ end }}

[查看详情]({{ .ExternalURL }}/#/alerts?receiver={{ .Receiver | urlquery }})
{{ end }}

3.2 实际应用案例

案例一:告警分级策略落地

场景描述:我们团队把告警分成P0-P3四个级别,不同级别走不同通知渠道和响应时效。这套分级策略跑了两年多,告警疲劳问题基本解决了。

分级标准

级别 定义 通知方式 响应时效 示例
P0 核心服务不可用 电话+短信+钉钉 5分钟内响应 数据库宕机、支付服务挂了
P1 服务降级但可用 钉钉+邮件 15分钟内响应 错误率超5%、延迟超2秒
P2 资源预警 钉钉群 1小时内处理 磁盘85%、内存90%
P3 信息通知 邮件 下个工作日处理 证书30天后过期

实现方式:在告警规则的labels里加severity字段,Alertmanager路由树根据severity分发。

# Alertmanager路由配置片段
route:
group_by:['alertname','cluster']
receiver:'default'
routes:
 -match:
   severity:critical
  receiver:'p0-pager'
  group_wait:10s
  repeat_interval:30m
 -match:
   severity:warning
  receiver:'p1-dingtalk'
  group_wait:30s
  repeat_interval:4h
 -match:
   severity:info
  receiver:'p2-dingtalk'
  group_wait:1m
  repeat_interval:12h
 -match:
   severity:none
  receiver:'p3-email'
  repeat_interval:24h

案例二:企业微信Webhook告警脚本

场景描述:部分团队用企业微信而不是钉钉,Alertmanager原生不支持企微,需要通过Webhook中转。我们写了个轻量的Python脚本做格式转换。

实现代码

#!/usr/bin/env python3
# 文件名:/opt/scripts/wecom_webhook.py
# 功能:接收Alertmanager Webhook,转发到企业微信机器人
# 启动:python3 /opt/scripts/wecom_webhook.py

importjson
importrequests
fromflaskimportFlask, request

app = Flask(__name__)

WECOM_WEBHOOK_URL ="https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_WECOM_KEY"

@app.route('/webhook', methods=['POST'])
defwebhook():
  data = request.json
  status = data.get('status','unknown')
  alerts = data.get('alerts', [])

 ifstatus =='firing':
    color ="warning"
    title =f"告警触发 ({len(alerts)}条)"
 else:
    color ="info"
    title =f"告警恢复 ({len(alerts)}条)"

  content_lines = [f"##{title}
"]
 foralertinalerts[:10]: # 最多显示10条
    labels = alert.get('labels', {})
    annotations = alert.get('annotations', {})
    content_lines.append(f"**{labels.get('alertname','N/A')}**")
    content_lines.append(f"> 实例:{labels.get('instance','N/A')}")
    content_lines.append(f"> 级别:{labels.get('severity','N/A')}")
    content_lines.append(f"> 摘要:{annotations.get('summary','N/A')}
")

  payload = {
   "msgtype":"markdown",
   "markdown": {
     "content":"
".join(content_lines)
    }
  }

  resp = requests.post(WECOM_WEBHOOK_URL, json=payload, timeout=10)
 returnjson.dumps({"status":"ok","wecom_response": resp.status_code})

if__name__ =='__main__':
  app.run(host='0.0.0.0', port=8065)

运行结果

告警触发 (2条)

NodeCPUHigh
> 实例: 10.0.1.12:9100
> 级别: warning
> 摘要: 10.0.1.12:9100 CPU使用率 92.3%

NodeMemoryHigh
> 实例: 10.0.1.12:9100
> 级别: warning
> 摘要: 10.0.1.12:9100 内存使用率 94.1%

四、最佳实践和注意事项

4.1 最佳实践

4.1.1 性能优化

告警规则分组评估:把相关的告警规则放在同一个group里,Prometheus会并行评估不同group。我们把600多条规则分成了12个group,评估耗时从3.2秒降到了0.8秒。

# 查看规则评估耗时
curl -s'http://localhost:9090/api/v1/query?query=prometheus_rule_group_duration_seconds{quantile="0.99"}'| jq .

避免在告警规则中使用高开销PromQL:count()、group_left、label_replace这些操作在大数据量下很耗CPU。能用Recording Rules预聚合的先聚合,告警规则里直接查预聚合后的指标。

合理设置evaluation_interval:默认15秒评估一次,600条规则每次评估都要跑一遍PromQL。如果规则不需要那么高的时效性,可以在group级别设置更长的interval。比如磁盘空间告警,60秒评估一次完全够用。

Alertmanager通知去重:group_by的选择直接影响告警合并效果。按['alertname', 'cluster']分组,同一个集群同一类告警会合并成一条通知。别把instance放进group_by,不然每台机器单独发一条,网络故障时钉钉群直接被刷屏。

4.1.2 安全加固

Alertmanager开启Basic Auth:和Prometheus一样,Alertmanager也支持web.yml配置认证。裸奔的Alertmanager任何人都能创建静默规则,等于能让告警失效。

# /etc/alertmanager/web.yml
basic_auth_users:
admin:$2a$12$KmR3iR5eJx5Oj5Yl5FpNOuJGQwMOsKOqJ7Mcp7hVQ8sKqGzLkjS6

Webhook地址用内网:钉钉/企微的Webhook转发服务只监听内网地址,不要暴露到公网。Webhook URL里包含access_token,泄露了别人就能往你的群里发消息。

告警通知脱敏:告警内容里不要包含敏感信息,比如数据库连接串、密码、内网IP段。通过模板控制输出内容,只展示必要的诊断信息。

静默规则审计:定期检查Alertmanager的静默规则,防止有人创建了永久静默忘记删除。我们写了个脚本每天扫描一次,超过7天的静默规则自动告警通知。

4.1.3 高可用配置

Alertmanager集群模式:生产环境至少部署3个Alertmanager实例,通过gossip协议同步状态。Prometheus配置里写上所有实例地址,任何一个挂了不影响告警通知。

# 实例1
alertmanager --cluster.listen-address=0.0.0.0:9094 
 --cluster.peer=10.0.1.51:9094 --cluster.peer=10.0.1.52:9094

# 实例2
alertmanager --cluster.listen-address=0.0.0.0:9094 
 --cluster.peer=10.0.1.50:9094 --cluster.peer=10.0.1.52:9094

# 实例3
alertmanager --cluster.listen-address=0.0.0.0:9094 
 --cluster.peer=10.0.1.50:9094 --cluster.peer=10.0.1.51:9094

通知渠道冗余:critical级别的告警至少配两个通知渠道。我们的做法是钉钉+电话,钉钉挂了电话还能打通。曾经钉钉API故障了2小时,全靠电话通知兜底。

备份策略:Alertmanager的静默规则和通知状态存在--storage.path目录下,定期备份这个目录。

4.2 注意事项

4.2.1 配置注意事项

WARNING:告警配置改错了可能导致关键告警丢失,后果比监控挂了还严重。

for参数不要设成0m,除非你确定这个告警不会有瞬时抖动。我们有个同事把CPU告警的for设成0,结果每天收到上百条CPU毛刺告警,一周后整个团队都对告警通知免疫了。

continue: true要谨慎使用。设了continue后告警会继续匹配下一条路由,可能导致同一条告警发到多个渠道。除非你确实需要多渠道通知,否则别加。

抑制规则的equal字段必须精确匹配。如果source和target的label名称不一致,抑制不会生效,而且不会报错。

4.2.2 常见错误

错误现象 原因分析 解决方案
告警规则配了但从不触发 PromQL表达式有误或for时间太长 在Prometheus UI手动执行表达式验证
同一条告警重复收到通知 group_by配置不当导致分组过细 检查group_by字段,减少分组维度
告警恢复通知没收到 receiver没配send_resolved: true 在webhook_configs里加上send_resolved
Alertmanager集群状态不同步 gossip端口不通或网络分区 检查9094端口连通性和防火墙规则
钉钉通知发送失败 access_token过期或IP白名单限制 检查钉钉机器人配置和安全设置

4.2.3 兼容性问题

版本兼容:Alertmanager 0.27对配置文件格式做了一些调整,match和match_re在未来版本会被matchers替代。建议新项目直接用matchers语法。

平台兼容:钉钉机器人2023年后强制要求加签或IP白名单,老的Webhook URL直接用会返回310000错误码。企业微信机器人对消息格式有长度限制,markdown内容超过4096字节会被截断。

组件依赖:prometheus-webhook-dingtalk 2.x版本要求Go 1.19+编译,低版本系统可能需要手动编译。

五、故障排查和监控

5.1 故障排查

5.1.1 日志查看

# 查看Alertmanager日志
sudo journalctl -u alertmanager -f --no-pager

# 查看最近的错误
sudo journalctl -u alertmanager --since"1 hour ago"| grep -i"error|warn"

# 查看钉钉Webhook转发服务日志
sudo journalctl -u dingtalk-webhook -f --no-pager

5.1.2 常见问题排查

问题一:告警规则配了但不触发

# 检查规则是否被Prometheus加载
curl -s http://localhost:9090/api/v1/rules | jq'.data.groups[].rules[] | select(.name=="NodeCPUHigh")'

# 手动执行告警表达式,看是否有返回值
curl -s'http://localhost:9090/api/v1/query?query=1-avg+by(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m]))>0.85'| jq .

# 检查for条件是否满足(pending状态说明条件满足但还没到for时间)
curl -s http://localhost:9090/api/v1/alerts | jq'.data.alerts[] | select(.labels.alertname=="NodeCPUHigh")'

解决方案

先在Prometheus UI的Graph页面手动执行PromQL,确认有数据返回

检查for时间是否太长,临时改短测试

检查label是否匹配,job名、instance格式是否和实际一致

问题二:告警触发了但通知没收到

# 检查Alertmanager是否收到了告警
curl -s http://localhost:9093/api/v2/alerts | jq'.[0:5]'

# 检查路由匹配结果
amtool --alertmanager.url=http://localhost:9093 config routestest
 severity=warning alertname=NodeCPUHigh

# 检查是否被静默规则屏蔽
amtool --alertmanager.url=http://localhost:9093 silence query

# 检查是否被抑制
curl -s http://localhost:9093/api/v2/alerts | jq'.[] | select(.status.state=="suppressed")'

解决方案

确认Prometheus配置了正确的Alertmanager地址

用amtool测试路由匹配,确认告警能匹配到正确的receiver

检查静默规则和抑制规则是否误伤

问题三:Alertmanager集群脑裂

# 查看集群成员状态
curl -s http://localhost:9093/api/v2/status | jq'.cluster'

# 检查gossip端口连通性
nc -zv 10.0.1.51 9094
nc -zv 10.0.1.52 9094

# 查看集群日志中的gossip相关信息
journalctl -u alertmanager | grep -i"gossip|cluster|peer"

解决方案

确认9094端口TCP和UDP都放通了,gossip协议两个都用

检查各实例的--cluster.peer参数是否正确

如果网络分区导致脑裂,恢复网络后集群会自动合并

5.1.3 调试模式

# Alertmanager开启debug日志
# 修改systemd服务,添加 --log.level=debug
sudo systemctl edit alertmanager
# 添加 ExecStart 覆盖

# 查看告警路由匹配过程
amtool --alertmanager.url=http://localhost:9093 config routes show

# 测试特定告警的路由匹配
amtool --alertmanager.url=http://localhost:9093 config routestest
 alertname=NodeDown severity=critical instance=10.0.1.10:9100

5.2 性能监控

5.2.1 关键指标监控

# Alertmanager通知发送成功率
curl -s'http://localhost:9093/metrics'| grep alertmanager_notifications_total

# 通知发送延迟
curl -s'http://localhost:9093/metrics'| grep alertmanager_notification_latency

# 当前活跃告警数
curl -s'http://localhost:9093/api/v2/alerts?active=true'| jq'length'

# Prometheus规则评估耗时
curl -s'http://localhost:9090/metrics'| grep prometheus_rule_group_duration

5.2.2 监控指标说明

指标名称 正常范围 告警阈值 说明
alertmanager_notifications_failed_total 0 >0 通知发送失败计数
alertmanager_notification_latency_seconds <5s >30s 通知发送延迟
prometheus_rule_group_duration_seconds <1s >5s 规则组评估耗时
prometheus_rule_evaluation_failures_total 0 >0 规则评估失败数
alertmanager_alerts 根据规模定 >500 活跃告警数量

5.2.3 Alertmanager自监控告警规则

# 文件路径:/etc/prometheus/rules/alertmanager_self_rules.yml
groups:
-name:alertmanager_self
 rules:
  -alert:AlertmanagerDown
   expr:up{job="alertmanager"}==0
   for:1m
   labels:
    severity:critical
   annotations:
    summary:"Alertmanager{{ $labels.instance }}宕机"

  -alert:AlertmanagerNotificationFailed
   expr:increase(alertmanager_notifications_failed_total[5m])>0
   for:1m
   labels:
    severity:critical
   annotations:
    summary:"Alertmanager通知发送失败"
    description:"集成{{ $labels.integration }}发送失败"

  -alert:AlertmanagerClusterMemberDown
   expr:alertmanager_cluster_members<3
        for:5m
        labels:
          severity:warning
        annotations:
          summary:"Alertmanager集群成员数不足3"

5.3 备份与恢复

5.3.1 备份策略

#!/bin/bash
# 文件名:/opt/scripts/alertmanager_backup.sh
# 备份Alertmanager配置和状态数据

BACKUP_DIR="/data/backup/alertmanager"
DATE=$(date +%Y%m%d)

mkdir -p"${BACKUP_DIR}"

# 备份配置文件
tar czf"${BACKUP_DIR}/alertmanager_config_${DATE}.tar.gz"
  /etc/alertmanager/ 
  /etc/prometheus/rules/

# 备份状态数据(静默规则等)
tar czf"${BACKUP_DIR}/alertmanager_data_${DATE}.tar.gz"
  /var/lib/alertmanager/

# 清理30天前的备份
find"${BACKUP_DIR}"-name"*.tar.gz"-mtime +30 -delete

5.3.2 恢复流程

停止服务:sudo systemctl stop alertmanager

恢复配置:tar xzf /data/backup/alertmanager/alertmanager_config_20241215.tar.gz -C /

恢复数据:tar xzf /data/backup/alertmanager/alertmanager_data_20241215.tar.gz -C /

重启服务:sudo systemctl start alertmanager

六、总结

6.1 技术要点回顾

告警规则的for参数是过滤误报的关键手段。CPU/内存类告警设5分钟,服务宕机类设1-2分钟,磁盘预测类设10分钟,这是我们反复调优后的经验值。

Alertmanager的路由树设计决定了告警通知的效率。按severity分级路由,配合group_by做告警合并,能把日均300条告警收敛到30条有效通知。

抑制规则能大幅减少告警风暴。节点宕机时自动抑制该节点上所有服务告警,一次网络故障从80条告警收敛到3条通知。

告警分级策略(P0-P3)是告警治理的基础。不同级别走不同通知渠道和响应时效,避免所有告警一视同仁导致的告警疲劳。

通知渠道要做冗余,critical级别至少配两个渠道。钉钉API故障时电话通知兜底,这个设计救过我们好几次。

6.2 进阶学习方向

告警自愈(Auto-Remediation):告警触发后自动执行修复脚本,比如磁盘满了自动清理日志、服务挂了自动重启。可以通过Webhook对接自动化平台实现。

实践建议:从简单的场景开始,比如自动重启崩溃的服务,逐步扩展到更复杂的自愈场景

AIOps智能告警:基于历史告警数据做异常检测,替代固定阈值。Prometheus的predict_linear是最简单的预测函数,更复杂的可以对接外部ML模型。

实践建议:先用predict_linear做磁盘和流量预测,积累经验后再考虑引入ML模型

OnCall轮值管理:配合PagerDuty或自建OnCall系统,实现告警自动分派和升级。值班人员15分钟没响应自动升级给主管。

6.3 参考资料

Alertmanager官方文档 - 配置参数和路由规则详解

Awesome Prometheus Alerts - 社区告警规则集合

prometheus-webhook-dingtalk - 钉钉通知转发工具

PromQL备忘单 - 告警表达式编写参考

附录

A. 命令速查表

# Alertmanager操作
amtool check-config /etc/alertmanager/alertmanager.yml # 检查配置语法
amtool --alertmanager.url=http://localhost:9093 alert query # 查看活跃告警
amtool --alertmanager.url=http://localhost:9093 silence add 
 alertname=NodeCPUHigh -d 2h -c"计划维护"      # 创建2小时静默
amtool --alertmanager.url=http://localhost:9093 silence query # 查看静默规则
amtool --alertmanager.url=http://localhost:9093 silence expire  # 删除静默

# 告警规则操作
promtool check rules /etc/prometheus/rules/*.yml     # 检查规则语法
promtooltestrules test_rules.yml            # 单元测试告警规则
curl -X POST http://localhost:9090/-/reload       # 热重载规则

B. 配置参数详解

Alertmanager路由参数

参数 默认值 说明
group_by [] 告警分组依据的label列表
group_wait 30s 新告警组等待合并的时间
group_interval 5m 同组告警发送间隔
repeat_interval 4h 已发送告警重复通知间隔
continue false 匹配后是否继续匹配下一条路由
match - 精确匹配label
match_re - 正则匹配label
receiver - 接收器名称

C. 术语表

术语 英文 解释
告警规则 Alert Rule 基于PromQL表达式定义的告警条件,由Prometheus评估
路由树 Route Tree Alertmanager中告警分发的树状匹配结构
分组 Grouping 将相同label的告警合并为一条通知发送
抑制 Inhibition 当某条告警触发时自动屏蔽相关的其他告警
静默 Silence 在指定时间窗口内屏蔽匹配条件的告警通知
接收器 Receiver 告警通知的目标渠道配置(邮件、Webhook等)
去重 Deduplication Alertmanager集群中避免同一告警被多次通知的机制
for持续时间 For Duration 告警条件需要持续满足的时间,用于过滤瞬时抖动

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 容器
    +关注

    关注

    0

    文章

    535

    浏览量

    23024
  • Prometheus
    +关注

    关注

    0

    文章

    36

    浏览量

    2072

原文标题:企业级监控告警落地:Prometheus 规则分层与 Alertmanager 通知编排

文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Prometheus的基本原理与开发指南

    PromQL高级实战 告警引擎深度解析 本地存储与远程存储 梯度运维管理平台监控模块架构 01监控系统概述 导读:本章从监控的作用、架构分类、指标监控发展史、指标监控典型架构等4个方面介绍监控系统的相关概念。 1.1.监控的作用 ★ 为了构建稳定性保障体系,核心就是在干
    的头像 发表于 11-09 10:45 2353次阅读
    <b class='flag-5'>Prometheus</b>的基本原理与开发指南

    IR615配置流量告警方法

    ;gt;告警 新建规则 配置告警规则如下: 测试:电脑连接路由器lan口,访问百度等页面,使流量超出阀值. 在路由器
    发表于 07-25 07:59

    基于人工智能的网络告警关联分析处理方法

    方法之一,告警相关性分析采用的方法有很多,例如基于规则告警相关性分析、基于事例的告警相关性分析、基于因果模型的相关性分析、基于神经网络的相关性分析等。但是这些方法都存在一定的缺点,例
    发表于 12-03 15:13

    prometheus做监控服务的整个流程介绍

    )>0更多:PromQL告警告警的流程大致就是:在prometheus中通过PromQL配置告警规则,如果
    发表于 12-23 17:34

    编写PCB设计规则检查器技巧

    编写PCB设计规则检查器技巧   本文阐述了一种编写PCB设计规则检查器(DRC)系统方法。利用电路图生成工具得到PCB设计后,即可运
    发表于 11-17 14:03 1218次阅读

    编写属于自己的PCB设计规则检查器

    编写属于自己的PCB设计规则检查器 编写属于自己的PCB设计规则检查器具有很多优点,尽管设计检查器并不那么简单,但也并非高不可攀,因为任何熟悉现有编程或脚本
    发表于 12-27 13:31 1053次阅读
    <b class='flag-5'>编写</b>属于自己的PCB设计<b class='flag-5'>规则</b>检查器

    加权增量关联规则挖掘在通信告警预测中的应用说明

    针对通信网络告警预测中预测精度不高、模型训练效率较低等缺陷,提出告警权值确定方法和基于自然序树( Can-tree)的加权增量关联规则挖掘的通信网络告警预测方案。首先,对
    发表于 12-12 11:49 2次下载
    加权增量关联<b class='flag-5'>规则</b>挖掘在通信<b class='flag-5'>告警</b>预测中的应用说明

    Prometheus服务监控系统

    prometheus.zip
    发表于 04-26 10:23 3次下载
    <b class='flag-5'>Prometheus</b>服务监控系统

    prometheus-book Prometheus操作指南

    ./oschina_soft/prometheus-book.zip
    发表于 05-16 09:11 5次下载
    <b class='flag-5'>prometheus</b>-book <b class='flag-5'>Prometheus</b>操作指南

    可视化操作的告警软件背景现状

    在云原生的生态下,kubernetes 已经被越来越多地应用到公司实际生产环境中。在这样的生态环境下系统监控、业务监控和数据库监控指标都需要在第一时间获取到,目前用的最多的也是prometheus、exporter、grafana、alertmanager这几个软件组建起
    的头像 发表于 10-11 09:49 1335次阅读

    Prometheus API使用介绍

    做为一位优秀的技术人员,往往能通过对数据的最大化利用来产生更多价值。而Prometheus的监控数据则是可以为我们所用的重要数据,它并不只能用于日常的监控和告警使用,也可以用于数据分析、成本管理等企业需求。
    的头像 发表于 10-31 09:23 4430次阅读

    系统监控相关知识及钉钉机器人告警脚本编写

    今天浩道跟大家分享硬核监控干货,一文带大家学习系统监控相关知识及钉钉机器人告警脚本编写
    的头像 发表于 11-18 09:18 1644次阅读

    SpringBoot+Prometheus+Grafana实现自定义监控

    为 /actuator/Prometheus 的 HTTP 服务来供 Prometheus 抓取数据,不过默认该服务是关闭的,该配置将打开所有的 Actuator 服务。
    的头像 发表于 12-26 16:02 2882次阅读

    prometheus下载安装教程

    Prometheus 是一个开放性的监控解决方案,用户可以非常方便的安装和使用 Prometheus 并且能够非常方便的对其进行扩展。 在Prometheus的架构设计中,Prometheus
    的头像 发表于 01-13 16:07 9997次阅读
    <b class='flag-5'>prometheus</b>下载安装教程

    Prometheus实战篇:Exporter知识概述

    所有可以向Prometheus提供监控样本数据的程序都可以被称为一个Exporter.而Exporter的一个实例称为target,如图下所示
    的头像 发表于 12-25 09:57 2254次阅读
    <b class='flag-5'>Prometheus</b><b class='flag-5'>实战</b>篇:Exporter知识概述