告警与通知
仪表盘做得再漂亮,也没人 7×24 盯着看。监控的闭环在告警:异常发生时主动喊人。Grafana 8 起把老的「面板告警」推倒重做成 Unified Alerting(统一告警),到 10/11/12 已经很成熟:告警规则不再绑死面板、评估引擎内置,还自带一个 Alertmanager 处理通知路由。这篇记录 Grafana 内置告警的完整玩法:规则怎么建、通知怎么发、路由怎么配,以及它和 Prometheus 告警体系怎么分工。Prometheus 侧的告警链路和 Alertmanager 本体的配置(分组、抑制、YAML 写法)见告警规则与 Alertmanager,那篇讲 Alertmanager 本体,这篇只讲 Grafana 内置引擎。
Grafana 告警与 Alertmanager 的关系
Unified Alerting 的架构一句话说清:评估引擎跑在 Grafana 进程里,规则存在 Grafana 数据库(或 provisioning 文件)中,按评估间隔周期性执行;评估产生的 firing 告警交给 Alertmanager 做分组、路由、静默,最后发通知。
关键在于这个 Alertmanager 有两个选择:
- 内置:Grafana 自带一个 Alertmanager,不用单独部署。Contact points、通知策略、静默、消息模板全在 Grafana UI 里配,开箱即用;
- 外部:Alerting → Alertmanagers 页面添加外部 Alertmanager 地址后,Grafana 只负责评估,把 firing 告警转发过去,通知策略交还给外面那套 YAML 管。
和「Prometheus 告警规则 → Alertmanager」这条经典路线对比:
| 对比项 | Prometheus 规则 + Alertmanager | Grafana 内置告警 |
|---|---|---|
| 规则定义 | YAML 规则文件 / PrometheusRule CRD | Grafana UI 配置,或 provisioning 文件 |
| 数据源 | 仅 Prometheus | 任意已接入数据源:Prometheus、Loki、MySQL、ES、CloudWatch |
| 表达式 | 纯 PromQL | 数据源查询 + reduce / threshold / math 表达式组合 |
| 规则管理 | git 管理、声明式、走 PR | UI 操作直观,也可导出 provisioning 进 git |
| 通知处理 | 独立部署的 Alertmanager | 内置 Alertmanager,可切换为外部 |
| 典型场景 | K8s、纯 Prometheus 栈、GitOps | 混数据源告警、小团队快速上手 |
选型建议(实操口径):
- K8s 上交给 operator + Alertmanager:规则写成 PrometheusRule CRD 跟集群同生命周期,声明式、可 GitOps,Grafana 只当看板。这套写法见告警规则与 Alertmanager。
- 混数据源场景用 Grafana 告警:告警条件要查 MySQL 行数、Elasticsearch 日志计数、云厂商监控指标时,Prometheus 管不着这些数据源,Grafana 告警是唯一选项。
- 小团队、虚拟机为主、没有专职运维:Grafana 告警 UI 一把梭,够用,少维护一套 Alertmanager。
创建告警规则
两个入口,殊途同归:
- 从面板创建:面板右上角菜单 → New alert rule,面板查询被预填进规则;
- 从零建:Alerting → Alert rules → New alert rule。
表单分三步(Grafana 11/12 的叫法,10 略有差异但结构相同)。
第一步:查询与表达式。 一条规则 = 「数据查询 + 表达式加工」。查询(Query A)从数据源取数;表达式(Expression B、C……)对查询结果逐层加工,常用的有 Reduce(把时序压成单值)和 Threshold(阈值判断);多个查询要算在一起时用 Math。最后指定哪个表达式作为告警条件。
以「内存使用率超 85%」为例。Query A(Prometheus 数据源):
100 * (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)
然后加两个表达式:
- Expression B:Reduce,Input 选 A,Function 选 Last,Mode 保持 Strict——把每台机器的时间序列压成「当前值」一个数字;
- Expression C:Threshold,Input 选 B,条件 IS ABOVE
85,并把 C 设为告警条件(Set as alert condition)。
第二步:评估行为。
- Evaluation group:规则分组,同组共享评估间隔(默认 1m)。间隔别贪短,每次评估都要查数据源,一堆 10s 间隔的规则能把 Prometheus 和 Grafana 一起拖慢;
- Pending period:等价于 Prometheus 规则里的
for——条件连续成立满这个时长才从 pending 转 firing。防抖核心,基础设施类告警 5m 起步,不设的话指标抖一下就喊一次人。
第三步:标签与摘要。
- Labels:
severity: warning、team: infra——后面通知策略的路由全靠标签,建规则时就打规范; - Annotations:summary、description、runbook_url,支持模板引用标签和值:
summary: 实例 {{ $labels.instance }} 内存使用率超 85%
description: {{ $labels.instance }} 内存使用率已连续 5 分钟高于 85%,请按 runbook 处理
文案写人话:半夜三点被叫醒的人看一眼 summary 就该知道是哪台机器、什么问题。保存后规则出现在 Alert rules 列表,状态按 Normal → Pending → Firing 流转。
从面板创建规则时,Grafana 会把面板查询复制进规则(之后改面板查询不影响规则,两边各改各的)。高效姿势:先在仪表盘里把查询调到曲线符合预期,再从面板 New alert rule 预填,少写一遍表达式。
Contact points 通知渠道
Alerting → Contact points,一个 contact point 就是一个通知渠道(底下可挂多个 integration)。
Webhook(万能姿势):URL 填接收端,Grafana 把告警按固定 JSON 结构 POST 过去。自建告警网关、接内部 IM、开工单系统都走这条路,可配 HTTP 基础认证和自定义 Header。载荷结构长这样:
{
"receiver": "infra-webhook",
"status": "firing",
"alerts": [
{
"status": "firing",
"labels": {"alertname": "HostHighMemoryUsage", "instance": "10.0.1.11:9100", "severity": "warning"},
"annotations": {"summary": "实例 10.0.1.11:9100 内存使用率超 85%"},
"startsAt": "2026-01-20T02:00:00Z",
"fingerprint": "a1b2c3d4"
}
]
}
钉钉群机器人:内置 DingDing 类型,URL 填机器人的 webhook 地址,加签密钥或关键词按机器人安全设置填,消息内容支持模板自定义。
企业微信:没有开箱即用的专用类型,社区惯例是 Webhook 类型 POST 给一个转换层(几十行的小服务,把 Grafana 的 JSON 翻译成企微 markdown 消息格式再推给群机器人)。能用 webhook 解决就别装第三方插件,少一个升级包袱。
邮件:选 Email 类型填收件人即可,但 SMTP 参数不在 UI 里——在 grafana.ini 的 [smtp] 段(或 GF_SMTP_* 环境变量):
[smtp]
enabled = true
host = smtp.exmail.qq.com:465
user = alert@example.com
password = xxxxxxxx
from_address = alert@example.com
改完重启 Grafana 生效。邮件延迟高、容易被淹没,定位是兜底和存档,第一响应渠道得是能「响」的。
每个 contact point 都有 Test 按钮:发一条测试告警验证渠道通畅。新渠道先点 Test,通了再去配路由——渠道不通时在策略页干等是排查不出东西的。
Notification policies 路由
Alerting → Notification policies,一棵策略树:
- Default policy 是根,所有告警的兜底,没配任何子策略时全部走它;
- 子策略按标签匹配(matcher):
severity = critical的电话值班,team = infra的发 infra 群,从上往下匹配,子策略里还能再嵌套子策略; - 每条策略指定三件事:发给哪个 contact point、按什么标签分组、通知节奏参数。
**分组(group by)**决定哪些告警合成一条通知:按 alertname, instance 分组,同一台机器的同一告警只收一条;一个命名空间集体爆炸,按 namespace 分组收一条汇总而不是五十条刷屏。
三个时间参数控制节奏,语义和 Alertmanager 完全一致:
| 参数 | 含义 | 默认值 | 经验 |
|---|---|---|---|
| group_wait | 新告警组首发前等待,凑齐同组告警 | 30s | 保持默认,改 0 等于放弃聚合、单条轰炸 |
| group_interval | 组内来了新告警,隔多久补发更新 | 5m | 保持默认 |
| repeat_interval | 同一告警一直没恢复,隔多久重复提醒 | 4h | 2h~12h,按团队响应节奏定 |
默认值在根策略上配,子策略可以按需覆盖(Timing options)。
静默与免打扰
Silence(静默) 解决「我知道它在报,别烦我」:发布窗口、计划内维护、已知问题修复中。Alerting → Silences → Create silence:填标签匹配器(如 namespace = shop)、起止时间、创建人和备注。起止时间内匹配的告警照常评估、照常 firing,但不发通知,到期自动失效。范围能圈小就别整个集群静默;复盘时注意「那段时间没收到通知」不等于「那段时间没问题」,告警页面里记录都在。
Mute timings(免打扰时段) 是长期的周期性时刻表:定义「每天 0:00-7:00」「每周六日」这样的固定时段,挂在某条通知策略上,时段内该策略不发通知,过了自动恢复。和 silence 的分工:silence 是一次性的起止时间,mute timings 是循环排班。典型场景——warning 级告警挂夜间 mute,半夜不推送、早上上班集中看积压,值夜班的同学睡得着;critical 策略不挂 mute,warning 可以等天亮,critical 必须半夜喊得醒人。
和 Alertmanager 的静默一样,silence 和 mute timings 捂住的只是通知的嘴,告警照常触发、照常能在 Alert rules 页面看到。别把「免打扰」当「问题已解决」用。
NoData 与错误处理
查询没数据时,告警该算什么状态?规则设置里的 Configure no data and error handling 两组选项:
- No Data:No Data(进入特殊状态,可单独路由)/ Alerting(没数据就告警)/ OK(视为正常)/ Keep Last(保持上一个状态);
- Error(评估出错,如数据源超时):Error / Alerting / OK / Keep Last,四选一结构相同。
经验值:
- 数据源偶尔抖动(Prometheus 重启、网络闪断):Error 选 Keep Last,避免一次超时刷一批误报;
- 「指标在 = 服务活着」的探活类告警:No Data 选 Alerting——没数据本身就是故障;
- NoData/Error 状态的实例会自动打上
alertname=DatasourceNoData、alertname=DatasourceError标签,可以在通知策略里按 alertname 单独路由(比如发给监控负责人而不是业务值班)。
常见坑
- 告警状态膨胀:一条规则不是一条告警——表达式结果里每条序列生成一个告警实例。查全集群的内存表达式,一条「内存超 85%」规则背后挂着几百个实例,集群一抖就是刷屏。建规则时用表单里的 Preview 看一眼实例数;用
sum by聚合时把标签集收窄到路由需要的维度,别把 pod、container 这种高基数标签留在结果里。 - 通知里标签不全:通知模板写了
{{ .Labels.pod }},但表达式sum by (namespace)聚合后 pod 标签早没了,渲染出来是<no value>。写模板对着告警实例的实际标签集写(规则详情页能看到每个实例的标签)。自定义消息模板的骨架长这样(填在 contact point 的 Optional settings 里):
{{ range .Alerts }}
[{{ .Status }}] {{ .Labels.alertname }}
实例: {{ .Labels.instance }} 级别: {{ .Labels.severity }}
摘要: {{ .Annotations.summary }}
{{ end }}
- repeat_interval 轰炸:它是「告警没恢复就定期再提醒」,不是「发送失败重试」。有人改成 1m,一条不恢复的告警每分钟刷一次,通道信噪比直接崩;反向极端设成 7d,挂了三天没人记得。保持 2h~12h。
- 内置 Alertmanager 的高可用:单实例 Grafana 不用操心;多实例部署时每个 Grafana 都在独立评估和发通知,会重复告警,需要配告警 HA(成员发现 + 通知去重)或直接对接外部 Alertmanager 集群——生产上多实例前把这块想清楚,细节见官方 HA 文档,这里一句带过。
小结
- Grafana 告警 = 内置评估引擎 + 内置 Alertmanager,能独立成军,也能转发外部 Alertmanager;K8s 声明式管理走 PrometheusRule + 独立 Alertmanager,混数据源和小团队用 Grafana 告警。
- 建规则三步:查询 + reduce/threshold 表达式 → 评估间隔与 pending 时长 → 标签与摘要;先在面板把查询调对再建规则。
- Contact point 定义渠道:webhook 万能、钉钉内置、企微走转换层、邮件靠 grafana.ini 配 SMTP;每个渠道先 Test 再上线。
- Notification policy 按标签路由,
group by聚合,group_wait/group_interval/repeat_interval控节奏。 - 静默是一次性豁免,mute timings 是循环免打扰;两者都只压通知、不压评估。
- NoData/Error 状态单独配置:探活类选 Alerting,数据源抖动选 Keep Last。
- 防轰炸三件套:pending 防抖、分组聚合、repeat_interval 别太短。
至此,从数据源接入、仪表盘制作、变量模板到告警通知,一条最小可用的 Grafana 可观测链路就齐了。剩下的就是把它跑在自己的基础设施上,在真实的告警里把阈值和节奏调到顺手。