告警规则的核心设计原则
监控告警体系的价值不在多而在精。一个日均产出300条告警的系统约等于没有监控——oncall工程师会对告警形成免疫,真正严重的故障被淹没在噪音里。告警规则设计的核心原则只有一条:每一条告警都应该需要人工介入。如果一条告警被触发后不需要任何人采取行动,它就是噪音,应该降级为记录规则(recording rule)或仪表盘指标。
Prometheus的告警规则由Alertmanager统一管理和路由。规则文件定义触发条件,Alertmanager负责去重、分组、抑制和路由。两者解耦意味着规则文件可以很细粒度地定义检测逻辑,不必关心通知渠道。
告警规则的基本结构:
groups:
- name: node_alerts
rules:
- alert: NodeHighCPU
expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
for: 10m
labels:
severity: warning
team: sre
annotations:
summary: "{{ $labels.instance }} CPU使用率超过85%"
description: "当前值: {{ $value }}%,持续10分钟"
for子句是降噪的关键——不写for意味着瞬时超标立即告警,CPU尖峰持续3秒就触发告警毫无意义。for: 10m表示条件必须持续满足10分钟才触发,过滤掉99%的瞬态波动。持续时间要根据业务SLA设定:P99延迟相关指标for3-5分钟,CPU/内存等资源指标for10-15分钟,磁盘空间for30分钟以上。
多维度告警分组与抑制策略
Alertmanager的group_by参数决定哪些标签作为告警分组的依据。同一组的告警合并为一条通知,减少轰炸效果:
route:
group_by: ['alertname', 'namespace', 'cluster']
group_wait: 30s # 第一条告警等30秒看是否有同组告警
group_interval: 5m # 同组告警合并间隔
repeat_interval: 4h # 未恢复时重复通知间隔
receiver: 'default-slack'
routes:
- match:
severity: critical
receiver: 'pagerduty-oncall'
group_wait: 10s # 严重告警快速通知
repeat_interval: 1h
- match_re:
team: dba
alertname: MySQL.*
receiver: 'dba-slack'
group_by: ['alertname', 'instance'] # DBA按实例维度分组
抑制规则(inhibit_rule)处理告警间的因果关系。宿主机宕机时,上面的所有容器告警都应该被抑制:
inhibit_rules:
- source_match:
alertname: NodeDown
severity: critical
target_match:
severity: warning
equal: ['instance'] # 同一台机器的告警被抑制
- source_match:
alertname: KubernetesNodeNotReady
target_match_re:
alertname: PodNotReady|DeploymentReplicasMismatch
equal: ['node']
抑制规则的核心是equal字段——只有equal中列出的标签完全匹配时才生效。忘记写equal会导致全局抑制,某个节点宕机后所有机器的Pod告警全部静默,酿成漏报。
阈值设定的实用方法论
阈值设定没有万能公式,但有清晰的方法论。第一种方法是历史基线法:取过去30天P95值作为warning阈值,P99值作为critical阈值。PromQL直接计算:
# 请求延迟P95过去30天基线
avg_over_time(
histogram_quantile(0.95,
rate(http_request_duration_seconds_bucket[5m])
)[30d:5m]
)
第二种方法是容量规划法:资源类指标按剩余容量设定阈值。磁盘使用率比绝对值更直观,但可用时间比使用率更实用:
# 预测磁盘24小时内是否会填满
predict_linear(
node_filesystem_avail_bytes{mountpoint="/data"}[6h],
24*3600
) < 0
第三种方法是SLO误差预算法:SRE稳定性工程体系下,告警阈值与SLO挂钩。SLO 99.9%的API,月误差预算43.8分钟。当月已消耗误差预算超过50%时触发warning,超过80%触发critical:
# 30天滚动窗口内的SLO达成率
1 - (
sum(rate(http_requests_total{code=~"5.."}[30d]))
/
sum(rate(http_requests_total[30d]))
) < 0.999
这种方法的优越之处在于:告警阈值直接映射业务影响,而非资源层面的间接推断。DevOps实践的核心就是把技术指标翻译成业务语言。
故障应急响应的告警分级与通知路由
告警严重等级的设定直接影响故障应急响应效率。推荐三级分类:
P1/Critical:服务完全不可用或数据一致性受损,5分钟内oncall必须响应。通知渠道:电话+短信+即时消息。典型规则:API 5xx率>10%、数据库主从切换失败、核心链路探测全部失败。
P2/Warning:服务降级但可用,30分钟内需排查。通知渠道:即时消息+工单。典型规则:API P99延迟超过基线2倍、磁盘剩余空间<20%、容器OOM Kill频次上升。
P3/Info:需要关注但不影响服务,4小时内处理即可。通知渠道:仪表盘标注或低优先级频道。典型规则:证书30天内过期、配置漂移检测。
路由配置示例:
receivers:
- name: 'pagerduty-oncall'
pagerduty_configs:
- service_key: '<key>'
severity: '{{ .CommonLabels.severity }}'
- name: 'slack-sre'
slack_configs:
- channel: '#sre-alerts'
title: '[{{ .Status | toUpper }}] {{ .CommonLabels.alertname }}'
text: >-
{{ range .Alerts }}
*{{ .Annotations.summary }}*
{{ .Annotations.description }}
{{ end }}
通知渠道选择的一个常见反模式是所有告警都发到同一个群。正确的做法是按团队和严重等级路由到不同渠道——Critical到值班电话,Warning到团队Slack频道,Info只记日志。日志分析和告警是两个独立的可观测性支柱,不要把它们混为一谈。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/prometheus-gao-jing-gui-ze-she-ji-shi-zhan-cong-yu-zhi-she/