Skip to content
Prometheus 规则与告警

Prometheus 规则与告警

本文档涵盖 Recording Rules(记录规则)、Alerting Rules(告警规则)以及 Alertmanager 告警管理——分组、抑制、静默、路由和通知。

符号说明

符号 含义
🚨 陷阱 / Pitfall
💡 最佳实践 / Best practice
🔬 深入原理 / Deep-dive
性能提示 / Performance note

1. Recording Rules 与 Alerting Rules

1.1 Recording Rules(记录规则)

作用: 将复杂/昂贵的 PromQL 查询预计算,存储为新的时间序列,加速看板查询。

groups:
  - name: cpu_aggregations
    interval: 60s              # 可选,覆盖 global.evaluation_interval
    rules:
      - record: job:node_cpu_usage:avg_rate5m
        expr: |
          100 - avg by(job) (
            rate(node_cpu_seconds_total{mode="idle"}[5m]) * 100
          )

      - record: instance_mode:node_cpu:rate1m
        expr: sum without(cpu) (rate(node_cpu_seconds_total[1m]))
        labels:
          source: 'recording_rule'

💡 命名规范: level:metric:operation,如 job:node_cpu_utilization:avg_rate5m。使用冒号分隔聚合级别、指标名和操作。

1.2 Alerting Rules(告警规则)

groups:
  - name: application_alerts
    rules:
      # === 基础告警 ===
      - alert: HighErrorRate
        expr: |
          sum(rate(http_requests_total{status=~"5.."}[5m]))
          / (sum(rate(http_requests_total[5m])) > 0)
          * 100 > 5
        for: 5m                     # 持续 5 分钟才触发(防抖动)
        labels:
          severity: warning
          team: backend
        annotations:
          summary: "错误率超过 5% (当前: {{ $value | humanizePercentage }})"
          description: "服务 {{ $labels.job }} 在实例 {{ $labels.instance }} 上错误率过高"
          runbook_url: "https://wiki.example.com/alerts/high-error-rate"

      # === 服务宕机 ===
      - alert: ServiceDown
        expr: up == 0
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "{{ $labels.job }} 在 {{ $labels.instance }} 已宕机"

      # === P99 延迟过高 ===
      - alert: HighP99Latency
        expr: |
          histogram_quantile(0.99,
            sum(rate(http_request_duration_seconds_bucket[5m])) by (le, service)
          ) > 2
        for: 10m
        labels:
          severity: critical
        annotations:
          summary: "P99 延迟超过 2 秒: {{ $value }}s"

      # === 磁盘空间不足 ===
      - alert: LowDiskSpace
        expr: |
          (node_filesystem_avail_bytes{mountpoint="/"}
          / node_filesystem_size_bytes{mountpoint="/"})
          * 100 < 10
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "磁盘使用率超过 90%,剩余 {{ $value | humanize }}%"

      # === 证书即将过期 ===
      - alert: SSLCertExpiringSoon
        expr: probe_ssl_earliest_cert_expiry - time() < 86400 * 7
        for: 1h
        labels:
          severity: warning
        annotations:
          summary: "SSL 证书将在 7 天内过期: {{ $labels.instance }}"

1.3 规则文件关键字段

字段 说明
alert 告警名称(alerting rules)
record 输出指标名(recording rules)
expr PromQL 表达式
for 持续多久才触发(防抖动)
keep_firing_for 条件恢复后继续触发多久
labels 额外的分类标签(用于 Alertmanager 路由)
annotations 描述信息(支持 {{ $labels.xxx }}{{ $value }} 模板语法)

🚨 告警规则一定要加 for 不加 for 会在每次短暂毛刺时都触发告警,造成严重的告警风暴。

💡 规则文件加载顺序: 同一 group 内的规则顺序执行(后面的可以引用前面的结果),不同 group 并行执行。如果有依赖关系,放到同一 group 中。

在 Recording Rules 中预聚合可以显著减少看板查询延迟,特别是跨许多实例的 Heavy 聚合查询。

1.4 验证与热加载

# 检查规则文件语法
promtool check rules /path/to/rules.yml

# 热加载(无需重启 Prometheus)
curl -X POST http://localhost:9090/-/reload

2. Alertmanager 告警管理

Alertmanager 负责接收 Prometheus 发来的告警,然后进行分组、抑制、静默、路由,最终通知到人。

2.1 核心概念

Prometheus Alert → Alertmanager → [分组] → [抑制] → [静默] → [路由] → Slack/Email/PagerDuty...
概念 说明
Grouping(分组) 将同类告警合并成一条通知,避免一次性收到 100 条相同类型的告警
Inhibition(抑制) 高优先级告警触发后,抑制相关的低优先级告警(如:节点宕机后不再发 Pod 告警)
Silence(静默) 在指定时间范围内不发送特定告警(如:计划中的维护窗口)
Routing(路由) 根据标签将告警分发到不同的接收者

2.2 alertmanager.yml 完整示例

global:
  resolve_timeout: 5m                    # 告警恢复后多久发送 resolved 通知
  smtp_smarthost: 'smtp.example.com:587'
  smtp_from: 'alertmanager@example.com'
  smtp_auth_username: 'alertmanager@example.com'
  smtp_auth_password: 'your-password'
  slack_api_url: 'https://hooks.slack.com/services/xxx'

# === 路由树 ===
route:
  group_by: ['alertname', 'namespace', 'severity']
  group_wait: 30s          # 收到第一条告警后等多久(等后续告警一起发)
  group_interval: 5m       # 同组有新告警时,间隔多久发更新
  repeat_interval: 4h      # 告警仍在触发时,多久重发一次
  receiver: 'slack-general'  # 默认接收者

  routes:
    # 关键告警 → PagerDuty + Slack
    - match:
        severity: critical
      receiver: 'pagerduty-critical'
      group_wait: 10s
      repeat_interval: 1h
      continue: true             # 继续匹配后续路由(同时发给 Slack)

    - match:
        severity: critical
      receiver: 'slack-critical'
      repeat_interval: 1h

    # 警告 → Slack 警告频道
    - match:
        severity: warning
      receiver: 'slack-warnings'

    # 数据库相关告警 → DBA 邮件
    - match_re:
        service: 'postgres|mysql|redis'
      receiver: 'email-dba'
      continue: true

# === 接收者(通知渠道)===
receivers:
  - name: 'slack-general'
    slack_configs:
      - channel: '#alerts-general'
        send_resolved: true
        title: '[{{ .Status | toUpper }}] {{ .CommonLabels.alertname }}'
        text: |-
          {{ range .Alerts }}
          *Alert:* {{ .Annotations.summary }}
          *Description:* {{ .Annotations.description }}
          *Severity:* {{ .Labels.severity }}
          {{ end }}

  - name: 'slack-critical'
    slack_configs:
      - channel: '#alerts-critical'
        send_resolved: true
        color: '{{ if eq .Status "firing" }}danger{{ else }}good{{ end }}'
        title: '🚨 {{ .CommonAnnotations.summary }}'

  - name: 'pagerduty-critical'
    pagerduty_configs:
      - routing_key: 'your-pagerduty-integration-key'
        severity: critical
        description: '{{ .CommonLabels.alertname }}: {{ .CommonAnnotations.summary }}'

  - name: 'email-dba'
    email_configs:
      - to: 'dba@example.com'
        send_resolved: true
        headers:
          Subject: '[{{ .Status | toUpper }}] {{ .CommonLabels.alertname }}'

# === 抑制规则 ===
inhibit_rules:
  # 有 critical 告警时,抑制同名 warning 告警
  - source_match:
      severity: 'critical'
    target_match:
      severity: 'warning'
    equal: ['alertname', 'namespace']

  # 节点宕机时,抑制 Pod 相关的所有告警
  - source_match:
      alertname: 'NodeDown'
    target_match_re:
      alertname: 'Pod.*'
    equal: ['node']

2.3 路由匹配方式

匹配器 语法 示例
精确匹配 match severity: critical
正则匹配 match_re service: 'postgres|mysql'
否定匹配 matchers severity != info
继续向下 continue: true 命中后继续匹配后续路由

2.4 时间相关参数

参数 默认值 意义
group_wait 30s 等多久才发第一条通知,用于收集同组新告警
group_interval 5m 同组已有告警更新时,间隔多久再发
repeat_interval 4h 告警一直触发时,间隔多久重复发
resolve_timeout 5m 告警恢复后多久发 resolved 通知

2.5 命令行操作

# 验证配置
amtool check-config alertmanager.yml

# 测试路由
amtool config routes test severity=critical team=backend

# 查看当前告警
amtool alert --alertmanager.url=http://localhost:9093

# 添加静默
amtool silence add --alertmanager.url=http://localhost:9093 \
  'alertname=HighCPUUsage' --duration=2h --comment='计划维护'

2.6 通知渠道汇总

渠道 配置块 关键参数
Slack slack_configs channel, api_url, send_resolved
Email email_configs to, send_resolved, headers
PagerDuty pagerduty_configs routing_key, severity
OpsGenie opsgenie_configs api_key, priority
企业微信 wechat_configs corp_id, api_secret
Webhook webhook_configs url, send_resolved
VictorOps victorops_configs api_key, routing_key

参考资料: