基于Prometheus 95分位数CPU指标配置HPA的技术咨询
我来一步步帮你解决这些问题,从核心的指标查询错误到生产环境的实践细节:
一、为什么你的histogram_quantile查询无数据?
你踩了一个常见的坑:histogram_quantile函数只能作用于Prometheus的直方图类型指标——也就是带有_bucket、_sum、_count后缀的指标组,这类指标是专门用来计算分位数的。而你用的namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate是计数器经过rate和sum处理后的Gauge类型指标,本质是单个数值,不是直方图,所以直接套histogram_quantile肯定返回空数据。
针对CPU使用率的分位数需求,你需要用quantile或quantile_over_time函数:
1. 计算Deployment下所有Pod的CPU使用率95分位数
这个指标反映的是「95%的Pod CPU使用率都低于该值」,适合作为HPA的全局阈值:
quantile(0.95, sum(rate(container_cpu_usage_seconds_total{namespace="api", container_name!="POD", pod_name=~"api-.+"}[2m])) by (pod_name))
rate(container_cpu_usage_seconds_total[2m]):计算每个容器2分钟内的CPU使用率(每秒消耗的CPU核数)sum(...) by (pod_name):聚合单个Pod下所有容器的CPU使用率,得到Pod级别的总使用率quantile(0.95, ...):对所有Pod的使用率计算95分位数
2. 计算单个Pod历史CPU使用率的95分位数
如果需要基于Pod的历史负载稳定性做扩缩容,可以用:
quantile_over_time(0.95, sum(rate(container_cpu_usage_seconds_total{namespace="api", container_name!="POD", pod_name=~"api-.+"}[2m])) by (pod_name)[10m:1m])
[10m:1m]:取过去10分钟的使用率数据,每1分钟一个采样点quantile_over_time:计算这段时间内单个Pod使用率的95分位数
二、自定义指标的Pod/Namespace自动填充问题
不会自动填充,你需要在prometheus-adapter的配置里显式定义标签映射,让适配器把Prometheus指标里的pod_name、namespace标签关联到Kubernetes的资源上。
举个完整的prometheus-adapter ConfigMap配置片段:
apiVersion: v1 kind: ConfigMap metadata: name: prometheus-adapter-config namespace: monitoring data: config.yaml: |- rules: # 定义Pod级别的CPU使用率95分位数指标 - seriesQuery: 'sum(rate(container_cpu_usage_seconds_total{container_name!="POD", pod_name!=""}[2m])) by (pod_name, namespace)' resources: overrides: namespace: {resource: "namespace"} pod_name: {resource: "pod"} name: matches: '^sum_rate_container_cpu_usage_seconds_total$' as: 'pod_cpu_usage_95th' metricsQuery: 'quantile(0.95, sum(rate(container_cpu_usage_seconds_total{container_name!="POD", pod_name!="", namespace!=""}[2m])) by (pod_name, namespace))'
这里的resources.overrides就是关键:把Prometheus的namespace标签映射为Kubernetes的namespace资源,pod_name映射为pod资源。配置完成后,prometheus-adapter会在Kubernetes API中暴露pod_cpu_usage_95th这个自定义指标,HPA可以直接引用,并且自动关联到对应的Pod和Namespace。
三、生产环境基于分位数实现HPA的最佳实践
1. 指标与阈值选择
- 优先用Pod集合的95分位数:过滤极端峰值,避免个别Pod的突发负载导致不必要的扩容
- 阈值设置要结合业务:比如如果你的Pod CPU请求是1核,那可以把目标阈值设为
700m(0.7核),预留一定缓冲空间
2. HPA配置细节
用autoscaling/v2版本的HPA,支持更灵活的扩缩容策略:
apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: api-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: api minReplicas: 2 maxReplicas: 10 metrics: - type: Pods pods: metric: name: pod_cpu_usage_95th target: type: AverageValue averageValue: 700m # 目标95分位数CPU使用率 behavior: scaleDown: stabilizationWindowSeconds: 300 # 5分钟内负载稳定才缩容,防止频繁波动 policies: - type: Percent value: 50 periodSeconds: 60 # 每次缩容最多减少50%的Pod scaleUp: stabilizationWindowSeconds: 60 # 1分钟内持续高负载才扩容,快速响应业务峰值 policies: - type: Percent value: 100 periodSeconds: 60 # 每次扩容最多翻倍Pod数量
3. 监控与调优
- 在Grafana中添加HPA面板:监控扩缩容事件、自定义指标的变化、Pod数量波动
- 调整时间窗口:如果扩容不及时,减小
rate的时间窗口(比如从2m改成1m);如果缩容太频繁,增大scaleDown.stabilizationWindowSeconds - 避免过度扩缩:设置合理的
maxReplicas,防止流量突增导致集群资源耗尽
内容的提问来源于stack exchange,提问作者codiaf

