华为云CCE弹性伸缩实践:让HPA、VPA与集群自动扩缩容协同工作

举报
yd_220626730 发表于 2026/11/14 09:28:45 2026/11/14
【摘要】 导读把应用搬上华为云容器引擎 CCE 之后,很多团队会遇到同一个矛盾:流量高峰时 Pod 不够用,请求排队、接口超时;流量低谷时节点空转,账单却一点不少。手工改副本数永远慢半拍,等人发现问题再扩容,高峰往往已经过去一半。弹性伸缩要解决的正是这个问题:让副本数和节点数跟随真实负载自动变化,高峰顶得住,低谷省得下。本文不讲空洞的概念,而是把 CCE 上最常用的三层伸缩机制讲清楚——Pod 水平...

导读

把应用搬上华为云容器引擎 CCE 之后,很多团队会遇到同一个矛盾:流量高峰时 Pod 不够用,请求排队、接口超时;流量低谷时节点空转,账单却一点不少。手工改副本数永远慢半拍,等人发现问题再扩容,高峰往往已经过去一半。

弹性伸缩要解决的正是这个问题:让副本数和节点数跟随真实负载自动变化,高峰顶得住,低谷省得下。本文不讲空洞的概念,而是把 CCE 上最常用的三层伸缩机制讲清楚——Pod 水平伸缩 HPA、Pod 垂直伸缩 VPA,以及集群节点自动扩缩容,再把它们拼成一套可以落地的协同方案。读完之后,你可以直接对照文中的配置清单,检查自己集群的伸缩策略有没有缺口。

需要先说明一个前提:伸缩不是万能药。它放大的是本来就健康的应用——无状态、可快速启动、资源用量可度量;如果应用启动要两分钟、一个请求占住线程不释放、或者根本没有设置合理的资源请求值,再好的伸缩策略也救不了它。先把应用做对,再谈自动伸缩。

一、为什么弹性伸缩不是“加机器”那么简单

不少人第一次接触弹性伸缩时,直觉是“流量大了就加节点”。这个直觉只对了一半。容器环境里的伸缩至少发生在三个不同的层次上,层次不同,触发条件、生效速度和副作用完全不同。

第一层是 Pod 副本数。流量涨了,先加 Pod,这是最快、最便宜的响应方式,秒级到分钟级就能见效。第二层是单个 Pod 的资源规格。有些应用不是副本不够,而是单个 Pod 的 CPU 或内存给少了,跑满之后频繁被限流,这时应该调整的是资源配额,而不是一味加副本。第三层才是节点数。当 Pod 加到节点装不下时,才需要扩节点;节点扩容涉及云服务器的创建和加入集群,耗时最长,成本也最高。

把三层混为一谈,就会出现典型问题:只配了 HPA,节点池却没有开自动扩缩容,高峰时 Pod 处于 Pending 状态迟迟调度不上去;或者只扩了节点,Pod 的资源请求值设得过大,一个节点只能装两三个 Pod,扩了节点也装不下多少副本。伸缩要按层次设计,每一层解决自己那一层的问题。

另外,伸缩的目标也不只是“顶住高峰”。一个好的伸缩策略要同时满足三件事:高峰时不丢请求,低谷时不浪费资源,波动时不来回震荡。第三点最容易被忽视:扩容太激进、缩容太急躁,会让副本数像钟摆一样来回跳动,反而增加调度和启动开销,甚至把依赖的数据库和下游服务打垮。

二、三层伸缩模型:先分清谁负责什么

可以用一张表把三层机制的职责分清楚:

层次 机制 调整对象 典型触发条件 生效速度
Pod 水平伸缩 HPA Deployment 等工作负载的副本数 CPU、内存利用率或自定义指标超过阈值 快,一般在分钟级
Pod 垂直伸缩 VPA 单个 Pod 的 CPU、内存请求值与上限 容器长期资源不足或长期闲置 中,需要重建 Pod
节点伸缩 集群自动扩缩容 节点池中的节点数量 有 Pod 长时间处于 Pending,或节点长期空闲 慢,一般在分钟级

这三层的关系是自上而下的。HPA 决定“需要多少个 Pod”,调度器决定“这些 Pod 能不能放得下”,节点自动扩缩容决定“放不下时要不要加节点”。反过来,缩容时也一样:HPA 先把副本数降下来,节点上出现大片空闲后,自动扩缩容组件再判断是否可以缩掉整台节点。

理解这个链条之后,很多故障现象就有了头绪。比如 HPA 已经把副本数从 3 扩到 20,但接口延迟没有改善,可能是节点资源不足,新 Pod 还在 Pending;也可能是应用本身有瓶颈,比如数据库连接池只有 20 个连接,再多 Pod 也没有用。伸缩策略的排查,永远要沿着“副本—调度—节点—依赖”这条链自上而下看。

三、HPA 实战:先把资源请求值写对

HPA 的计算逻辑并不复杂:它按设定的目标值,用当前指标除以目标指标,再乘以当前副本数,得到期望副本数。公式简单,但前提是分母要真实——CPU 利用率的分母是 Pod 的 CPU 请求值(requests),而不是上限(limits),也不是节点总容量。如果 requests 写得离谱,HPA 的判断就会跟着离谱。

举一个常见的错误:开发为了“保险”,把 CPU requests 写成 2 核,实际上应用平时只用 0.2 核。HPA 看到的利用率永远只有 10%,即使流量翻了三倍也触发不了扩容。反过来,把 requests 写得过小,比如 0.05 核,应用一跑就超过 100%,HPA 会不停扩容,直到撞上最大副本数。

所以配 HPA 之前,先做资源画像:在日常流量和峰值流量下分别观察应用的实际 CPU、内存用量,取一个能覆盖大多数情况的值作为 requests,再给 limits 留出合理余量。一般建议:requests 按 P80 左右的日常用量来定,limits 按峰值用量的 1.5 倍左右来定,不要把 limits 设成 requests 的十倍,那样会让调度器误判节点剩余容量。

下面是一个比较完整的 HPA 配置示例,使用的是 Kubernetes 的 autoscaling/v2 版本:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: order-api-hpa
  namespace: prod
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: order-api
  minReplicas: 3
  maxReplicas: 30
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 65
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 75
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
        - type: Percent
          value: 100
          periodSeconds: 60
        - type: Pods
          value: 4
          periodSeconds: 60
      selectPolicy: Max
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
        - type: Percent
          value: 20
          periodSeconds: 60
      selectPolicy: Min

这个配置里有几个要点值得逐一说明。第一,minReplicas 设为 3 而不是 1,是为了保证高可用:即使某个节点出故障,服务仍然有副本在其他节点上运行;同时 3 个副本也能分担突发流量的第一波冲击。第二,CPU 目标定在 65% 而不是 90%,是给扩容留出反应时间——从指标超标到新 Pod 就绪需要时间,目标定得太高,等新 Pod 上线时旧 Pod 可能已经被压垮了。

第三,behavior 字段是防止震荡的关键。scaleUp 的稳定窗口只有 60 秒,扩容要快;scaleDown 的稳定窗口是 300 秒,缩容要慢。缩容策略每次只缩 20%,避免流量刚回落一点就把副本砍掉一半,下一波流量一来又要重新扩容。扩容和缩容不对称,是伸缩策略里最基本的一条经验:扩容宁可激进,缩容务必谨慎。

第四,同时用 CPU 和内存两个指标时,HPA 会取两者算出的副本数中的较大值。这符合直觉:只要有一个资源吃紧,就应该扩容。但要注意,内存利用率作为伸缩指标要慎用——很多语言的运行时(比如 Java、Go)会主动占用内存,内存曲线并不总能反映真实负载,误触发的概率比 CPU 高。内存更适合做告警和容量规划,CPU 更适合做日常伸缩的主指标。

四、只看 CPU 是不够的:自定义指标怎么选

CPU 够用,并不等于服务够用。很多业务的瓶颈不在 CPU,而在队列长度、请求并发数或者外部依赖的响应时间。这时就需要自定义指标:把真正反映业务压力的数字接进 HPA。

常见的自定义指标有三类。第一类是应用层指标,比如每秒请求数、进行中的请求数、消息队列的待消费消息数。对网关、订单接口这类服务,进行中的请求数往往比 CPU 更灵敏:CPU 还没涨上去,请求已经开始排队了。第二类是中间件指标,比如数据库连接池的使用率、线程池的排队任务数。第三类是业务指标,比如待处理的订单数——这类指标需要业务系统自己暴露,一般通过 Prometheus 的自定义指标接口采集。

在 CCE 场景下,自定义指标的链路一般是:应用通过 Prometheus 格式暴露指标,集群内的 Prometheus 采集后,由指标适配器提供给 HPA 使用;也可以通过华为云应用运维管理服务 AOM 的指标能力来查看和告警。无论走哪条链路,都要先确认一个问题:指标的采集延迟是多少。如果指标每两分钟才更新一次,HPA 的反应就会慢两分钟,突发流量面前这个延迟可能是致命的。

还有一个经常被忽略的细节:自定义指标的单位和量纲要和 HPA 的目标值对齐。比如用“每个 Pod 的平均进行中请求数”做目标,就要确认指标是按 Pod 平均的,还是总量;总量指标除以副本数才是每个 Pod 的负担,写错了会导致 HPA 算出的副本数差一个数量级。上线前先在测试环境压测一轮,对照指标曲线和副本数曲线,确认两者是同步变化的,再推到生产。

五、VPA:给单个 Pod“调个子”,但要小心用

如果说 HPA 是“多招几个人”,VPA 就是“让每个人更能干”:它根据容器历史的实际用量,推荐或直接调整 Pod 的 CPU、内存请求值与上限。适合两类场景:一是长期资源配额明显不合理的老应用,比如 requests 长期只有实际用量的三分之一;二是工作负载比较固定、副本数变化不大的有状态类辅助服务。

VPA 有几种工作模式,需要根据场景选择。只推荐、不改动的模式最安全,适合先跑一两周观察推荐值,确认合理再人工调整;初始值模式只在 Pod 创建时应用推荐值,不影响运行中的 Pod;自动模式会在推荐值变化较大时重建 Pod,效果最彻底,但对在线业务有风险——重建意味着 Pod 要重启,如果应用没有做好优雅下线和就绪检查,重启期间会出现短暂的请求失败。

使用 VPA 时要守住两条红线。第一,不要对同一个工作负载同时开 HPA 和 VPA 的自动模式:HPA 按 CPU 利用率算副本数,VPA 又在改 CPU 请求值,利用率的分母一直在变,两者会互相干扰,导致副本数和资源配额一起震荡。如果一定要同时用,让 VPA 只处于推荐模式,人工采纳推荐值。第二,核心业务不要用自动模式,至少在初期不要用;先用推荐模式跑一段时间,把推荐值和实际用量曲线对照看,确认推荐逻辑符合业务特点再考虑自动。

六、节点自动扩缩容:节点池才是成本的关键

Pod 层面的伸缩做得再好,节点层跟不上也是白搭。CCE 的节点自动扩缩容一般按节点池来配置:当有 Pod 因为资源不足长时间处于 Pending,组件会向节点池申请扩容;当某个节点上的 Pod 可以被安全地调度到其他节点、且节点利用率长期低于阈值时,组件会排空该节点并缩容。

节点池设计有几个实操要点。第一,按用途分池:把核心业务、批处理任务、测试环境分到不同的节点池,分别设置最小、最大节点数和自动扩缩容开关。批处理任务波峰波谷明显,适合开自动扩缩容;核心业务的节点池要留出最小节点数作为底线,避免缩容后遇到突发流量还要等节点创建。第二,节点的规格要和 Pod 的资源请求值匹配:如果 Pod 的 requests 普遍是 1 核 2G,节点选 8 核 16G 比较合理,装箱率较高;节点过大,调度碎片多;节点过小,系统组件本身占用的资源比例就偏高。

第三,缩容不是无条件的。带本地存储的 Pod、有 PodDisruptionBudget 限制的工作负载、以及设置了防驱逐注解的 Pod,都会阻止节点被排空。缩容前要检查这些约束,否则会出现“节点明明很空却缩不掉”的情况。另外,节点缩容要配合优雅终止:给 Pod 设置合理的 terminationGracePeriodSeconds,并在应用里处理 SIGTERM 信号,先停止接收新请求、处理完进行中的请求再退出,否则缩容会直接造成请求失败。

节点扩容的速度也值得单独规划。从触发扩容到新节点 Ready,一般需要几分钟,这段时间里 Pending 的 Pod 只能等待。对有明确可预期高峰的业务(比如每天固定时段的流量高峰、营销活动),不要完全依赖自动扩容,可以提前用定时任务或手动方式把节点池扩到预期规模,活动结束后再缩回来。自动扩缩容擅长应对不可预期的波动,定时扩缩容擅长应对可预期的高峰,两者结合效果最好。

七、成本治理:伸缩的另一面是省钱

很多团队只把伸缩当成稳定性手段,其实它也是成本手段。节点空转是最常见的浪费:夜间流量只有白天的十分之一,如果节点数一点不降,相当于整夜都在为不存在的流量付费。把 HPA 的缩容策略配好、把节点池的自动缩容打开,夜间成本通常能下降三到五成,效果立竿见。

成本治理还可以从三个方向再深入。第一是装箱率:通过合理设置 requests,让每个节点的 CPU、内存利用率保持在一个健康区间。利用率过低说明 requests 设小了、节点买多了;利用率长期超过 85% 则要小心,突发流量来时没有缓冲。可以定期看节点利用率分布,把长期低于 30% 的节点池作为优化重点。

第二是节点计费方式的搭配:长期稳定运行的底座负载适合包年包月,波动部分的负载适合按需计费,节点池可以按计费方式分开配置。第三是清理长期闲置的资源:测试环境下班后缩到最小规模、删除长期 Pending 或 CrashLoopBackOff 的异常 Pod、回收不再使用的负载均衡器和弹性公网 IP,这些都是不需要改代码就能省下的成本。

需要提醒的是,省钱不能以牺牲可用性为代价。minReplicas 和节点池最小节点数是底线,缩容策略再激进也不能突破底线;核心业务的 HPA 目标值不要定得过高,留出扩容的反应时间。成本优化的目标是“去掉确定的浪费”,而不是“赌流量不会涨”。

八、常见故障排查:按这条链自上而下查

现象 先查什么 常见原因
HPA 不扩容 HPA 状态与指标值 requests 设得过大,或指标采集异常
HPA 反复扩缩容 behavior 配置与指标曲线 缩容窗口太短,或指标本身波动大
Pod 长时间 Pending 节点资源与节点池状态 节点池未开自动扩缩容,或节点池已到上限
节点缩不掉 节点上 Pod 的驱逐约束 有本地存储 Pod 或 PDB 限制
扩容后延迟没改善 下游依赖与应用瓶颈 数据库连接池、线程池或外部接口先到了瓶颈
新 Pod 启动后就失败 就绪探针与启动时间 探针阈值太严,或应用启动慢于探针超时

排查时建议使用 kubectl describe hpa、kubectl describe pod、kubectl get events 等命令,先看事件和状态,再看配置。CCE 控制台的事件中心和 AOM 的监控告警也可以作为辅助手段。养成一个习惯:每次调整伸缩参数后,记录调整前后的副本数曲线和节点数曲线,确认调整真的生效了,而不是只改了配置没有验证。

九、落地检查清单

  1. 每个工作负载都设置了合理的 requests 和 limits,requests 有资源画像依据。
  2. 核心服务 minReplicas 不小于 3,maxReplicas 有明确上限,避免无限扩容打垮下游。
  3. HPA 目标值留有余量,扩容快、缩容慢,behavior 参数已配置。
  4. 就绪探针、存活探针、优雅终止都已配置,新 Pod 能快速、平稳地接管流量。
  5. 节点池已按用途分池,自动扩缩容开关、最小与最大节点数已设置。
  6. PodDisruptionBudget 已配置,关键服务在节点维护和缩容时仍有足够副本。
  7. 监控与告警已覆盖副本数、节点数、Pending Pod 数和关键业务指标。
  8. 压测验证过一次完整的高峰:从触发扩容到新 Pod 就绪,全程耗时符合预期。

结语

弹性伸缩的本质,是把“人盯着曲线改副本数”这件事,变成一套可度量、可验证、可回滚的自动化规则。HPA 管副本,VPA 管规格,节点自动扩缩容管容量,三层各司其职,再用监控和压测把规则验证一遍,一套能顶住高峰、又能在低谷省钱的伸缩体系就基本成型了。

最后再强调一次顺序:先把应用做成无状态、可快速启动、资源可度量,再配 HPA;先把节点池分好、把驱逐约束理清,再开节点自动扩缩容。顺序对了,伸缩就是帮手;顺序错了,伸缩只会把原有的问题放大。希望这篇文章里的配置示例和检查清单,能帮你少走一些弯路。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。