自定义指标 HPA 怎么工作
HPA 控制器周期性读取指标,按「当前值 ÷ 目标值」计算期望副本数并调整工作负载。默认它只能拿 CPU 与内存(metrics.k8s.io);要按 QPS、队列深度、连接数这类业务指标伸缩,就要通过 custom.metrics.k8s.io(Pod 或对象维度)与 external.metrics.k8s.io(集群外指标)暴露,通常由 prometheus-adapter、KEDA 之类适配器把监控系统的数据转换成这些 API。指标 APIService 不可用时,HPA 会报获取指标失败并停止扩缩。
基本信息
| 适用对象 | autoscaling/v2 的 HorizontalPodAutoscaler |
|---|---|
| 依赖条件 | metrics.k8s.io、custom.metrics.k8s.io、external.metrics.k8s.io 三类 APIService |
| 度量写法 | AverageValue、Value、AverageUtilization 等类型 |
| 常见实现 | prometheus-adapter、KEDA,以及云厂商提供的适配器 |
| 前置检查 | kubectl get apiservices | grep -E 'custom|external' |
典型使用场景
- 按每秒请求数扩容:CPU 使用率与真实负载相关性差的网关类服务
- 按队列深度扩容:消费者按积压量提前扩容而不是等 CPU 打满
- 按连接数扩容:长连接网关用连接数比 CPU 更能反映容量
- 按业务漏斗指标扩容:登录数、下单量等直接反映压力的指标
- 事件驱动伸缩:用 KEDA 按消息队列长度从零扩容
Pods 自定义指标片段
Pods 自定义指标片段
metrics:
- type: Pods # 指标来自每个 Pod 的平均值
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: "800" # 每 Pod 目标 800 req/s
- type: External # 集群外指标(如消息队列积压)
external:
metric:
name: rabbitmq_queue_messages
target:
type: Value
value: "1000"确认适配器与取值
确认适配器与取值
kubectl get apiservices | grep -E 'custom|external'
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta2" | head -c 300
kubectl get hpa web-hpa -o jsonpath='{.status.currentMetrics}'
kubectl describe hpa web-hpa | tail -15 # 拿不到指标时这里给出原因指标类型对照
| 类型 | 维度 | 典型指标 |
|---|---|---|
| Resource | 容器或 Pod | CPU、内存使用率 |
| Pods | 每个 Pod 的平均值 | 每 Pod 请求数、连接数 |
| Object | 某个对象 | Ingress 请求数、与服务绑定的指标 |
| External | 集群外系统 | 消息队列积压、云监控数据 |
配置写错时最典型的报错是 unable to get metric 或 failed to get ... metric:先按适配器的命名规则核对指标名与标签,再检查指标系统里是否真有该时间序列。
业务指标往往滞后于压力变化,扩容决策会慢半拍:配合合理的冷却窗口与提前量设计,避免刚扩完就缩的抖动。
排查时按「指标系统 → 适配器 → 指标 API → HPA 状态」的顺序逐层看:先在监控里确认时间序列存在,再看适配器能否查询到,最后看 HPA 的 status 与事件,能省下大量猜测时间。