一、弹性伸缩组(Kubernetes HPA)触发异常的常见表现

很多开发同学在接触云原生服务的时候,都会遇到这样的场景:部署的Web服务配置了自动扩缩容,本来想着能根据业务量自动调整Pod数量,省得手动操作,但实际用起来却发现,要么业务量涨了CPU超标,HPA没动静;要么业务量降了好半天,Pod还没缩下去。就像咱们开一家小饭馆,规定客人超过10个就加服务员,结果客人满座了,收银台却没统计到人数,或者刚加了服务员,又马上要求再加,显得乱哄哄的,反而影响效率。

1.1 真实场景还原

举个最近公司的例子:咱们的电商小程序后端用K8s集群部署,HPA配置了最小Pod数2个,最大10个,CPU使用率阈值设的是70%。上周六晚场直播,商品销量突然暴涨,后端Pod的CPU很快冲到了80%,但集群里的Pod数量一直停在2个,没触发扩容,导致后续请求排队,服务响应慢了好几秒,差点出问题。后来排查才发现,根源是冷却时间和指标采集的问题。

二、核心根源一:冷却时间的"隐形门槛"

弹性伸缩的冷却时间,其实就是系统为了避免频繁扩缩容带来的波动,设置的缓冲时间。就像你刚加了一个服务员,总不能过1分钟又加另一个,得等服务员到位,运转顺畅了再调整,这段等待的时间就是冷却时间。很多人不知道的是,K8s里的HPA有两个核心冷却参数:扩容冷却(scale-up stabilization window)和缩容冷却(scale-down stabilization window),如果设置不对,就会导致该扩容的时候不扩容,该缩容的时候不缩。

2.1 错误的冷却配置导致的异常

举个具体的K8s HPA配置示例,咱们写个错误的配置,注释里标清楚问题:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web-hpa
  namespace: default
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-deploy
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  # 错误设置:扩容冷却设成1分钟,但缩容冷却也设成1分钟,不合理
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60  # 扩容冷却1分钟,意思是CPU超标后,要等1分钟才会触发扩容
      policies:
      - type: Percent
        value: 100
        periodSeconds: 15
    scaleDown:
      stabilizationWindowSeconds: 60  # 缩容冷却1分钟,意思是CPU降下来后,要等1分钟才会触发缩容
      policies:
      - type: Percent
        value: 10
        periodSeconds: 60

这个配置的问题在于,扩容冷却只有1分钟,而咱们那次的CPU spike只持续了40秒,还没等冷却时间到,CPU就稍微降了一点,HPA以为业务量没那么大,就没触发扩容,导致Pod数量不够。

三、核心根源二:指标采集的"时间差陷阱"

另一个常见问题是指标采集的时延,就像饭馆的收银台是每隔5分钟统计一次客人数量,而不是实时统计,结果客人在第4分钟满座,到第5分钟统计的时候,刚好客人走了一波,统计下来人数没到阈值,就不会加服务员。在K8s里,指标(比如CPU、内存)是由metrics-server组件定期采集的,采集间隔的设置会直接影响HPA的判断。

3.1 指标采集时延导致的误判

咱们来看metrics-server的配置示例,假设采集间隔设的太长,导致HPA拿到的指标不是实时数据:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: metrics-server
  namespace: kube-system
spec:
  template:
    spec:
      containers:
      - name: metrics-server
        image: k8s.gcr.io/metrics-server/metrics-server:v0.6.1
        args:
        - --metric-resolution=1m  # 这里的意思是每1分钟采集一次指标
        - --kubelet-insecure-tls

这个参数--metric-resolution就是指标采集的间隔,如果你设成1分钟,那HPA的同步间隔(默认也是1分钟),就意味着业务的CPU spike如果持续时间小于1分钟,HPA根本拿不到实时的高CPU数据,自然不会触发扩容。之前咱们的直播场景里,CPU spike持续了40秒,刚好卡在采集间隔里,所以HPA没识别到,这也是异常的重要原因。

四、完整排查流程(按步骤来)

遇到弹性伸缩不触发的问题,别慌,按下面的步骤排查,准能找到问题:

4.1 第一步:先查HPA的事件日志

K8s的HPA会把事件记录下来,告诉你为什么没触发扩缩容,用下面的命令查看:

# 查看default命名空间下的web-hpa的事件
kubectl -n default describe hpa web-hpa

执行完这个命令,你会看到Events部分,里面如果有"Not enough metrics collected"或者"Scale in cooldown"这样的提示,就能快速定位是指标还是冷却的问题。比如之前咱们的场景,Events里就写了"Failed to scale up: waiting for scale-up cooldown to complete",说明是冷却时间的问题。

4.2 第二步:核对冷却时间参数

找到HPA的behavior部分,看看stabilizationWindowSeconds的值是不是合理,比如大促的时候,可以把扩容冷却改成10秒,缩容改成30秒,平时用默认的5分钟就行,这样既避免了频繁调整,又不会影响业务。

4.3 第三步:验证指标采集的实时性

用kubectl top pod看实时的CPU,和metrics-server的指标对比:

# 查看web-deploy的Pod实时CPU
kubectl -n default top pod -l app=web

如果实时的CPU是80%,但metrics-server显示的CPU只有60%,那肯定是采集间隔太长,或者metrics-server有问题,需要调整采集间隔。

五、该场景的技术优缺点和注意事项

5.1 技术优缺点分析

用HPA的冷却时间和指标采集机制,优点是很明显的:比如冷却机制避免了Pod的频繁重启,减少了服务中断的概率;指标采集定期更新,减少了系统的开销,不会占用太多资源。但缺点也很突出:冷却时间设置不合理会导致响应不及时,指标采集间隔太长会错过业务的突发波动,这些都是实际使用中要注意的问题。

5.2 实际应用的注意事项

咱们在实际项目中,要注意这几点:第一,根据业务场景调整冷却时间,比如直播、大促这样的突发业务,缩短扩容冷却时间,日常平稳业务用默认;第二,指标采集间隔要和HPA的同步匹配,别差距太大,比如HPA同步是1分钟,指标采集就设1分钟;第三,要给HPA设置告警,比如当HPA的Pod数达到最大值,或者长时间没触发扩缩容,要及时通知开发人员,避免服务出问题。

六、总结

总的来说,弹性伸缩不触发的问题,大部分都出在冷却时间和指标采集这两个地方,就像饭馆的服务员排班,你得算好客人的统计时间,还有调整的缓冲时间,这样才能应对客人的波动。排查的时候,先看HPA的事件,再核对参数,最后验证指标,步骤简单,调整也不难。只要把这两个根源问题解决,弹性伸缩就能正常工作,帮你省不少事。