Prometheus 告警规则编写指南:从入门到别再半夜被叫醒

Prometheus Alerting Rules Guide: From Basics to Stopping 3AM False Alarms

| Sophia Li | 2026-08-14T09:32:26

写了一年告警规则,总结出的最佳实践。重点是怎么减少误报,不要让值班的人被无意义的告警叫醒。

One year of alerting rules experience distilled into best practices, focusing on reducing false positives and unnecessary 3AM pages.

## 告警的核心原则 先说最重要的原则:**每一条告警都应该需要有人采取行动**。 如果收到告警后的反应是"看看就好"或"等会儿自己恢复",这条告警就不应该存在。无意义的告警会导致"狼来了"效应——当真正的问题出现时,值班人员已经对告警麻木了。 ## 基础规则写法 ```yaml groups: - name: service-alerts rules: - alert: HighErrorRate expr: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.05 for: 5m labels: severity: critical annotations: summary: "{{ $labels.instance }} 错误率超过 5%" description: "过去 5 分钟错误率为 {{ $value | humanizePercentage }}" ``` 关键字段: - `expr`:PromQL 查询表达式 - `for`:持续多长时间才触发(避免瞬时抖动) - `severity`:严重程度(决定通知方式) ## 五个常见错误 ### 错误一:没有 `for` 或 `for` 太短 ```yaml # ❌ 没有 for —— 一次抖动就告警 - alert: HighCPU expr: node_cpu_usage > 0.9 # ✅ 持续 10 分钟才告警 - alert: HighCPU expr: node_cpu_usage > 0.9 for: 10m ``` CPU 偶尔飙到 90% 是正常的(比如 GC),持续 10 分钟才是真正的问题。 ### 错误二:阈值太绝对 ```yaml # ❌ 固定阈值 —— 不同服务的"正常"不一样 - alert: HighLatency expr: http_request_duration_seconds > 1 # ✅ 基于历史基线的动态阈值 - alert: HighLatency expr: > http_request_duration_seconds{quantile="0.99"} > 3 * avg_over_time(http_request_duration_seconds{quantile="0.99"}[7d]) for: 10m ``` P99 延迟超过过去 7 天平均值的 3 倍,才告警。 ### 错误三:不区分严重程度 ```yaml # ❌ 所有告警都是 critical severity: critical # 半夜被电话叫醒 # ✅ 分级 severity: info → Slack 通知 severity: warning → 邮件 + Slack severity: critical → 电话 + 短信 + Slack ``` 能不打电话就不打电话。 ### 错误四:告警描述不清 ```yaml # ❌ 只说"高了",没有上下文 summary: "CPU 高" # ✅ 给出具体数值和处理建议 summary: "{{ $labels.instance }} CPU 持续 10 分钟超过 90%(当前 {{ $value | humanize }}%)" description: | 可能原因:1) 请求量突增 2) 内存泄漏导致 GC 3) 死循环 排查步骤:先看 Grafana 仪表盘 xxx,检查请求量和 GC 频率 操作手册:https://wiki.example.com/runbook/high-cpu ``` 半夜三点被叫醒的人,需要**立刻知道该做什么**,而不是先研究这个告警是什么意思。 ### 错误五:不监控告警系统本身 ```yaml # 告警的告警! - alert: PrometheusTargetDown expr: up == 0 for: 5m labels: severity: critical annotations: summary: "Prometheus 无法抓取 {{ $labels.instance }}" ``` 如果 Prometheus 自己挂了或者抓取失败,所有告警都会失效。必须有"谁来监控监控系统"的兜底方案。 ## 实用告警模板 ### API 可用性 ```yaml - alert: ServiceDown expr: probe_success == 0 for: 2m labels: severity: critical - alert: HighErrorRate expr: > sum(rate(http_requests_total{status=~"5.."}[5m])) by (service) / sum(rate(http_requests_total[5m])) by (service) > 0.01 for: 5m labels: severity: warning ``` ### 资源使用 ```yaml - alert: DiskSpaceLow expr: node_filesystem_avail_bytes / node_filesystem_size_bytes sum(rate(orders_created_total[30m])) < 0.5 * sum(rate(orders_created_total[30m] offset 1d)) for: 15m labels: severity: warning annotations: summary: "订单量较昨天同期下降超过 50%" ``` ## 总结 好的告警规则应该做到: 1. **每条告警都需要行动** 2. **有足够的 `for` 持续时间** 3. **分级,不要全是 critical** 4. **描述清晰,包含处理建议** 5. **定期 review,删除不再有用的告警** 记住:告警的目标不是"发现所有异常",而是"在真正需要人介入时通知到人"。


Prometheus alerting best practices from one year of on-call experience. Core principle: every alert must require action. Five common mistakes: missing/short `for` duration, absolute thresholds (use dynamic baselines), no severity differentiation, unclear descriptions (include runbook links), and not monitoring the monitoring system. Practical templates for API availability, resource usage, and business metrics. Key takeaway: alerts should notify when human intervention is needed, not for every anomaly.

← Back to News