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的基本原理与开发指南
基于人工智能的网络告警关联分析处理方法
编写PCB设计规则检查器技巧
编写属于自己的PCB设计规则检查器
加权增量关联规则挖掘在通信告警预测中的应用说明
可视化操作的告警软件背景现状
Prometheus API使用介绍
SpringBoot+Prometheus+Grafana实现自定义监控
prometheus下载安装教程
Prometheus告警规则编写与Alertmanager通知配置实战
评论