3. PromQL 聚合基础:回顾 sum、avg、max、min、count 等聚合函数
在构建误差预算告警体系之前,必须牢固掌握 PromQL 的聚合操作。聚合函数将一组时间序列(通常由 job、instance、service 等标签区分)合并为单一输出,是降噪和提炼关键指标的核心手段。
3.1 聚合函数速查表
以下五个聚合函数覆盖了 90% 的 SRE 监控场景。注意:聚合函数必须配合 by 或 without 子句使用,否则会丢失所有标签维度。
| 函数 | 行为描述 | 典型 SRE 场景 |
|---|---|---|
sum |
对指定维度内的所有序列值求和 | 计算集群总 QPS、总错误数、总请求延迟 |
avg |
计算指定维度内的算术平均值 | 平均 CPU 使用率、平均延迟、平均错误率 |
max |
取指定维度内的最大值 | 最慢实例的延迟、最高 CPU 节点、最大错误数 |
min |
取指定维度内的最小值 | 最低可用实例数、最小剩余磁盘空间 |
count |
统计指定维度内的时间序列数量 | 存活实例数、健康 Pod 数、满足条件的节点数 |
关键区别:
count 统计的是序列数量,而非数值总和。例如 count by (job) (up == 1) 返回每个 job 中健康实例的个数。
3.2 聚合行为与标签保留规则
聚合函数的行为由 by 和 without 子句控制,理解它们的差异是避免告警误报的基础。
by (label_list):显式声明保留哪些标签,其余标签全部丢弃。输出序列数 = 保留标签的笛卡尔积组合数。without (label_list):显式声明丢弃哪些标签,其余标签全部保留。适用于排除高基数标签(如instance)后观察服务级指标。
# 示例:按 job 聚合,丢弃 instance 标签
sum by (job) (rate(http_requests_total[5m]))
# 等价写法:丢弃 instance 和 pod 标签
sum without (instance, pod) (rate(http_requests_total[5m]))
常见陷阱:如果
by 子句中遗漏了关键标签(如 job),聚合结果会意外合并不同服务的指标,导致误差预算计算错误。始终先使用 count by (job, instance) 验证序列基数。
3.3 聚合在误差预算中的角色
在误差预算告警链中,聚合函数承担以下职责:
- 降维:将实例级指标(高基数)聚合为服务级指标(低基数),减少告警风暴。
- 归一化:通过
avg或sum / count计算比率,如错误率 =sum(rate(errors_total)) / sum(rate(requests_total))。 - 边界检测:使用
max或min发现异常实例,作为告警的补充信号。
实战建议:误差预算告警应优先使用
sum by (service) 聚合后的比率指标,而非原始实例级指标。这能过滤掉单实例抖动,聚焦服务整体健康度。
3.4 聚合函数行为对比图
下图展示了五个聚合函数在相同输入数据上的不同输出行为。输入为三个实例的 QPS 序列,聚合维度为 by (service)。
3.5 聚合与告警降噪的关联
在误差预算台账中,聚合函数直接影响告警的触发频率和准确度:
- 过度聚合(如全局
sum无by)会掩盖局部故障,导致告警延迟。 - 欠聚合(保留
instance标签)会导致单实例抖动触发大量告警,产生告警风暴。 - 最佳实践:误差预算告警使用
sum by (service, slo_class)聚合,保留服务级和 SLO 分类标签,丢弃实例级标签。
降噪效果示例:假设 100 个实例中有 3 个实例错误率突增。使用
max by (instance) 会触发 3 条告警;使用 avg by (service) 可能不触发(被正常实例稀释);使用 sum by (service) (errors) / sum by (service) (requests) 计算服务级错误率,只有当整体错误率超过 SLO 阈值时才告警,实现最佳降噪。
3.6 聚合函数选择决策树
在编写误差预算查询时,按以下决策树选择聚合函数:
3.7 常见聚合错误与排查
| 错误模式 | 现象 | 根因 | 修复方法 |
|---|---|---|---|
遗漏 by 子句 |
聚合结果只有一个值,丢失所有标签 | 全局聚合,未保留维度 | 添加 by (job, service) |
错误使用 avg 计算比率 |
比率值异常(如错误率 > 1) | avg 对每个序列独立求平均后再平均 |
改用 sum / sum 计算比率 |
| 高基数标签未排除 | 聚合结果序列数过多,查询缓慢 | without 未排除 instance、pod |
使用 without (instance, pod) |
count 误用于数值求和 |
结果远小于预期 | count 统计序列数而非数值 |
改用 sum |
调试技巧:在 Prometheus 的 Graph 页面中,先执行
count by (job, instance) (your_metric) 查看序列基数,再决定聚合维度。基数超过 100 的查询应考虑降维。