3. HPA高级配置:自定义指标、多指标伸缩、行为策略(behavior)

好,咱们继续深入。基础HPA配置,说白了就是根据CPU或内存来扩缩容。但实际生产环境里,哪有这么简单?我见过太多团队,业务高峰期CPU才30%,但请求延迟已经飙到天上去了。这时候,你就得用上HPA的高级玩法了。

3.1 自定义指标:让HPA听懂你的业务语言

默认的CPU和内存指标,其实挺粗糙的。你想想看,一个Web应用,用户排队等响应,CPU可能并不高,但队列长度已经爆炸了。这时候扩缩容的依据,应该是“队列深度”或者“每秒请求数”,而不是CPU。

Kubernetes支持自定义指标,通过 external.metricspods.metrics 来引用。我习惯用Prometheus Adapter来桥接,把Prometheus里的业务指标暴露给HPA。

举个例子,假设你的应用暴露了一个 http_requests_per_second 指标。配置起来大概是这样的:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: webapp-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: webapp
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Pods
    pods:
      metric:
        name: http_requests_per_second
      target:
        type: AverageValue
        averageValue: 100

这里的关键是 type: Pods,它会从每个Pod上拉取指标,然后算平均值。目标值是每个Pod处理100 QPS。超过这个值,HPA就会加Pod。

我的经验:自定义指标采集有个坑——指标延迟。Prometheus拉取周期默认15秒,HPA评估周期默认也是15秒。两下一叠加,响应可能慢30秒以上。我建议把Prometheus的采集间隔调到10秒,HPA的 --horizontal-pod-autoscaler-sync-period 也调到10秒。

3.2 多指标伸缩:别让单一指标骗了你

单一指标伸缩,容易误判。比如只看CPU,内存爆了它不管。只看QPS,后端数据库连接池满了它也不知道。所以,生产环境我强烈建议用多指标。

HPA支持同时配置多个指标,它会取所有指标中 最激进的那个 作为最终决策。什么意思呢?就是哪个指标要求扩的Pod多,就听谁的。

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: multi-metric-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  minReplicas: 3
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
  - type: Pods
    pods:
      metric:
        name: request_latency_seconds
      target:
        type: AverageValue
        averageValue: 0.5

这个配置同时监控CPU、内存和请求延迟。只要有一个指标超标,就会触发扩容。我曾经遇到过内存泄漏的应用,CPU一直正常,但内存悄悄涨到90%。多亏了内存指标,HPA及时扩容,没让服务挂掉。

注意:多指标不是越多越好。指标太多,HPA评估时会取最大值,可能导致频繁扩缩。我一般建议不超过3个核心指标。选指标时,选那些真正反映“系统瓶颈”的,而不是“系统状态”的。

3.3 行为策略(behavior):给HPA装上“阻尼器”

默认的HPA行为,其实挺“愣”的。指标一波动,它就跟着动。结果呢?Pod刚启动起来,指标又降了,它又把Pod缩掉。这种“抖动”在线上是非常危险的。

Kubernetes v1.18之后引入了 behavior 字段,让你可以精细控制扩缩容的行为。说白了,就是给HPA装上“阻尼器”和“加速器”。

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: behavior-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  minReplicas: 2
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 10
        periodSeconds: 60
      - type: Pods
        value: 2
        periodSeconds: 60
      selectPolicy: Min
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
      - type: Percent
        value: 100
        periodSeconds: 15
      - type: Pods
        value: 4
        periodSeconds: 15
      selectPolicy: Max

这段配置,我拆开来讲。

3.3.1 缩容策略:慢一点,稳一点

stabilizationWindowSeconds: 300 是“冷静期”。意思是,指标降到目标值以下后,HPA会等300秒再决定是否缩容。这能有效避免因为瞬时波动导致的误缩。

缩容策略我用了两条:

  • 每分钟最多缩容10%的Pod
  • 每分钟最多缩容2个Pod

selectPolicy: Min 表示取这两个策略中 更保守 的那个。也就是每分钟最多缩2个Pod。这样即使指标降得很快,Pod也不会一下子全没了。

核心思想:扩容要快,缩容要慢。这是生产环境HPA配置的黄金法则。

3.3.2 扩容策略:快刀斩乱麻

扩容的 stabilizationWindowSeconds: 0,不等待,立即响应。因为流量突增时,每一秒都很宝贵。

扩容策略:

  • 每15秒最多扩容100%的Pod(翻倍扩容)
  • 每15秒最多扩容4个Pod

selectPolicy: Max 取更激进的策略。如果当前有3个Pod,100%就是加3个,但上限是4个,所以取4个。如果当前有10个Pod,100%是加10个,远超4个,那就取10个。这样在Pod少的时候能快速翻倍,Pod多的时候也能线性增长。

我曾经在一个电商大促项目中,就是因为没配behavior,结果流量突增时HPA反应太慢,导致服务雪崩。后来配上了这个策略,扩容速度提升了3倍,再也没出过问题。

3.4 综合配置示例:一个生产级的HPA

最后,我给你一个我常用的生产级配置模板。它结合了自定义指标、多指标和行为策略:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: production-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: production-app
  minReplicas: 3
  maxReplicas: 50
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
  - type: Pods
    pods:
      metric:
        name: requests_per_second
      target:
        type: AverageValue
        averageValue: 500
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 5
        periodSeconds: 60
      - type: Pods
        value: 1
        periodSeconds: 60
      selectPolicy: Min
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
      - type: Percent
        value: 200
        periodSeconds: 15
      - type: Pods
        value: 6
        periodSeconds: 15
      selectPolicy: Max

这个配置里,缩容非常保守——每分钟最多缩5%或1个Pod。扩容则非常激进——每15秒最多翻两倍或加6个Pod。嗯,这里要注意,minReplicas: 3 保证了即使业务低谷,也有3个Pod兜底。

避坑指南:我曾经把 minReplicas 设成1,结果那个Pod所在的节点挂了,业务直接中断。后来我养成了习惯,关键服务至少2个副本起步。另外,maxReplicas 不要设太大,要考虑后端资源(数据库连接池、缓存等)的承受能力。

好了,HPA高级配置就讲到这里。记住,弹性伸缩不是“自动挡”就完事了,你得根据业务特点调参。多观察、多调整,才能找到最适合你的那一组参数。