在 Kubernetes 生产环境中,工作负载的流量曲线越来越难以用单一资源维度刻画。原生 HPA 基于 CPU 和内存的扩缩策略,在应对消息驱动型服务或长连接网关时常常失效。通过引入自定义指标,我们可以将业务语义层面的信号转化为扩缩依据,使副本数量真正跟随真实压力变化。

自定义指标的工作机制与架构链路
HPA 的扩缩决策依赖于 metrics 查询接口。当使用自定义指标时,集群需要部署 Metrics Adapter 组件,它负责将外部监控系统(如 Prometheus)中的时序数据,翻译成 Kubernetes API 所能识别的指标格式。HPA 控制器并不会直接连接监控系统,而是向 API 聚合层发起请求,聚合层再把请求转发给对应的 Adapter。这种解耦设计让 HPA 本身无需关心指标来源。
具体流程中,应用首先通过客户端库暴露符合 Prometheus 规范的端点,例如用 Counter 记录 HTTP 请求总量。Prometheus 定时抓取后存储为时序数据。Adapter 配置对应的发现规则,把诸如 http_requests_per_second 这样的指标映射为 custom.metrics.k8s.io 组下的资源。随后用户在 HPA 对象中引用该指标名并设定目标值,控制器便周期性计算当前值与目标值的比率来决定扩缩。
这一机制的优势在于扩展性强。除了请求率,还可以接入 Kafka 消费滞后量、Redis 连接数、甚至业务订单堆积数。但也带来新的挑战:指标链路变长后,任一环节延迟都会造成 HPA 决策滞后。因此在生产里通常将 Adapter 与 Prometheus 同可用区部署,并压缩抓取间隔到 15 秒级别,避免扩缩动作明显落后真实负载。
基于 Prometheus 的指标暴露与 Adapter 配置实例
我们以一个简单的 Go HTTP 服务为例,演示如何暴露请求率指标。服务使用官方 Prometheus 客户端,在处理函数中对计数器递增,并挂载 /metrics 端点。Kubernetes 的 Service 与 Pod 需添加 prometheus.io/scrape: "true" 注解以便被自动发现。
package main
import (
"net/http"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var reqCounter = prometheus.NewCounter(prometheus.CounterOpts{
Name: "http_requests_total",
Help: "Total number of HTTP requests",
})
func init() {
prometheus.MustRegister(reqCounter)
}
func handler(w http.ResponseWriter, r *http.Request) {
reqCounter.Inc()
w.Write([]byte("ok"))
}
func main() {
http.Handle("/metrics", promhttp.Handler())
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
Adapter 侧常用 kube-prometheus-stack 附带的 prometheus-adapter。其核心是配置文件中的 rules 段落,将 PromQL 查询结果绑定为自定义指标。例如下面规则把每秒请求率映射为名为 pods/http_requests_per_second 的指标,HPA 可直接引用。
rules:
- seriesQuery: 'http_requests_total'
resources:
overrides:
namespace: {resource: "namespace"}
pod: {resource: "pod"}
name:
matches: "http_requests_total"
as: "http_requests_per_second"
metricsQuery: 'sum(rate(http_requests_total[1m])) by (pod)'
配置生效后,使用 kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/http_requests_per_second" 可验证指标是否成功注册。若返回 JSON 中包含数值,说明链路通畅。这一步排查非常关键,很多 HPA 不生效的问题都源于 Adapter 规则匹配失败或权限不足。
扩缩策略调优与常见误区规避
即便指标接通,不合理的参数仍会导致集群抖动。HPA 默认的缩容冷却期为五分钟,扩容则较快。对于流量陡降明显的场景,过长冷却会让资源闲置;而对延迟敏感服务,频繁扩容可能引发冷启动雪崩。我们可以通过 behavior 字段精细控制扩缩速率,分别设定 scaleUp 与 scaleDown 的步长与稳定窗口。
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
minReplicas: 2
maxReplicas: 20
metrics:
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: "100"
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 50
periodSeconds: 60
另一个常见误区是直接使用未做聚合的原始指标。例如将 Pod 的瞬时错误数作为扩缩依据,会因偶发报错造成非理性扩容。正确做法是用速率或滑动平均值平滑,并在 PromQL 中按 Pod 或 Deployment 合理分组。此外,自定义指标名称必须保持稳定,CI 中修改监控埋点而不同步 Adapter 规则,会让 HPA 陷入永久未知指标状态。
从成本视角看,自定义指标让弹性更贴近业务,但也要求团队具备指标治理意识。建议将核心链路的指标纳入告警,并定期审视 HPA 事件,确认扩缩动作与流量曲线吻合。只有把指标质量、参数调优和监控闭环结合起来,集群弹性伸缩才能既省成本又不误事。
Kubernetes_HPA自定义指标弹性伸缩修改时间:2026-08-15 19:32:31