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 - 服务发现