Prometheus 告警规则怎么自己写,云原生环境下那些坑和注意点分享
- 问答
- 2026-01-18 18:49:44
- 1
关于怎么自己写Prometheus告警规则,以及在云原生环境下有哪些坑和注意点,我结合一些网络上的实践经验,比如像“Kubernetes实战指南”这类博客和“Prometheus官方文档”的建议,来直接说一下。
第一部分:怎么写Prometheus告警规则
告警规则是写在单独的.yml或.yaml文件里的,然后在Prometheus的配置文件中告诉它去哪里加载这些规则文件。
一条告警规则的核心其实就三句话:“在什么情况下”、“持续多长时间”、“该报什么警”。
具体来看,一个规则文件里主要包含两个大块:groups,一个group就是一组相关的告警规则,方便管理,每条规则rule有几个关键字段:
alert:给告警起个名字,这个名字要一眼就能看出问题,比如HighCPUUsage、NodeDown。expr:这是最关键的,写一个PromQL表达式,这个表达式的结果应该是一个数值或者一组时间序列,当这个表达式的计算结果“有值”(比如大于0)时,就说明触发了告警的条件,比如你想监控CPU使用率,表达式可能是(1 - avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance)) * 100 > 80,意思是CPU使用率超过80%。for:等待时间,上面表达式条件满足了,不能马上报警,得持续一段时间,这是为了防止一些瞬间的毛刺导致误报,比如for: 5m,就是条件连续满足5分钟才真正触发告警。labels:给这条告警添加额外的标签,这些标签会随着告警一起发送给Alertmanager,这里非常关键,你后面在Alertmanager里做路由(比如这个告警该发给哪个团队)、静默、聚合,主要就是靠这里的标签,常见的标签比如severity: warning/critical(严重等级)、team: frontend(负责团队)。annotations:告警的详细描述信息,这部分是给人看的,这里可以用变量,把监控数据的具体值动态放进去。summary: 简短摘要,实例 {{ $labels.instance }} CPU使用率过高description: 详细描述,实例 {{ $labels.instance }} 的CPU使用率已经达到 {{ $value }}%,持续超过5分钟。
举个例子,一个完整的告警规则看起来是这样的:
groups:
- name: node.rules
rules:
- alert: NodeCPUUsageHigh
expr: (1 - avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance)) * 100 > 85
for: 5m
labels:
severity: critical
team: infra
annotations:
summary: "实例 {{ $labels.instance }} CPU使用率过高"
description: "实例 {{ $labels.instance }} 的CPU使用率已经达到 {{ $value | printf "%.2f" }}%,超过85%阈值,持续5分钟。"
写的时候,核心思路就是:把你的运维经验翻译成PromQL语言,你先得知道什么样的情况是异常的(比如连接数暴涨、错误码增多、响应时间变长),然后用合适的指标和表达式把它描述出来。
第二部分:云原生环境下的坑和注意点
在云原生环境里,尤其是Kubernetes里,东西是动态的,今天Pod还在,明天可能就没了,这带来了很多传统环境没有的坑。
-
动态性导致的“误报”和“漏报”(这个点在“云原生社区”的很多讨论里被反复提到):
- 坑:你监控的Pod可能因为弹性伸缩、发布、故障等原因随时被创建或销毁,如果你的告警规则
for时间设得太短,一个Pod刚启动时资源使用率高,可能就会触发告警,但它可能只是在进行初始化,这是误报,反之,如果一个Pod已经挂了并且被快速重建了,你的监控可能还没来得及抓取到足够的数据,它就已经消失了,导致漏报。 - 注意点:对于短期存在的对象(比如Job/CronJob的Pod),告警要非常小心,可能需要对指标做更短周期的判断或者使用不同的阈值,对于长期存在的核心组件,告警的
for时间要设得足够长,以过滤掉重启、发布等正常波动。
- 坑:你监控的Pod可能因为弹性伸缩、发布、故障等原因随时被创建或销毁,如果你的告警规则
-
标签泛滥问题(这是Prometheus监控Kubernetes的经典问题,官方文档有提及):
- 坑:Kubernetes会给所有资源打上大量标签(label),比如Pod名字、所属Deployment、节点名等等,Prometheus在采集时,这些标签都会成为时间序列的标签,如果你在写告警规则的
expr里不加选择地使用所有标签,或者用by ()分组时包含了太多不稳定的标签(比如Pod名),会导致Prometheus产生海量的、生命周期很短的时间序列,给服务器造成巨大压力。 - 注意点:在写PromQL时,要明确你需要根据哪些标签来聚合或分组,尽量使用相对稳定的标签进行
group by,比如namespace,service,deployment,避免直接使用pod_name或container_name这种高度易变的标签作为聚合的主要维度,除非你确实需要。
- 坑:Kubernetes会给所有资源打上大量标签(label),比如Pod名字、所属Deployment、节点名等等,Prometheus在采集时,这些标签都会成为时间序列的标签,如果你在写告警规则的
-
监控目标发现与Relabeling的复杂性:
- 坑:在Kubernetes中,Prometheus通过Service Discovery自动发现要监控的目标,这个过程里会用到大量的Relabeling配置来重写标签、过滤目标,如果你的告警规则依赖某个标签(比如
job标签或者一个自定义的team标签),但这个标签在Relabeling过程中被意外丢弃或修改了,就会导致告警规则无法匹配到数据,永远不触发。 - 注意点:写告警规则时,心里要清楚你用的标签是从哪里来的,最好去Prometheus的Web UI上,检查一下你用的指标实际暴露出来的标签是什么,确保和你规则里引用的
$labels.xxx是一致的,理顺Service Discovery和Relabeling的配置是稳定告警的基础。
- 坑:在Kubernetes中,Prometheus通过Service Discovery自动发现要监控的目标,这个过程里会用到大量的Relabeling配置来重写标签、过滤目标,如果你的告警规则依赖某个标签(比如
-
资源指标的含义变化:
- 坑:在容器环境下,CPU、内存这些指标的理解和物理机不同,你监控容器内存使用率,用的是
container_memory_working_set_bytes,但这个值接近容器限制(limit)时,容器不一定会被OOM Kill,因为还有Page Cache等因素,直接套用物理机的阈值可能会过度紧张。 - 注意点:要深入了解容器资源模型,告警阈值需要根据容器的Request和Limit来合理设定,而不是一个固定的百分比,可以设置“内存使用量超过Limit的90%”告警,这比“内存使用率超过90%”更符合容器场景。
- 坑:在容器环境下,CPU、内存这些指标的理解和物理机不同,你监控容器内存使用率,用的是
-
“告警风暴”的放大效应:
- 坑:在Kubernetes里,一个底层节点故障,可能导致上面运行的几十个Pod同时出问题,从而触发几十条内容相似的告警(比如Pod重启、无法连接等),如果这些告警没有很好地被聚合,会瞬间淹没Alertmanager和运维人员。
- 注意点:这在“Alertmanager最佳实践”里是重点,一定要利用好告警规则里的
labels,给同一类告警打上相同的标签(比如alertname,cluster,namespace),然后在Alertmanager的配置中,设置合理的group_by(比如按cluster和alertname分组),并配置group_wait和group_interval,让Alertmanager把短时间内同一组的告警合并成一条通知发出来。
在云原生里写告警,思路要从静态的“监控机器”转变到动态的“监控服务”,规则要能适应环境的弹性变化,写PromQL时要时刻警惕标签带来的资源消耗和混淆,并且从一开始就要为告警设计好聚合策略,避免被自己的告警系统“打垮”。

本文由革姣丽于2026-01-18发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://www.haoid.cn/wenda/83200.html
