HPA 基于 CPU 扩缩容出现抖动,你会如何引入自定义指标并设置稳定窗口

解读

  1. 抖动本质:CPU 瞬时冲高→HPA 立即扩容→Pod 启动后 CPU 回落→HPA 立即缩容→流量再来又冲高,形成“扩-缩-扩”循环。
  2. 国内生产环境常见诱因:
    • 促销/整点秒杀带来的脉冲流量,CPU 采样周期 15 s 内被“尖刺”拉高;
    • Java 应用 Full GC 瞬时拉高 CPU,但仅持续 3–5 s;
    • 容器限额设置不合理,单核限流导致 CPU 被 throttle,利用率失真。
  3. 面试考点:
    • 能否跳出“调大 CPU 阈值”思维,用自定义指标刻画“真实业务压力”;
    • 能否利用 K8s 原生 stabilizationWindowSeconds、behavior.scaleDown/selectPolicy 等参数做“防抖”;
    • 能否给出可落地的灰度验证方案,兼顾国内云厂商(ACK、TKE、CCE)实现差异。

知识点

  1. 自定义指标链路
    Prometheus → Adapter(prometheus-adapter 或 alibaba-cloud-metrics-adapter)→ Metrics API(custom.metrics.k8s.io)→ HPA v2。
  2. HPA 行为策略
    • behavior.scaleDown.stabilizationWindowSeconds:缩容冷静期;
    • behavior.scaleDown.selectPolicy: Min,取所有指标中最保守的推荐副本数;
    • behavior.scaleDown.policies:可定义“过去 300 s 内最多缩 10%” 的步长限制。
  3. 业务层黄金指标
    • QPS/RT:gateway_request_qps{job="ingress-nginx"}、gateway_request_duration_seconds_bucket;
    • 队列积压:kafka_consumer_lag_sum、rocketmq_group_diff;
    • 线程池饱和度:tomcat_threads_busy_ratio。
  4. 采样窗口与 P95 聚合
    用 2 min 滑动 P95 过滤尖刺,比瞬时平均值更稳。
  5. 国内云差异
    • 阿里云 ACK:prometheus-adapter 需开启 alibaba-metrics-discovery,支持 SLB 7 层 QPS 直接透出;
    • 腾讯云 TKE:自定义指标需通过云监控 CLS 中转,adapter 版本 ≥0.10 才支持 selectPolicy。

答案

“出现抖动,我不会简单把 CPU 阈值从 70% 调到 85%,而是分三步走:

第一步,引入业务自定义指标。选最能代表‘用户压力’的指标,比如网关 QPS 或消息队列堆积量。以 Gateway QPS 为例,我们在 Prometheus 里记录 ingress-nginx 的 gateway_request_qps,adapter 配置:

  • seriesQuery: gateway_request_qps{namespace!=""} resources: {template: "<<.Resource>>"} name: {matches: "gateway_request_qps", as: "gateway_qps_per_pod"} metricsQuery: 'sum(rate(gateway_request_qps[2m])) by (<<.GroupBy>>) / count(pod:container_cpu_usage:sum{<<.LabelMatchers>>})'

得到“单 Pod 平均 QPS”指标,HPA 里同时监控 CPU 与 gateway_qps_per_pod。

第二步,设置稳定窗口与步长策略,防止毛刺触发扩缩。HPA v2 行为字段如下:

behavior: scaleDown: stabilizationWindowSeconds: 300 # 过去 5 min 内最大副本数 selectPolicy: Min policies: - type: Percent value: 10 periodSeconds: 60 # 每 60 s 最多缩 10% scaleUp: stabilizationWindowSeconds: 0 selectPolicy: Max policies: - type: Percent value: 50 periodSeconds: 60

这样即使 CPU 瞬时掉到 20%,也必须连续 5 min 保持低负载才真正缩容,且一次只缩 10%,把抖动幅度降到 1–2 Pod。

第三步,灰度验证。先在预发环境注入 2× 脉冲流量,持续 10 min,观察:

  • 扩容触发时间 ≤ 30 s,冷启动 RT 上涨不超过 20%;
  • 流量回落后,缩容动作延迟 5 min,副本数呈阶梯式下降,无回弹。
    通过后再上生产,并配合告警:若 10 min 内扩缩循环 ≥3 次,自动锁住 HPA 手动介入。”

拓展思考

  1. 如果业务是“定时任务型”,CPU 每天 02:00 突增 3 min,是否仍用 QPS?可改用 CronHPA 提前扩容,避免与实时指标混用。
  2. 国内部分金融客户要求“副本数不能低于 3”,可通过 HPA 的 minReplicas 硬限制,但突发高峰可能仍不足,可再引入 KEDA 的“队列长度 + Cron”混合触发器。
  3. 当集群节点池开启 CA(Cluster Autoscaler)时,HPA 扩容后若节点不够,CA 再扩容节点,整体冷启动可能 3–5 min,需把 stabilizationWindowSeconds 与 CA 的扩容信号联动,防止“Pod 已缩、节点才到”的浪费。