资讯详情

资讯详情

Prometheus告警规则模板库:从零搭建到生产调优实战

1. 为什么我坚持维护一套自己的告警规则模板库做运维和SRE这些年我经手过的监控系统少说也有十几套了。每次新环境搭建、每次迁移、每次接手别人的集群最耗时间的事情往往不是装Prometheus、不是配Grafana而是告警规则到底该怎么写。装软件半小时搞定规则调优能折腾你三个月。这个项目标题说的“常用prometheus告警规则模板”本质上就是把我这些年反复写、反复改、反复踩坑之后沉淀下来的那批规则整理成一套可以直接拿来用、也可以按需裁剪的模板集合。先说清楚它是什么。这是一套面向Prometheus生态的告警规则模板覆盖主机、容器、中间件、数据库、应用层这几个最常见的监控维度用PromQL表达以YAML格式组织可以直接通过rule_files加载到Prometheus里也可以配合Alertmanager做路由分发。它能解决的核心问题是让你在搭建完监控采集之后不用从零开始想“该告什么警”。很多人采集指标配得很全但告警规则要么空着要么只配了个“实例挂了”结果真出问题时要么没告警、要么告警风暴值班的人被淹没在噪音里。这套模板适合谁我觉得三类人最用得上。第一类是刚接触Prometheus的运维或开发手上有一套新集群指标已经采上来了但不知道哪些指标值得告、阈值该定多少拿模板当起点最省事。第二类是已经有告警但噪音很大的团队可以拿这套模板做对照看看自己的规则是不是缺了for、是不是聚合维度写错了、是不是该用rate的地方用了increase。第三类是做标准化建设的比如要给多个业务线统一告警规范这套模板可以作为基线各业务在此基础上做增量。需要提前说明一点模板不是拿来即用的银弹。每个环境的业务特征、流量模型、硬件规格都不一样阈值必须结合实际情况调。我在下面会把每条规则背后的判断逻辑讲清楚你理解了“为什么这么写”改起来才不会心虚。这也是我写这篇东西的核心目的——给的是思路和骨架不是让你闭眼复制。2. 整体设计与规则组织思路拆解2.1 为什么按“层次对象”来组织规则文件规则文件怎么拆分这个看似是小事实际上直接影响后期维护成本。我见过把所有规则塞进一个alerts.yml的做法几百行下去改一条规则要滚半天多人协作时冲突不断。也见过按告警级别拆的critical.yml、warning.yml各一个文件听起来合理但实际用起来很别扭——同一个对象的严重告警和警告往往要一起看、一起调拆开反而割裂。我最终采用的是按监控对象分层的组织方式大致是这样rules/ host/ # 主机层CPU、内存、磁盘、负载、文件句柄 container/ # 容器层Pod状态、重启、资源限制、OOM middleware/ # 中间件各类消息队列、缓存、网关 database/ # 数据库连接数、慢查询、复制延迟、磁盘 application/ # 应用层请求量、错误率、延迟、饱和度 meta/ # 元监控采集目标存活、规则评估自身健康这么拆的理由很实在。第一故障排查天然是按层走的——主机挂了先看主机容器异常先看容器定位到中间件再看中间件规则文件和排查路径对齐找起来快。第二权限和职责能对上——主机规则通常由基础架构团队维护应用规则由业务团队维护文件边界清晰Code Review和变更审批都好划分。第三复用粒度合适——新上一个中间件把对应目录下的模板拷过来改改就行不用在几百行里挑挑拣拣。每个目录内部我习惯再按“资源维度”细分比如主机层里CPU、内存、磁盘各成一组。这样单文件不会太长通常控制在80到150行之间读起来不累。2.2 告警分级与for时长的取舍逻辑告警级别我固定用三档critical、warning、info。这个分级不是为了好看而是直接对应Alertmanager的路由策略和值班响应。critical意味着“现在就得有人起来处理”走电话或强提醒warning是“工作时间处理或者观察趋势”info基本是记录性质进工单不进值班。比级别更容易被忽视、但影响更大的是for字段。for决定了一个条件要持续多久才真正触发告警它是抑制抖动的最重要手段。我踩过最典型的坑是CPU使用率规则没写for或者只写了30s结果一次正常的批处理任务跑起来CPU瞬间冲到90%告警就响了值班的人半夜被叫醒一看是定时任务气得不行。我的经验取值是这样的告警类型建议for理由实例存活类1m采集本身有间隔太短会误报太长发现慢资源使用率类5m~10m过滤瞬时峰值反映真实持续压力错误率类2m~5m兼顾灵敏度和抗抖动容量趋势类30m~1h趋势问题不急看的是长期走向配置/状态类1m状态异常通常需要尽快知道这里有个容易被忽略的细节for的计时是从表达式第一次为真开始算的如果中间有一次评估为假计时会重置。所以对于波动大的指标光靠for不够还得配合avg_over_time之类的聚合函数先把曲线平滑掉再交给for判断。这两者是配合关系不是二选一。2.3 阈值为什么不能照抄以及怎么定模板里我会给一个默认阈值但我必须强调默认值只是起点不是答案。原因很简单一台4核8G的机器和一台64核256G的机器CPU告警阈值能一样吗一个IO密集型和CPU密集型的服务内存水位线能一样吗我定阈值的习惯做法是“三步走”。第一步先让指标裸跑一到两周不做任何告警把数据拉出来看分布——P50、P95、P99各是多少峰值出现在什么时段。第二步以P99为参考往上留出合理余量作为warning线再往上留出更大余量作为critical线。第三步上线后持续观察误报率误报多的往上调漏报的往下调一般迭代两三轮就稳了。举个具体例子。某服务的请求延迟P99稳定在200ms左右偶发峰值到400ms。那warning可以定在500ms、for 5mcritical定在1s、for 2m。这样正常波动不会触发真出问题时又能及时抓到。如果直接抄一个“延迟超过100ms就告警”的模板那这个服务天天告警规则很快就没人看了——没人看的告警等于没有告警这是运维里最危险的假安全感。3. 核心规则模板逐类拆解与实操要点3.1 主机层CPU、内存、磁盘、负载的规则写法主机层是最基础的一层规则也最通用。先看CPU。很多人第一反应是写100 - avg(rate(node_cpu_seconds_total{modeidle}[5m])) * 100 80这个写法本身没错但有两个细节要注意。一是要按instance聚合否则多核多实例混在一起算平均值一台机器满载会被其他空闲机器稀释掉二是rate的窗口要和采集间隔匹配采集间隔15s的话[5m]窗口里有20个点足够平滑。我常用的CPU规则是这样的- alert: HostHighCpuUsage expr: | 100 - (avg by (instance) (rate(node_cpu_seconds_total{modeidle}[5m])) * 100) 85 for: 10m labels: severity: warning annotations: summary: 主机 CPU 使用率持续偏高 (实例 {{ $labels.instance }}) description: CPU 空闲率低于 15%已持续 10 分钟当前值 {{ $value | printf \%.1f\ }}%。注意for: 10m这个取值。CPU短时冲高太常见了编译、批处理、日志轮转都会造成尖峰10分钟能过滤掉绝大多数瞬时波动。如果业务对CPU极其敏感可以缩到5分钟但别再短了。内存规则有个坑node_memory_MemAvailable_bytes和node_memory_MemFree_bytes不是一回事。后者只算完全空闲的内存前者还包含了可回收的缓存判断内存压力应该用Available而不是Free。用Free的话Linux会把大量内存拿去做页缓存Free常年很低告警天天响。正确写法是算Available占Total的比例- alert: HostHighMemoryUsage expr: | (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 90 for: 10m labels: severity: warning磁盘规则要分两个维度使用率和剩余空间绝对值。只看使用率会漏掉小分区——一个10G的分区用到95%只剩500M可能比一个1T分区用到85%更危险。所以我会同时配两条使用率阈值定在85%剩余空间定在低于5G告警。另外磁盘预测也值得配一条用predict_linear算未来4小时是否会写满这个对提前介入特别有用- alert: HostDiskWillFillIn4Hours expr: | predict_linear(node_filesystem_avail_bytes{fstype!~tmpfs|overlay}[1h], 4 * 3600) 0 for: 30m labels: severity: warning负载规则要注意node_load1的绝对值没有普适意义必须结合CPU核数看。我的做法是算负载与核数的比值超过1.5告警。核数通过count by (instance) (node_cpu_seconds_total{modeidle})拿到。3.2 容器层Pod状态、重启与资源限制的规则容器层的规则和主机层思路不同因为容器的生命周期短、变化快规则要更关注“状态”而不是“水位”。最基础的是Pod非Running状态告警但这里有个细节kube_pod_status_phase会为每个phase各输出一条时间序列值为1表示当前处于该phase。所以判断“不是Running”不能简单写phase ! Running而要针对具体异常phase写比如Pending和Failed- alert: PodPendingTooLong expr: | kube_pod_status_phase{phasePending} 1 for: 15m labels: severity: warningfor: 15m是因为Pod启动、调度、拉镜像都需要时间刚创建就Pending是正常的15分钟还Pending才说明有问题可能是资源不足或镜像拉不下来。重启次数告警我用的是increase而不是直接看计数器。kube_pod_container_status_restarts_total是累计值直接判断大于某个数没意义——一个跑了半年的Pod重启过5次很正常。正确做法是看一段时间内的增量- alert: PodRestartingFrequently expr: | increase(kube_pod_container_status_restarts_total[1h]) 3 for: 5m labels: severity: warning资源限制这块我强烈建议配“接近limit”的告警。容器内存接近limit会被OOM KillCPU接近limit会被限流这两种情况都会造成服务抖动但未必立刻挂掉很容易被忽视。用container_memory_working_set_bytes除以kube_pod_container_resource_limits算比例超过90%告警。这里用working_set而不是usage是因为working_set排除了可回收的缓存更接近真实压力。3.3 应用层错误率、延迟与饱和度的黄金指标应用层规则我基本围绕四个黄金指标展开流量、错误、延迟、饱和度。这四个词不是玄学是Google SRE那套方法论里反复验证过的最小充分集。流量本身一般不告警除非骤降重点在错误率、延迟和饱和度。错误率规则的关键是分母要对。我见过有人写rate(http_requests_total{status~5..}[5m]) 0.1这个写法告的是“每秒5xx请求数超过0.1”不是错误率。流量大的服务这个阈值形同虚设流量小的服务又永远触发不了。正确做法是算比例- alert: HighErrorRate expr: | sum by (service) (rate(http_requests_total{status~5..}[5m])) / sum by (service) (rate(http_requests_total[5m])) 0.05 for: 5m labels: severity: critical5%这个阈值是经验值核心链路可以收紧到1%非核心可以放宽到10%。另外要注意分母为0的情况服务完全没流量时这个表达式会得到NaN不会触发告警这通常是符合预期的——没流量自然没错误。延迟规则要用直方图的分位数而不是平均值。平均值会把长尾掩盖掉一个P99是2秒但平均值200ms的服务用户体验其实很差。用histogram_quantile算P99- alert: HighLatencyP99 expr: | histogram_quantile(0.99, sum by (service, le) (rate(http_request_duration_seconds_bucket[5m])) ) 1 for: 5m labels: severity: warning这里有个实操要点histogram_quantile必须配合sum by (le)使用且le标签必须保留在聚合维度里否则算出来的分位数是错的。这个坑我见过不止一个人踩。饱和度我一般看并发连接数或线程池使用率接近上限时告警。这类指标因框架而异模板里给的是通用骨架具体指标名要按实际技术栈替换。3.4 元监控别让监控系统自己瞎了这一类规则最容易被忽略但我觉得它比任何业务规则都重要——监控系统自己出问题时你得知道。核心就两条采集目标是否存活规则评估是否正常。目标存活用up 0判断但要加for因为采集偶尔失败一次很正常- alert: TargetDown expr: up 0 for: 3m labels: severity: warning规则评估健康度看prometheus_rule_evaluation_failures_total的增量以及prometheus_rule_group_last_duration_seconds是否超过评估间隔。规则评估失败意味着告警可能根本没在算这是最隐蔽的故障。还有一条值得配prometheus_notifications_dropped_total增量大于0说明告警发不出去Alertmanager那边可能有问题。4. 实操落地从模板到可用规则的完整流程4.1 规则文件的加载与校验模板拿到手第一步不是直接扔进生产而是先做语法校验。Prometheus自带promtool这是最靠谱的检查工具promtool check rules rules/host/*.yml这个命令会检查YAML语法、PromQL表达式合法性、告警名称和标签是否符合规范。我习惯把它加进CI流程规则文件变更时自动跑一遍避免把语法错误带到线上。实测下来promtool能抓出90%以上的低级错误比如括号不匹配、函数名拼错、for格式不对。加载方式是在prometheus.yml里配rule_filesrule_files: - rules/host/*.yml - rules/container/*.yml - rules/application/*.yml支持通配符按目录加载很方便。改完规则后Prometheus支持热加载发个SIGHUP或者调/-/reload接口就行不用重启。但热加载有个前提启动时要加--web.enable-lifecycle参数。4.2 阈值调优的实操记录我拿一个真实场景说下调优过程。某服务刚接入监控时错误率规则用的是模板默认的5%、for 5m。上线第一周告警响了十几次值班同事怨声载道。我把告警历史拉出来看发现大部分是发布期间的短暂抖动——新版本滚动发布时旧Pod下线、新Pod还没完全就绪会有几十秒的5xx。处理办法有两个。一是把for从5m调到8m覆盖发布窗口二是在发布期间用维护窗口静默。我两个都做了for调到8m作为常态防护发布时再叠加静默。调整后一周误报降到两次都是真实问题。这个例子说明阈值调优不是拍脑袋是拿数据说话每次调整都要有依据、有记录。延迟规则的调优也类似。最初P99阈值定在500ms结果某服务因为依赖的下游接口本身P99就在600ms左右天天告警。跟业务方确认后这个延迟是下游的固有特征不是本服务的问题于是把阈值放宽到800ms同时在下游服务那边单独配了规则。告警要告到能处理的人头上告到处理不了的人那里就是噪音。4.3 与Alertmanager的路由配合规则里的severity标签最终要靠Alertmanager的路由来落地。我的路由配置大致是这样critical走即时通知渠道warning走工作时间汇总info只进工单系统。分组用alertname加service避免同一服务的多条告警刷屏。抑制规则也值得配比如主机宕机的告警应该抑制该主机上所有其他告警不然一台机器挂了能给你发几十条。这里有个细节规则里的annotations要写清楚summary一句话说清是什么问题description带上当前值和关键上下文。值班的人半夜看到告警第一眼要能判断严重程度和大致方向而不是再去翻文档。我见过description只写“出问题了”的规则这种规则等于没写。5. 常见问题与排查技巧实录5.1 告警不触发或延迟触发的排查最常见的问题是“明明指标超了告警没响”。排查顺序我一般是这样的先确认规则有没有被加载访问Prometheus的/rules页面能看到所有已加载规则和它们的当前状态再看表达式的即时值在Graph页面把expr贴进去执行看返回什么然后看for状态/alerts页面会显示pending中的告警和已持续时间最后看Alertmanager有没有收到查它的/api/v2/alerts。按这个顺序走基本能定位到卡在哪一环。我遇到过最隐蔽的一次是规则加载了、表达式也对、for也满足了但Alertmanager没收到——查下来是规则里的标签和路由配置的匹配条件对不上告警被路由到了空接收器。这种问题光看Prometheus看不出来必须两边对照。5.2 告警风暴的抑制与收敛告警风暴的成因通常有三类一是某个基础组件挂了依赖它的所有服务一起告警二是阈值定得太敏感正常波动就触发三是聚合维度写错一个实例的问题被放大成几十条。对应的处理手段分别是配抑制规则、调阈值加for、修正聚合维度。抑制规则我必配的一条是TargetDown触发时抑制同一实例上的所有其他告警。因为实例都挂了上面的CPU、内存、应用指标告警都没有意义。另一条是critical抑制同名的warning避免同一问题两个级别一起响。5.3 常见问题速查表现象可能原因排查动作规则不生效文件未加载或语法错误promtool check rules查/rules页面告警频繁误报for太短或阈值过低拉历史数据看分布调for和阈值告警延迟很久才响for过长或评估间隔大查evaluation_interval和for设置同一问题多条告警聚合维度缺失检查by子句是否漏了关键标签告警发不出去Alertmanager路由或抑制配置查Alertmanager日志和路由匹配分位数算出来不对le标签未保留在聚合中确认sum by (le)写法5.4 几条踩坑换来的经验第一条别在规则里写死实例名或服务名。模板要通用具体对象靠标签匹配写死了就没法复用了。第二条annotations里的$value记得格式化默认会输出一长串小数用printf %.1f处理一下值班的人看着舒服。第三条规则命名要有统一前缀比如Host、Pod、App开头告警列表里一眼能看出属于哪一层。第四条定期清理僵尸规则业务下线了规则还留着不仅浪费评估资源还会在指标消失时产生奇怪的告警。我个人在实际操作中的体会是告警规则这件事没有一劳永逸它是个持续迭代的过程。模板给的是起点和骨架真正让它好用的是你在自己环境里一轮轮的调优。每次误报都是一次改进机会每次漏报都是一次补课。把这套模板当成你的第一版草稿而不是最终答案心态就对了。后续如果团队规模上来还可以考虑把规则做成可参数化的形式用配置管理工具按环境渲染那样多集群维护会轻松很多。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →