Prometheus查询pod内存使用性能分位数
Prometheus query quantile of pod memory usage performance
我想获取我的 pods 上次 x 时间的 0.95 个百分点的内存使用情况。但是,如果我使用 'big' (7 / 10d) 范围,此查询开始花费的时间太长。
我现在使用的查询是:
quantile_over_time(0.95, container_memory_usage_bytes[10d])
大约需要 100 秒才能完成
为简洁起见,我删除了额外的命名空间过滤器
我可以采取哪些步骤来提高此查询的性能? (除了把机器做大)
我考虑过每 x 次(比如说 30 分钟)计算 0.95 个百分位数并将其标记为 p95_memory_usage 并在查询中使用 p95_memory_usage 而不是 container_memory_usage_bytes,这样我就可以减少查询必须经过的点数。
但是,这不会扭曲价值观吗?
正如您已经观察到的那样,聚合分位数(随着时间或其他原因)并没有真正起作用。
您可以尝试使用记录规则构建内存使用率随时间变化的直方图,看起来像 "real" Prometheus 直方图(由 _bucket
、_count
和 _sum
指标)尽管这样做可能很乏味。类似于:
- record: container_memory_usage_bytes_bucket
labels:
le: 100000.0
expr: |
container_memory_usage_bytes > bool 100000.0
+
(
container_memory_usage_bytes_bucket{le="100000.0"}
or ignoring(le)
container_memory_usage_bytes * 0
)
重复您感兴趣的所有存储桶大小,添加 _count
和 _sum
指标。
直方图可以毫无问题地聚合(随时间或其他方式),因此您可以使用第二组记录规则计算直方图指标的增加,分辨率低得多(例如每小时或每天增加,每小时或每日分辨率)。最后,您可以在低分辨率直方图(样本比原始时间序列少很多)上使用 histogram_quantile
来计算分位数。
虽然工作量很大,但也会有一些缺点:您只会得到 hourly/daily 分位数的更新,并且准确度可能会较低,具体取决于您使用的直方图桶的数量定义。
否则(这是我在写完以上所有内容后才想到的)您可以定义一个以较低分辨率运行的记录规则(例如每小时一次)并记录 container_memory_usage_bytes
指标的当前值。然后你可以继续使用 quantile_over_time
这个较低的分辨率指标。你显然会失去精度(因为你扔掉了很多样本)并且你的分位数每小时只会更新一次,但它要简单得多。而你只需要等待 10 天,看看结果是否足够接近。 (o:
quantile_over_time(0.95, container_memory_usage_bytes[10d])
查询可能会很慢,因为它需要考虑过去 10 天所有 container_memory_usage_bytes
时间序列的所有原始样本。要处理的样本数量可能非常大。可以通过以下查询进行估算:
sum(count_over_time(container_memory_usage_bytes[10d]))
请注意,如果 quantile_over_time(...)
查询用于在 Grafana 中构建图形(又名 range query
而不是 instant query
),那么从 sum(count_over_time(...))
必须乘以 Grafana 图上的点数,因为 Prometheus 对显示图上的每个点单独执行 quantile_over_time(...)
。通常 Grafana 需要大约 1000 个点来构建平滑图。因此,从 sum(count_over_time(...))
返回的数字必须乘以 1000,以估计 Prometheus 需要处理以构建 quantile_over_time(...)
图的原始样本数。在 this article 中查看更多详细信息。
减少查询时长有以下解决方案:
- 添加更具体的标签过滤器以减少所选时间序列的数量,从而减少要处理的原始样本的数量。
- 减少方括号中的lookbehind window。例如,将
[10d]
更改为 [1d]
可将要处理的原始样本数量减少 10 倍。
- 使用 recording rules 计算 coarser-grained 结果。
- 尝试使用其他 Prometheus-compatible 系统,这可能会以更快的速度处理繁重的查询。例如,尝试 VictoriaMetrics.
我想获取我的 pods 上次 x 时间的 0.95 个百分点的内存使用情况。但是,如果我使用 'big' (7 / 10d) 范围,此查询开始花费的时间太长。
我现在使用的查询是:
quantile_over_time(0.95, container_memory_usage_bytes[10d])
大约需要 100 秒才能完成
为简洁起见,我删除了额外的命名空间过滤器
我可以采取哪些步骤来提高此查询的性能? (除了把机器做大)
我考虑过每 x 次(比如说 30 分钟)计算 0.95 个百分位数并将其标记为 p95_memory_usage 并在查询中使用 p95_memory_usage 而不是 container_memory_usage_bytes,这样我就可以减少查询必须经过的点数。
但是,这不会扭曲价值观吗?
正如您已经观察到的那样,聚合分位数(随着时间或其他原因)并没有真正起作用。
您可以尝试使用记录规则构建内存使用率随时间变化的直方图,看起来像 "real" Prometheus 直方图(由 _bucket
、_count
和 _sum
指标)尽管这样做可能很乏味。类似于:
- record: container_memory_usage_bytes_bucket
labels:
le: 100000.0
expr: |
container_memory_usage_bytes > bool 100000.0
+
(
container_memory_usage_bytes_bucket{le="100000.0"}
or ignoring(le)
container_memory_usage_bytes * 0
)
重复您感兴趣的所有存储桶大小,添加 _count
和 _sum
指标。
直方图可以毫无问题地聚合(随时间或其他方式),因此您可以使用第二组记录规则计算直方图指标的增加,分辨率低得多(例如每小时或每天增加,每小时或每日分辨率)。最后,您可以在低分辨率直方图(样本比原始时间序列少很多)上使用 histogram_quantile
来计算分位数。
虽然工作量很大,但也会有一些缺点:您只会得到 hourly/daily 分位数的更新,并且准确度可能会较低,具体取决于您使用的直方图桶的数量定义。
否则(这是我在写完以上所有内容后才想到的)您可以定义一个以较低分辨率运行的记录规则(例如每小时一次)并记录 container_memory_usage_bytes
指标的当前值。然后你可以继续使用 quantile_over_time
这个较低的分辨率指标。你显然会失去精度(因为你扔掉了很多样本)并且你的分位数每小时只会更新一次,但它要简单得多。而你只需要等待 10 天,看看结果是否足够接近。 (o:
quantile_over_time(0.95, container_memory_usage_bytes[10d])
查询可能会很慢,因为它需要考虑过去 10 天所有 container_memory_usage_bytes
时间序列的所有原始样本。要处理的样本数量可能非常大。可以通过以下查询进行估算:
sum(count_over_time(container_memory_usage_bytes[10d]))
请注意,如果 quantile_over_time(...)
查询用于在 Grafana 中构建图形(又名 range query
而不是 instant query
),那么从 sum(count_over_time(...))
必须乘以 Grafana 图上的点数,因为 Prometheus 对显示图上的每个点单独执行 quantile_over_time(...)
。通常 Grafana 需要大约 1000 个点来构建平滑图。因此,从 sum(count_over_time(...))
返回的数字必须乘以 1000,以估计 Prometheus 需要处理以构建 quantile_over_time(...)
图的原始样本数。在 this article 中查看更多详细信息。
减少查询时长有以下解决方案:
- 添加更具体的标签过滤器以减少所选时间序列的数量,从而减少要处理的原始样本的数量。
- 减少方括号中的lookbehind window。例如,将
[10d]
更改为[1d]
可将要处理的原始样本数量减少 10 倍。 - 使用 recording rules 计算 coarser-grained 结果。
- 尝试使用其他 Prometheus-compatible 系统,这可能会以更快的速度处理繁重的查询。例如,尝试 VictoriaMetrics.