很高兴宣布:Kubernetes指标的原生直方图支持已进入Beta阶段,并在Kubernetes v1.37中默认启用!
原生直方图此前通过KEP-5808在Kubernetes v1.36中以Alpha功能引入,为Kubernetes指标带来高分辨率、低基数的可观测性。采用Prometheus原生直方图后,Kubernetes组件能够以更高精度公开延迟与持续时间指标,同时显著降低遥测数据存储和抓取开销。 (KEP-5808;Prometheus Native Histograms)
为什么要超越经典直方图?
从Kubernetes可观测性的早期开始,持续时间与延迟指标,例如API服务器请求延迟、调度耗时,就一直依赖经典Prometheus直方图。
经典直方图要求指标作者定义一组静态的累积桶边界(le标签),例如0.005、0.01、0.025、0.05、0.1、0.25、0.5、1、2.5、5、10。虽然这种方式很熟悉,但它带来三个主要挑战:
- 猜测桶边界:工作负载的延迟分布发生变化时,例如移到微秒范围,或出现超过最高桶的长尾延迟,直方图会失去观察能力。提前指定桶边界,意味着在观察分布之前就要知道分布。
- 高基数与存储成本:经典直方图把每个桶边界导出为独立时间序列(_bucket{le=”…”})。一个包含10个桶、具有多个标签的直方图,会让时间序列数量乘以10,增加Prometheus内存消耗和时间序列数据库(TSDB)的存储成本。
- 分位数插值误差:使用histogram_quantile()计算百分位数时,依赖静态桶边界之间的线性插值。如果桶跨度较大,分位数计算可能出现显著估计误差。
什么是Prometheus原生直方图?
Prometheus原生直方图使用动态指数桶,替代用户定义的静态桶。 (Prometheus Native Histograms)
它不再为每个桶边界生成独立时间序列,而是将原生直方图存储为单一时间序列,包含描述正负跨度、零阈值和指数缩放因子的丰富结构。
- 自动获得高分辨率:指数桶动态适应任意数值范围,从纳秒到小时,无需预先配置桶边界。
- 时间序列最多减少90%:将桶整合为单一时间序列中的结构化跨度,显著减少抓取和存储开销。
- 精确计算分位数:在整个观测值范围内,可以用数学上有界的误差计算分位数;默认配置下最坏相对误差约为5%。
原生直方图在Kubernetes中如何工作
Kubernetes在共享指标子系统k8s.io/component-base/metrics中直接实现原生直方图支持。
图1展示Kubernetes各组件如何处理并公开原生直方图指标。
图1:Kubernetes中的原生直方图处理与双格式公开流程。
1. 双格式公开,不破坏现有兼容性
KEP-5808的一项主要设计要求,是不干扰现有可观测性系统。启用NativeHistograms特性门控后,Kubernetes组件使用双格式公开:
- 经典桶(h.Bucket)仍与原生跨度一同输出。依赖传统文本抓取或经典桶标签的现有Prometheus服务器、仪表盘和告警规则,无需修改即可继续工作。
- 原生跨度(h.Schema、h.PositiveSpan)包含在同一Protobuf负载中,供理解原生直方图的采集器使用。
2. 经过调优的默认指数配置
启用NativeHistograms后,k8s.io/component-base/metrics包自动为所有直方图指标应用标准化的指数选项:
- BucketFactor: 1.1:配置指数桶,每个桶最多比前一个桶宽10%。无论操作耗时1毫秒还是10秒,分位数计算的最坏相对误差都具有数学上界,最多约为5%。
- MaxBucketNumber: 160:把每个直方图的最大桶数量限制为160。这个上限遵循OpenTelemetry SDK对以2为底的指数直方图聚合的建议,即使遇到极端离群值分布,也能保护组件的内存使用。
3. 广泛的组件支持
由于原生直方图集成在component-base/metrics中,所有主要Kubernetes控制平面及节点组件都会自动继承支持,包括:
- kube-apiserver,例如apiserver_request_duration_seconds、身份验证与授权指标、校验延迟。
- kube-scheduler,例如scheduler_plugin_execution_duration_seconds、scheduler_scheduling_algorithm_duration_seconds。
- kubelet,包含节点级容器运行时与Pod生命周期指标。
- kube-controller-manager和kube-proxy。
如何抓取原生直方图
简短的答案是:升级到Kubernetes v1.37,就可以使用。
Kubernetes v1.37默认启用NativeHistograms,因此集群已经公开双格式指标。如何配置Prometheus抓取原生直方图,取决于Prometheus版本:
1. 按版本配置Prometheus抓取
-
Prometheus 3.0及以上(推荐):在scrape_configs中使用明确的逐任务配置,替代全局标志。Prometheus 3.9及以上已弃用全局–enable-feature=native-histograms标志:
scrape_configs: - job_name: 'kubernetes-apiservers' scrape_native_histograms: true always_scrape_classic_histograms: true # Recommended during transition必须阅读原生直方图文档中“迁移仪表盘与告警”的注意事项。简而言之:过渡期间始终设置always_scrape_classic_histograms: true。没有此设置时,Prometheus只摄取原生格式,停止摄取经典_bucket、_count和_sum序列。设置always_scrape_classic_histograms: true,可以保证现有仪表盘(histogram_quantile(…_bucket…))和告警在迁移到原生直方图期间继续工作。 (迁移仪表盘与告警)
-
Prometheus 2.40至2.x:启动Prometheus时设置以下特性标志,在全局启用原生直方图:
prometheus --enable-feature=native-histograms注意,在Prometheus 2.x中,这个设置对全部抓取目标统一生效,不能逐个选择。
2. 验证Protobuf双格式公开
标准Prometheus文本抓取(application/openmetrics-text或纯文本格式)只传输经典桶。启用scrape_native_histograms后,Prometheus会自动与Kubernetes端点协商Protobuf格式。
可以使用curl并通过Accept请求头指定Protobuf,验证Kubernetes组件是否正在导出原生直方图。例如:
## THIS IS NOT SECURE. ONLY DO THIS IN A TEST CONTEXT.
curl --insecure \
-H "Accept: application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited" \
--header "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
https://localhost:6443/metrics
解码后,直方图指标(如apiserver_request_duration_seconds)返回的MetricFamily将同时包含传统bucket条目及已填充的schema、positive_span字段。
在PromQL中查询原生直方图
Prometheus摄取原生直方图之后,可以使用标准PromQL直方图函数查询,无需静态le桶标签或_bucket后缀:
# 1. Calculating P99 latency for a single target:
# Classic histogram (requires _bucket suffix):
histogram_quantile(0.99, rate(apiserver_request_duration_seconds_bucket[5m]))
# Native histogram (operates directly on the metric name):
histogram_quantile(0.99, rate(apiserver_request_duration_seconds[5m]))
# 2. Aggregating across multiple instances (e.g., all API servers):
# Classic histogram (requires sum by (le) to preserve bucket boundaries):
histogram_quantile(0.99, sum by (le) (rate(apiserver_request_duration_seconds_bucket[5m])))
# Native histogram (no grouping by le required!):
histogram_quantile(0.99, sum(rate(apiserver_request_duration_seconds[5m])))
使用原生直方图时,histogram_quantile()等函数直接操作时间序列内部的动态指数跨度,得到高精度分位数,避免静态桶插值误差。
关于在PromQL中查询原生直方图的官方文档,请参阅:
- PromQL histogram_quantile文档 (PromQL histogram_quantile documentation)
- PromQL histogram_fraction文档 (PromQL histogram_fraction documentation)
- PromQL histogram_sum文档 (PromQL histogram_sum documentation)
- PromQL histogram_count文档 (PromQL histogram_count documentation)
- PromQL histogram_count文档(原文重复列出) (PromQL histogram_count documentation)
- PromQL histogram_stddev与histogram_stdvar文档 (PromQL histogram_stddev and histogram_stdvar documentation)
仪表盘迁移与回滚策略
推荐的迁移工作流
为了安全地将监控基础架构迁移到原生直方图,同时保持现有告警和仪表盘正常,我建议采用四步流程:
- 启用两种格式:在Prometheus 3.x抓取配置中,同时设置scrape_native_histograms: true与always_scrape_classic_histograms: true,在过渡期间安全采集两种格式。
- 迁移查询:将Grafana仪表盘与Prometheus告警规则从经典分位数查询histogram_quantile(…_bucket…)改为原生直方图查询histogram_quantile(…),并将经典_count、_sum序列引用替换为histogram_count(…)、histogram_sum(…)。
- 在预发布或生产环境验证:使用新的原生直方图查询,检查所有仪表盘和SLO告警能否正确绘图与触发。
- 获得约10倍存储节省:迁移完成后,设置always_scrape_classic_histograms: false。Prometheus将停止摄取静态_bucket、_count与_sum时间序列,直方图时间序列数量最多减少90%!
可退出与灵活回滚
因为原生直方图以双格式公开,从采集器角度看,是否使用它完全由你选择:
- 立即回滚采集器:需要停止摄取原生直方图时,只需在Prometheus任务配置中设置scrape_native_histograms: false。无需重启Kubernetes,Prometheus会立即恢复为只抓取经典格式,且不丢失数据。
- 回滚组件特性门控:管理员也可以在Kubernetes组件上使用–feature-gates=NativeHistograms=false禁用特性门控,但需要重启组件。
下一步与参与方式
原生直方图将在未来Kubernetes版本中继续迈向正式可用(GA)。SIG Instrumentation将持续评估生态系统准备情况、性能特征,以及长期计划:当监控社区普遍采用原生直方图后,最终弃用静态经典桶。
- 阅读KEP-5808页面或KEP GitHub议题,了解更多信息。 (KEP-5808页面;KEP GitHub议题)
- 阅读Prometheus原生直方图规范和PromQL查询函数文档。 (Prometheus原生直方图规范;PromQL查询函数文档)
- 在Slack的#sig-instrumentation频道参与SIG Instrumentation,或加入每周SIG会议。 (SIG Instrumentation)
致谢
衷心感谢SIG Instrumentation的贡献者与各组件负责人,共同完成Kubernetes原生直方图的设计、实现、测试及审查!











暂无评论内容