3. PromQL 进阶:聚合操作、子查询、Recording Rules 在容量分析中的应用
在容量压测与巡检场景中,原始指标往往无法直接反映系统瓶颈。PromQL 的聚合操作、子查询与 Recording Rules 是构建容量分析模型的三项核心能力。本章将逐一拆解其语法、适用场景及编排优化策略。
3.1 聚合操作:从多维数据中提取容量特征
聚合操作通过 by 或 without 子句对标签维度进行归并,是容量分析中最常用的数据降维手段。
3.1.1 常用聚合函数与容量语义
| 聚合函数 | 容量分析语义 | 典型场景 |
|---|---|---|
sum() |
计算资源总量或请求总量 | 集群 CPU 总使用率、总 QPS |
avg() |
平均负载水平 | 平均响应时间、平均磁盘 IO 等待 |
max() |
峰值压力点 | 单机最高内存使用率、最大延迟 |
quantile() |
分位数分布 | P99 延迟、P95 请求大小 |
topk() |
识别异常热点 | CPU 使用率最高的前 5 个容器 |
3.1.2 聚合操作在压测巡检中的典型用法
# 计算集群整体 CPU 使用率(按 instance 聚合后取平均)
avg by (cluster) (rate(node_cpu_seconds_total{mode!="idle"}[5m]))
# 找出内存使用率超过 80% 的前 10 个 Pod
topk(10, container_memory_working_set_bytes / container_spec_memory_limit_bytes > 0.8)
# 按机房维度统计 P99 延迟
quantile by (datacenter) (0.99, http_request_duration_seconds)
容量巡检最佳实践: 在压测脚本中,优先使用
by 保留关键分组标签(如 cluster、service),避免 without 意外丢弃维度导致数据混淆。
3.2 子查询:实现时间窗口内的二次计算
子查询允许在 PromQL 中对一个时间范围内的数据进行“查询中的查询”,常用于计算窗口内的聚合趋势或异常检测。
3.2.1 子查询语法结构
<instant_query> [<range>:<resolution>] [offset <duration>]
- instant_query:内层即时查询表达式
- range:外层时间窗口,如
[30m] - resolution:内层计算步长,如
:1m
3.2.2 容量分析中的子查询场景
| 场景 | 子查询表达式 | 说明 |
|---|---|---|
| 过去 1 小时内的最大 CPU 峰值 | max_over_time( rate(node_cpu_seconds_total[5m]) [1h:1m] ) |
每 1 分钟计算一次 5m 速率,再取 1h 最大值 |
| 检测持续 15 分钟以上的高内存 | min_over_time( (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes [15m:1m] ) > 0.9 |
确保 15 分钟内每个 1m 采样点都超过 90% |
| 压测期间平均 QPS 的波动范围 | stddev_over_time( rate(http_requests_total[1m]) [10m:30s] ) |
评估流量抖动程度 |
性能警告: 子查询会大幅增加 Prometheus 计算开销。在压测巡检脚本中,建议将子查询结果通过 Recording Rules 固化,避免每次查询都重复计算。
3.3 Recording Rules:预计算与查询加速
Recording Rules 允许将复杂的 PromQL 表达式预先计算并存储为新的时间序列,是容量分析脚本编排优化的核心手段。
3.3.1 Recording Rules 配置结构
groups:
- name: capacity_analysis
interval: 30s
rules:
- record: cluster:cpu_usage_avg:5m
expr: avg by (cluster) (rate(node_cpu_seconds_total{mode!="idle"}[5m]))
- record: service:p99_latency:1h
expr: quantile by (service) (0.99, rate(http_request_duration_seconds_sum[5m]) / rate(http_request_duration_seconds_count[5m]))
- record: instance:memory_pressure:1m
expr: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes > 0.85
3.3.2 容量分析中的 Recording Rules 设计原则
| 原则 | 说明 | 反例 |
|---|---|---|
| 按分析粒度分层 | 集群级、服务级、实例级分别定义规则 | 将所有聚合写在一个规则中 |
| 设置合理的评估间隔 | 压测场景用 15-30s,巡检场景用 1-5m | 所有规则统一使用 15s |
| 命名规范可溯源 | 使用 level:metric:window 格式 |
随意命名如 rule1 |
| 避免过度预计算 | 只固化高频查询或高开销表达式 | 对简单 rate() 也做 Recording Rule |
3.4 三者协同:容量压测巡检脚本编排模型
聚合操作、子查询与 Recording Rules 并非孤立使用,而是形成一套从原始数据到告警阈值的完整链路。
编排流程: 原始指标 → 聚合操作(降维) → 子查询(窗口检测) → Recording Rules(固化) → 巡检脚本(阈值判断)
3.5 实战案例:压测脚本中的容量阈值编排
以下是一个完整的压测巡检脚本片段,展示聚合、子查询与 Recording Rules 的协同使用。
3.5.1 定义 Recording Rules
groups:
- name: stress_test_capacity
interval: 30s
rules:
- record: stress:cluster:cpu_peak:15m
expr: max_over_time( avg by (cluster) (rate(node_cpu_seconds_total{mode!="idle"}[2m]) ) [15m:30s] )
- record: stress:service:mem_sustained:10m
expr: min_over_time( (container_memory_working_set_bytes / container_spec_memory_limit_bytes) [10m:1m] )
3.5.2 巡检脚本中的阈值判断
# 判断集群 CPU 峰值是否超过 85%
stress:cluster:cpu_peak:15m > 0.85
# 判断服务内存持续压力是否超过 90%
stress:service:mem_sustained:10m > 0.9
# 结合子查询检测突发流量(过去 5 分钟内 QPS 增长超过 200%)
rate(http_requests_total[1m]) / avg_over_time(rate(http_requests_total[1m])[30m:1m]) > 3
脚本编排建议: 将 Recording Rules 的评估间隔与压测脚本的巡检周期对齐(如均为 30s),避免因时间窗口错位导致误告警。同时,在脚本中优先引用预计算指标,减少实时 PromQL 计算对 Prometheus 的压力。
3.6 本章小结
- 聚合操作是容量分析的基石,通过
by/without控制维度粒度,使用quantile/topk识别异常。 - 子查询提供时间窗口内的二次计算能力,适用于持续异常检测和峰值分析,但需注意性能开销。
- Recording Rules 将高频或高开销查询预计算固化,是压测巡检脚本性能优化的关键手段。
- 三者协同形成“原始指标 → 聚合降维 → 窗口检测 → 预计算固化 → 阈值判断”的完整编排链路。