强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Prometheus 完全指南 / 09 - 录制规则

09 - 录制规则

9.1 概述

录制规则(Recording Rules)允许预先计算常用的、计算量大的 PromQL 表达式,并将结果保存为新的时间序列。这样可以显著提高查询性能,尤其是在 Grafana Dashboard 中频繁使用的查询。

原始指标 ──► 录制规则(定期计算) ──► 新的时间序列(预聚合结果)
                                           │
                                           ▼
                                     Dashboard 直接查询(快!)

录制规则 vs 实时查询

维度实时查询录制规则
计算时机查询时计算后台定期计算
查询速度慢(复杂查询)快(预计算)
数据新鲜度实时有延迟(evaluation_interval)
适用场景临时查询/调试Dashboard/告警
存储开销无额外开销需要额外存储

9.2 规则语法

# /etc/prometheus/rules/recording.yml
groups:
  - name: <group_name>
    interval: <duration>           # 可选,覆盖全局 evaluation_interval
    rules:
      - record: <new_metric_name>  # 新指标名称
        expr: <promql_expr>        # PromQL 表达式
        labels:                    # 可选,附加标签
          label_name: label_value

基本示例

groups:
  - name: node_recording
    interval: 30s
    rules:
      # CPU 使用率
      - record: instance:node_cpu_usage:ratio
        expr: |
          1 - avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m]))

      # 内存使用率
      - record: instance:node_memory_usage:ratio
        expr: |
          1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes

      # 磁盘使用率
      - record: instance:node_disk_usage:ratio
        expr: |
          1 - node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}

9.3 命名规范

录制规则的命名应遵循特定的格式,以便区分预计算结果和原始指标。

推荐格式

<level>:<source>_<metric>_<aggregation>:<unit>

示例:
  instance:node_cpu_usage:ratio
  job:http_requests:rate5m
  cluster:node_memory_usage:avg
  service:http_latency:p99_5m
部分说明示例
level聚合级别instance, job, cluster
source数据来源node, http, grpc
metric指标名称cpu_usage, request_total
aggregation聚合方式rate5m, avg, p99, sum
unit单位ratio, seconds, bytes

常见命名模式

# 速率预计算
- record: job:http_requests:rate5m
  expr: sum by(job) (rate(http_requests_total[5m]))

# 分位数预计算
- record: job:http_request_duration:p99_5m
  expr: |
    histogram_quantile(0.99,
      sum by(job, le) (rate(http_request_duration_seconds_bucket[5m]))
    )

# 比率预计算
- record: instance:node_cpu_usage:ratio
  expr: |
    1 - avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m]))

9.4 预聚合最佳实践

分层聚合

原始指标(15s 采集)
    │
    ▼ 第一层:rate / 基础计算(30s)
    │
    ├── instance 级别聚合
    │
    ▼ 第二层:聚合到 job 级别(1m)
    │
    ├── job 级别聚合
    │
    ▼ 第三层:聚合到集群级别(5m)
    │
    └── cluster 级别聚合
groups:
  # 第一层:基础 rate 计算
  - name: http_requests_rate
    interval: 30s
    rules:
      - record: instance:http_requests:rate5m
        expr: rate(http_requests_total[5m])

  # 第二层:job 级别聚合
  - name: http_requests_job
    interval: 1m
    rules:
      - record: job:http_requests:rate5m
        expr: sum by(job) (instance:http_requests:rate5m)

      - record: job:http_errors:rate5m
        expr: sum by(job) (instance:http_requests:rate5m{status=~"5.."})

      - record: job:http_error_ratio:ratio
        expr: job:http_errors:rate5m / job:http_requests:rate5m

  # 第三层:集群级别聚合
  - name: http_requests_cluster
    interval: 5m
    rules:
      - record: cluster:http_requests:rate5m
        expr: sum by(cluster) (job:http_requests:rate5m)

节点基础指标预聚合

groups:
  - name: node_recording
    interval: 30s
    rules:
      # CPU 使用率(每实例)
      - record: instance:node_cpu_usage:ratio
        expr: |
          1 - avg by(instance) (
            rate(node_cpu_seconds_total{mode="idle"}[5m])
          )

      # 内存使用率
      - record: instance:node_memory_usage:ratio
        expr: |
          1 - (
            node_memory_MemAvailable_bytes
            / node_memory_MemTotal_bytes
          )

      # 磁盘使用率
      - record: instance:node_filesystem_usage:ratio
        expr: |
          1 - (
            node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"}
            / node_filesystem_size_bytes{fstype!~"tmpfs|overlay"}
          )

      # 磁盘 IO 利用率
      - record: instance:node_disk_io_utilisation:ratio
        expr: |
          rate(node_disk_io_time_seconds_total[5m])

      # 网络接收速率 (bytes/s)
      - record: instance:node_network_receive:rate5m
        expr: |
          rate(node_network_receive_bytes_total{device!="lo"}[5m])

      # 网络发送速率 (bytes/s)
      - record: instance:node_network_transmit:rate5m
        expr: |
          rate(node_network_transmit_bytes_total{device!="lo"}[5m])

HTTP 服务指标预聚合

groups:
  - name: http_recording
    interval: 30s
    rules:
      # 请求速率(按 job, status)
      - record: job:http_requests:rate5m
        expr: sum by(job, status) (rate(http_requests_total[5m]))

      # 错误请求速率
      - record: job:http_errors:rate5m
        expr: sum by(job) (rate(http_requests_total{status=~"5.."}[5m]))

      # 总请求速率
      - record: job:http_all_requests:rate5m
        expr: sum by(job) (rate(http_requests_total[5m]))

      # 错误率
      - record: job:http_error_ratio:ratio
        expr: job:http_errors:rate5m / job:http_all_requests:rate5m

      # P50 延迟
      - record: job:http_duration:p50_5m
        expr: |
          histogram_quantile(0.50,
            sum by(job, le) (rate(http_request_duration_seconds_bucket[5m]))
          )

      # P90 延迟
      - record: job:http_duration:p90_5m
        expr: |
          histogram_quantile(0.90,
            sum by(job, le) (rate(http_request_duration_seconds_bucket[5m]))
          )

      # P99 延迟
      - record: job:http_duration:p99_5m
        expr: |
          histogram_quantile(0.99,
            sum by(job, le) (rate(http_request_duration_seconds_bucket[5m]))
          )

      # 平均延迟
      - record: job:http_duration:avg_5m
        expr: |
          rate(http_request_duration_seconds_sum[5m])
          / rate(http_request_duration_seconds_count[5m])

9.5 性能优化

减少原始指标查询

# ❌ 每个告警/图表都重复计算 rate
# 告警1: rate(http_requests_total[5m])
# 告警2: rate(http_requests_total[5m])
# Dashboard: rate(http_requests_total[5m])

# ✅ 使用录制规则预计算
# 录制规则: job:http_requests:rate5m = sum(rate(http_requests_total[5m]))
# 告警1: job:http_requests:rate5m
# 告警2: job:http_requests:rate5m
# Dashboard: job:http_requests:rate5m

降低采集频率

指标类型推荐间隔说明
基础 rate 计算15-30s与采集间隔相近
聚合指标30s-1m中间聚合层
高层聚合1-5m最终展示层

存储开销估算

新时间序列数 = 录制规则数 × 唯一标签组合数

示例:
  10 条录制规则 × 50 个 job = 500 条新时间序列
  每条序列每样本 2 字节,15s 间隔
  每天存储: 500 × (86400/15) × 2 bytes ≈ 5.76 MB/天
  15 天保留: ≈ 86.4 MB

9.6 告警规则中使用录制规则

groups:
  # 录制规则
  - name: http_recording
    interval: 30s
    rules:
      - record: job:http_error_ratio:ratio
        expr: |
          sum by(job) (rate(http_requests_total{status=~"5.."}[5m]))
          / sum by(job) (rate(http_requests_total[5m]))

  # 告警规则(使用录制结果)
  - name: http_alerts
    rules:
      - alert: HighErrorRate
        expr: job:http_error_ratio:ratio > 0.05
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "{{ $labels.job }} 错误率 {{ $value | humanizePercentage }}"

注意:告警规则引用录制规则时,录制规则必须先于告警规则评估。建议将录制规则放在告警规则之前的 group 中,或使用不同的 group name 确保顺序。


9.7 规则管理工具

验证规则语法

# 检查规则文件
promtool check rules /etc/prometheus/rules/*.yml

# 输出示例
# Checking /etc/prometheus/rules/recording.yml
#   SUCCESS: 15 rules found

查看规则状态

# 通过 API 查看规则状态
curl http://localhost:9090/api/v1/rules

# 查看特定组
curl http://localhost:9090/api/v1/rules?rule_group=http_recording

热重载规则

# 重载配置(包括规则文件)
kill -HUP $(pgrep prometheus)

# 或通过 API
curl -X POST http://localhost:9090/-/reload

9.8 常见问题

规则未执行

# 1. 检查规则语法
promtool check rules /etc/prometheus/rules/*.yml

# 2. 检查表达式是否返回数据
# 在 Prometheus Web UI 中测试 expr

# 3. 检查规则组评估日志
# 查看 Prometheus 日志中的规则评估信息

录制规则数据延迟

录制规则数据的延迟 = evaluation_interval + 计算时间。例如 evaluation_interval: 30s,数据最多延迟 30-60 秒。

规则评估超时

如果规则表达式过于复杂,可能导致评估超时。解决方案:

  • 简化表达式
  • 使用分层聚合
  • 增加 evaluation_timeout(默认 10s)

9.9 本章小结

要点说明
目的预计算复杂查询,提升性能
命名<level>:<source>_<metric>_<agg>:<unit>
分层原始 → rate → job聚合 → 集群聚合
最佳实践告警使用录制结果,Dashboard 使用录制结果
验证promtool check rules

扩展阅读


上一章08 - 告警规则编写 下一章10 - 服务发现