PrometheusRule告警

PrometheusRule告警实战

1.PrometheusRule告警规则

PrometheusRulePrometheus Operator 提供的一种 Kubernetes 自定义资源(CRD),用来在 Kubernetes 中以声明式的方式管理 Prometheus 的告警规则。

Prometheus Operator 会监听 PrometheusRule,根据 Prometheus 资源的 ruleSelectorruleNamespaceSelector 选择规则,再把选中的规则加载到 Prometheus。

简单说:PrometheusRule 就是放在 Kubernetes 里的“Prometheus 告警规则”配置文件。

可以通过如下命令查看默认配置的告警策略:

1
2
3
4
5
6
7
8
9
10
[root@k8s-master01 30-Prometheus]# kubectl get prometheusrules -n monitoring
NAME AGE
alertmanager-main-rules 315d
grafana-rules 315d
kube-prometheus-rules 315d
kube-state-metrics-rules 315d
kubernetes-monitoring-rules 315d
node-exporter-rules 315d
prometheus-k8s-prometheus-rules 315d
prometheus-operator-rules 315d

也可以通过-oyaml 查看某个 rules 的详细配置:

1
kubectl get prometheusrules -n monitoring node-exporter-rules -oyaml

下面是一个标准的 PrometheusRule 资源配置案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: monitoring.coreos.com/v1  #指定资源所属的 API 组和版本。
kind: PrometheusRule #指定 Kubernetes 资源类型。
metadata:
name: my-custom-alerts #指定资源的名字是my-custom-alerts
namespace: monitoring #资源所在的命名空间
#labels: #定义该资源的标签,必须匹配 Prometheus 的 ruleSelector,不然Prometheus不会加载该资源,因为Prometheus中定义的是 ruleSelector: {},表示匹配所有,所以这里不写也可以。
#prometheus: k8s
#role: alert-rules
spec: #是资源的期望状态,是 PrometheusRule 的核心配置。它描述要创建哪些规则组和具体规则。
groups: #定义规则组列表
- name: my-node-alerts #组名,自定义,同一 PrometheusRule 内唯一
rules: # 定义具体规则的列表
- alert: InstanceDown #报警的名字
expr: up{ job="node-exporter"} == 0 #Expression的缩写,表达式,触发报警的核心逻辑(固定语法,PromQL 查询语言)
for: 5m #持续时间,这个异常状态持续了5分钟还没有恢复,告警才从pending变为firing,才真正触发报警
labels: # # 定义报警携带的标签(会传给 Alertmanager,用于路由)
severity: critical # 调度中心就是靠这些标签来决定发给谁的。
team: ops
annotations: # 定义报警的详细描述文本
summary: "实例 {{ $labels.instance }} 宕机" #定义该报警简要说明
description: "该实例已经失去连接超过 5 分钟,请立即检查。" #定义该报警的详细说明
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# Prometheus Operator 提供的 PrometheusRule CRD 的 API 版本。
# 集群中必须已安装 prometheusrules.monitoring.coreos.com CRD。
apiVersion: monitoring.coreos.com/v1

# 声明这是一个 PrometheusRule 资源,用于定义告警规则或记录规则。
kind: PrometheusRule

# Kubernetes 对象的通用元数据。
metadata:
# 当前 PrometheusRule 对象的名称。
# 必须在 monitoring 命名空间内唯一,不需要与 Prometheus 或 ServiceMonitor 同名。
name: my-custom-alerts

# 当前资源所在的 Kubernetes 命名空间。
# 该命名空间必须被 Prometheus CR 的 spec.ruleNamespaceSelector 选中。
namespace: monitoring

# 当前 Kubernetes 对象的标签。
# 这些标签用于匹配 Prometheus CR 的 spec.ruleSelector,
# 不会自动成为告警事件的标签。
#
# 如果 Prometheus 的 ruleSelector 要求以下标签,则必须取消注释。
# 如果 ruleSelector: {} 并且命名空间也在选择范围内,通常可以省略。
# labels:
# prometheus: k8s
# role: alert-rules

# PrometheusRule 的规则定义。
spec:
# 规则组列表,可以按基础设施、组件或业务拆分成多个规则组。
groups:
# 规则组名称,用于在 Prometheus 中识别和管理这一组规则。
# 不需要匹配其他 Kubernetes 资源名称,建议保持清晰且尽量唯一。
- name: my-node-alerts

# 当前规则组中的规则列表。
# 使用 alert 字段的是告警规则;使用 record 字段的是记录规则。
rules:
# 告警名称。
# 告警触发后会生成 alertname="InstanceDown" 标签,
# Alertmanager 可以根据 alertname 进行路由、分组或静默。
- alert: InstanceDown

# PromQL 告警表达式。
# up=0 表示 Prometheus 最近一次抓取该目标失败。
# job="node-exporter" 必须与 Prometheus 中真实的 job 标签值一致。
# 可通过 count by (job) (up) 查询实际 job 标签。
expr: up{job="node-exporter"} == 0

# 表达式连续成立 5 分钟后,告警才从 pending 进入 firing。
# 用于过滤短暂网络抖动、进程重启等瞬时故障。
for: 5m

# 附加到告警实例上的标签,并发送给 Alertmanager。
# 应与 Alertmanager 的 route、inhibit_rules 和静默规范保持一致。
labels:
# 告警严重级别。该值不是 Prometheus 固定枚举,
# 但必须与组织的告警分级和 Alertmanager 路由配置一致。
severity: critical

# 告警责任团队。Alertmanager 可以通过 team="ops" 路由到运维团队。
team: ops

# 供通知接收者阅读的告警说明。
# 通常由 Alertmanager 通知模板读取,不建议用于路由。
annotations:
# 告警简要摘要。
# $labels.instance 来自 expr 查询结果中的 instance 标签。
summary: "Node Exporter 采集目标 {{ $labels.instance }} 不可达"

# 告警详细描述。加入 job 和 instance,方便快速定位目标。
# “抓取失败”不一定代表主机宕机,也可能是网络或 exporter 故障。
description: "Prometheus 已连续 5 分钟无法抓取 job={{ $labels.job }}、instance={{ $labels.instance }},请检查目标状态、Node Exporter、网络和抓取配置。"

使用kubectl create -f创建资源后要在 Prometheus页面 的 Status / Rules 确认 my-node-alertsInstanceDown 已被加载。仅仅 kubectl apply 成功,不代表 Prometheus 已经选择并加载了该规则。

2.实现域名监控告警

在实际的生产环境中,域名的可访问性和延迟性两者都需要监控,但它们的紧急程度和关注点不同。可以把它们分为两类:

🔴 **完全宕机 (可用性监控)**:比如网站返回了 502 错误,或者根本连不上。这属于“致命级别 (Critical)”,因为用户完全无法使用。

🟡 **访问延迟 (性能监控)**:比如网站还能打开,但加载需要 5 秒钟。这通常属于“警告级别 (Warning)”,因为它严重影响了用户体验,且可能是系统即将崩溃的前兆。

下面以对域名访问延迟进行监控,访问延迟大于 5 秒进行告警,此时可以创建一个 PrometheusRule 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
cat >blackbox-rule.yaml<<EOF
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: blackbox
namespace: monitoring
labels:
prometheus: k8s
role: alert-rules
spec:
groups:
- name: blackbox-exporter
rules:
# 🔴 规则 1:域名完全不可访问 (致命级别)
- alert: WebsiteDown
expr: probe_success{ job="web-probe" } == 0
for: 1m
labels:
severity: critical
team: web
annotations:
summary: "网站 {{ $labels.instance }} 无法访问 🚨"
description: "该网站已连续 1 分钟无法连接 (当前状态值为 {{ $value }}),请立刻处理!"
# 🟡 规则 2:访问延迟过高 (警告级别)
- alert: HighLatency
expr: probe_duration_seconds{ job="web-probe"} > 5
for: 2m
labels:
severity: warning
team: web
annotations:
summary: "网站 {{ $labels.instance }} 访问延迟过高 🐢"
description: "该网站加载时间已超过 5 秒 (当前耗时为 {{ $value }} 秒),请检查服务性能。"
EOF

创建上述资源:

1
2
3
4
5
6
7
8
#创建
[root@k8s-master01 PrometheusRule]# kubectl create -f blackbox-rule.yaml
prometheusrule.monitoring.coreos.com/blackbox created

# 查看
[root@k8s-master01 PrometheusRule]# kubectl get prometheusrules.monitoring.coreos.com -n monitoring
NAME AGE
blackbox 47s

之后通过Prometheus的web界面Status/Rules中查看是否加载该规则,如下图表示规则配置正常,不代表告警服务正常:

有没有产生告警要在Alerts中看,如下图,已经产生告警:

需要特别注意:

  • metadata.labels 必须匹配 Prometheus CR 的 spec.ruleSelector
  • monitoring 命名空间必须被 Prometheus CR 的 spec.ruleNamespaceSelector 选中。
  • probe_successprobe_duration_seconds 通常来自 Blackbox Exporter。

带注释的详细版本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# 指定 PrometheusRule 使用的 API 组和版本。
# 集群中必须安装 Prometheus Operator 及 PrometheusRule CRD。
apiVersion: monitoring.coreos.com/v1
# 指定 Kubernetes 资源类型,PrometheusRule 用于声明 Prometheus 告警规则和记录规则。
kind: PrometheusRule
# Kubernetes 资源的元数据。
metadata:
# PrometheusRule 资源名称,在同一个命名空间内必须唯一。
# 该名称不需要与 Prometheus、Blackbox Exporter 或 ServiceMonitor 的名称一致。
name: blackbox
# PrometheusRule 所在的 Kubernetes 命名空间。
namespace: monitoring
# Kubernetes 对象标签。
# 这些标签用于匹配 Prometheus CR 的 spec.ruleSelector。
# 它们与告警规则中的 labels 不同:
# 1. metadata.labels:
# 用于 Prometheus 选择和加载 PrometheusRule 资源。
# 2. spec.groups[].rules[].labels:
# 用于给告警添加标签,并传递给 Alertmanager 做路由、分组、静默和抑制。
# 例如,Prometheus CR 如果配置为:
# spec:
# ruleSelector:
# matchLabels:
# prometheus: k8s
# role: alert-rules
#
# 那么本资源必须具有下面两个标签。
labels:
# Prometheus CR 的 ruleSelector 需要匹配的标签。
# 该值必须与 ruleSelector 中 prometheus 的值一致。
prometheus: k8s
# Prometheus CR 的 ruleSelector 需要匹配的标签。
# 该值必须与 ruleSelector 中 role 的值一致。
role: alert-rules
# PrometheusRule 的具体配置。
# spec 中定义要交给 Prometheus 加载的规则。
spec:
# Prometheus 规则组列表。
# 每个规则组由一个 name 和一个 rules 列表组成。
groups:
# 规则组名称。
# 用于在 Prometheus 的 Rules 页面、API 和日志中标识该规则组。
# 建议名称具有明确业务含义,并尽量避免在多个规则文件中重复。
- name: blackbox-exporter
# 当前规则组中的 Prometheus 规则列表。
# 使用 alert 字段定义告警规则;
# 使用 record 字段定义记录规则。
rules:
# 规则 1:网站或探测目标不可访问。
- alert: WebsiteDown
# PromQL 告警表达式。
# probe_success 是 Blackbox Exporter 常见的探测结果指标:
# 1 表示探测成功;
# 0 表示探测失败。
# 当前写法会匹配所有 probe_success == 0 的目标。
# 如果 Prometheus 中还有其他类型的 Blackbox 探测任务,
# 可能会把非网站探测目标也纳入该告警。
# 如果只监控 web-probe,建议改为:
# expr: probe_success{job="web-probe"} == 0
# 其中 job 的实际值必须与 Prometheus 中的 job 标签一致。
expr: probe_success{job="web-probe"} == 0
# 表达式连续满足 1 分钟后,告警才进入 firing 状态。
# 状态变化通常为:
# inactive -> pending -> firing
# 如果探测失败持续时间不足 1 分钟,告警会恢复为 inactive,
# 不会发送正式告警通知。
for: 1m
# 告警标签。
# 这些标签会附加到生成的告警实例上,并发送给 Alertmanager。
labels:
# 告警严重级别。
# critical 不是 Prometheus 强制规定的固定值,
# 但必须与 Alertmanager 路由配置中的 matcher 保持一致。
# 例如 Alertmanager 可以按以下条件路由:
# severity="critical"
severity: critical
# 告警责任团队。
# Alertmanager 可以根据 team="web" 将告警发送给 Web 团队。
team: web
# 告警注解。
# annotations 主要用于生成通知标题、正文和排障链接。
# 通常不用于 Alertmanager 路由匹配。
annotations:
# 告警简要描述。
# $labels.instance 是当前告警时间序列中的 instance 标签值。
# 对 Blackbox Exporter 来说,它通常代表被探测的目标地址,
# 但最终值取决于 Prometheus 的 relabel_configs 配置。
summary: "网站 {{ $labels.instance }} 无法访问 🚨"
# 告警详细描述。
# $value 是 PromQL 表达式当前的计算结果。
# 对 probe_success == 0 来说,通常为 0。
# 该内容通常会被 Alertmanager 的邮件、企业微信、钉钉、
# 飞书或其他通知模板引用。
description: "该网站已连续 1 分钟无法连接,当前 probe_success 值为 {{ $value }},请检查网站服务、Blackbox Exporter、网络连通性和 DNS。"
# 规则 2:网站访问延迟过高。
- alert: HighLatency
# PromQL 告警表达式。
# probe_duration_seconds 是 Blackbox Exporter 常见的探测耗时指标,
# 单位是秒。
#
# > 5 表示探测耗时超过 5 秒。
# job="web-probe" 用于只匹配网站探测任务。
# 该 job 标签值必须与 Prometheus 中实际采集到的标签一致。
expr: probe_duration_seconds{job="web-probe"} > 5
# 访问延迟必须连续超过 5 秒并持续 2 分钟,
# 告警才会进入 firing 状态。
#
# 该配置可以减少偶发的高延迟或网络瞬时抖动造成的误报。
for: 2m
# 告警标签。
# 这些标签会传递给 Alertmanager,
# 可用于根据严重程度和责任团队进行告警路由。
labels:
# 告警严重级别。
# 此处设置为 warning,表示需要关注但通常不属于立即中断业务的故障。
# Alertmanager 必须使用相同的值进行匹配。
severity: warning
# 告警责任团队。
# 与 WebsiteDown 使用相同的 team 值,
# 表示这两类告警都由 Web 团队负责处理。
team: web
# 告警注解。
# 用于描述告警内容、当前状态和处理方向。
annotations:
# 告警简要标题。
# $labels.instance 表示发生高延迟的探测目标。
summary: "网站 {{ $labels.instance }} 访问延迟过高 🐢"
# 告警详细描述。
# $value 是当前探测耗时,单位为秒。
# 由于表达式条件是 > 5,因此这里的值应大于 5。
description: "网站探测耗时已超过 5 秒,当前耗时为 {{ $value }} 秒,请检查网站服务性能、网络延迟、DNS 和 Blackbox Exporter。"

3.应用服务活性探测告警

针对于基础组件也可以实现活性探测,比如 MySQL 和 Redis 监控,可以通过 up 指标进行监控:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
cat >basic-role.yaml<<EOF
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: database-monitor-alerts
namespace: monitoring
labels:
prometheus: k8s
role: alert-rules
spec:
groups:
- name: database-alerts
rules:
# 🔴 规则 1:MySQL 宕机
- alert: MySQLDown
expr: mysql_up == 0
for: 1m
labels:
severity: critical
team: dba
annotations:
summary: "MySQL 实例 {{ $labels.instance }} 宕机 🚨"
description: "数据库已断开连接超过 1 分钟,请立即排查业务影响!"
# 🔴 规则 2:Redis 宕机
- name: redis-alerts
rules:
- alert: RedisDown
expr: redis_up == 0
for: 1m
labels:
severity: critical
team: dba
annotations:
summary: "Redis 实例 {{ $labels.instance }} 宕机 🚨"
description: "Redis 缓存服务已断开连接超过 1 分钟,请立即排查!"
EOF

创建资源:

1
2
[root@k8s-master01 PrometheusRule]# kubectl create -f basic-role.yaml
prometheusrule.monitoring.coreos.com/database-monitor-alerts created

查看资源:

1
2
3
[root@k8s-master01 PrometheusRule]# kubectl get prometheusrules.monitoring.coreos.com -n monitoring
NAME AGE
database-monitor-alerts 23s

通过Prometheus的web控制台Status/Rules查看到规则:

注意事项:在该博客通过Mysql Exporter采集mysql的数据时,默认报警中 所展示的mysql exporter的地址,语义上存在错误,当收到MySQL宕机报警时是MySQL Exporter的ip,真实的应该是所监控的目标MySQL地址,解决方案见2.1.6步骤

4.基于Grafana面板告警

有很多监控语法可能比较复杂,此时可以借助现有的 Dashboard 编写 PrometheusRule。 比如想要实现主机内存的监控,可以先从面板获取 PromQL 语法:

指标名称 含义 说明
node_memory_MemTotal_bytes 物理总内存 服务器插了多少内存就是多少。
node_memory_MemFree_bytes 绝对空闲内存 完全没被任何进程或内核使用的内存。(数值通常很小,不代表系统缺内存)
node_memory_Cached_bytes 页面缓存 用于缓存文件内容的内存,用来加速读取,需要时可被系统回收
node_memory_Buffers_bytes 缓冲区 用于缓存文件系统元数据等的内存,需要时可被系统回收
node_memory_MemAvailable_bytes 实际可用内存 MemFree + 可回收的 Cached/Buffers。评估系统内存是否紧张的唯一金标准。

接下来结合grafana中主机监控的模板做一个针对内存使用率大于55的告警,我这里为了看到告警所以设置的阈值低,生产根据需求改。

选择指标右上角的三个点,在点击Edit

获取到监控语句,进行稍加改造即可,去掉语句中变量部分:

1
2
3
4
5
6
100 -
(
avg(node_memory_MemAvailable_bytes{job="node-exporter"}) by(instance)/
avg(node_memory_MemTotal_bytes{job="node-exporter"}) by(instance)
* 100
) >=55

接下来创建一个 PrometheusRule告警:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[root@k8s-master01 PrometheusRule]# cat node-memory-rule.yaml
# PrometheusRule配置如下,expr: |中的|作用是告诉 YAML 解析器:“从下一行开始,直到缩进结束,这中间所有的内容(包括换行符和空格)都原封不动地当作一个完整的字符串。”
kind: PrometheusRule
apiVersion: monitoring.coreos.com/v1
metadata:
name: node-memory-rule
namespace: monitoring
spec:
groups:
- name: node-memory
rules:
- alert: NodeMemoryUseTooHigh
expr: |
100 -
(
avg(node_memory_MemAvailable_bytes{job="node-exporter"}) by(instance)/
avg(node_memory_MemTotal_bytes{job="node-exporter"}) by(instance)
* 100
) >=55
for: 5m
labels:
severity: warning
type: node
annotations:
summary: "主机:{{ $labels.instance }} 内存使用率超过55%"
description: "主机:{{ $labels.instance }} 内存使用率高, 当前值:{{ $value }}"

创建上述资源:

1
2
[root@k8s-master01 PrometheusRule]# kubectl create -f node-memory-rule.yaml
prometheusrule.monitoring.coreos.com/node-memory-rule created

在Prometheus的web UI中Status/Rules查看是否存在该规则,可以通过ctrl+f搜索PrometheusRule资源中的.spec.groups.name的值node-memory快速定位,也可以搜.spec.groups.rules.alert的值NodeMemoryUseTooHigh快速定位

因为我设置的阈值较低,所以在Alerts中已经产生了告警,证明该规则配置正确,已经可以正常报警,下一步是通知到相关人员