华为云 CCE 弹性伸缩实战:HPA 与 Cluster Autoscaler 协同降本 40% 的落地路径
一、背景:为什么"固定节点池"会成为成本黑洞
大多数团队第一次把业务搬上华为云 CCE(云容器引擎)时,习惯按业务峰值申请节点:32 vCPU 的节点池常驻 20 台,白天勉强够用,夜里 CPU 利用率却跌到 8% 以下。容器化的弹性优势没有兑现,账单却按峰值付了一整年。
我们在一个典型的电商中台项目里做过统计:一个自然周内,订单服务 Pod 的 CPU 使用率在 5%~78% 之间剧烈波动,而节点池的分配率始终保持在 65% 以上。真正的问题不是"资源不够",而是资源无法在时间维度上流动。解决思路只有两条:让 Pod 数量随负载变化(HPA),让节点数量随 Pod 需求变化(Cluster Autoscaler)。两者必须协同,缺一不可。
二、第一层弹性:用 HPA 让 Pod 数量跟上业务节奏
HPA(Horizontal Pod Autoscaler)依据指标扩缩副本数。实践中最大的误区是"只看 CPU"。CPU 属于滞后指标,等它升高时,请求已经在排队了。更稳妥的做法是组合指标:CPU 利用率兜底,业务自定义指标(如每秒订单数、消息队列堆积量)作为前馈信号。
以下是一个订单服务的 HPA 配置示例,使用 autoscaling/v2:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: order-service-hpa
namespace: prod
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: order-service
minReplicas: 3
maxReplicas: 30
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 65
- type: Pods
pods:
metric:
name: orders_per_second
target:
type: AverageValue
averageValue: "50"
behavior:
scaleUp:
stabilizationWindowSeconds: 30
policies:
- type: Percent
value: 100
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Pods
value: 2
periodSeconds: 60
三个参数值得反复打磨:
| 参数 | 常见错误值 | 建议值 | 说明 |
|---|---|---|---|
| averageUtilization | 80% | 60%~70% | 预留缓冲,避免扩缩震荡 |
| scaleDown 稳定窗口 | 0 秒 | 300 秒 | 防止流量抖动导致反复缩容 |
| minReplicas | 1 | 3 | 保证多可用区打散与滚动升级余量 |
behavior 字段是 v2 版本的核心价值。缩容窗口设置过短,会出现"扩容—缩容—再扩容"的锯齿,反而拉高平均副本数;设置 300 秒后,我们观测到的副本数曲线平滑了约 70%。
三、第二层弹性:让 Cluster Autoscaler 承接节点缺口
HPA 把副本数扩到 30,如果节点没有可分配资源,新 Pod 就会长期 Pending。这时需要节点弹性:CCE 的节点池支持开启自动扩缩容,由 Cluster Autoscaler 根据 Pending Pod 的资源请求量决定是否新增节点。
落地时有四个关键约束:
- 节点池按规格分层。建议至少划分"通用型(4U8G)"和"计算型(8U16G)"两个池,并设置不同的扩缩上限。小规格节点扩容快、粒度细,适合 Web 类服务;大规格节点适合批处理。
- 必须配置 requests。Cluster Autoscaler 依据 requests 而非实际使用量计算缺口。没有 requests 的 Pod 会被判定为 0,导致节点永远不扩。
- 设置缩容阈值与冷却时间。节点利用率低于 50% 持续 10 分钟才触发缩容,避免刚缩完又扩。
- 为关键业务保留固定节点。数据库、注册中心等有状态服务应放在固定节点池,并打上污点,防止被弹性池的缩容逻辑波及。
一个可用的节点池伸缩配置片段如下:
apiVersion: node.k8s.io/v1
kind: NodePool
metadata:
name: web-spot-pool
spec:
autoscaling:
enable: true
minNodeCount: 3
maxNodeCount: 25
scaleDownUtilizationThreshold: 0.5
scaleDownUnneededTime: 10m
nodeTemplate:
flavor: c6.xlarge.2
labels:
workload: web
taints: []
四、协同调优:三个真实踩过的坑
坑一:扩容速度不匹配。 HPA 在 30 秒内把副本拉到 20,而新节点从创建到 Ready 需要 2~3 分钟。这段时间的流量全部压在旧节点上,接口超时率飙升。解决办法是保留 20% 的节点缓冲(即"暂停缩容水位"),并开启 CCE 的节点预热镜像,把启动时间从 180 秒压到 70 秒。
坑二:指标采集延迟。 自定义指标经由云原生监控插件汇聚,存在 15~30 秒延迟。我们把 HPA 的 scaleUp 稳定窗口设为 30 秒,同时在前端网关做限流兜底,避免指标还没上报就被打穿。
坑三:缩容误杀长连接。 WebSocket 服务的 Pod 被缩容时,连接直接断开。正确的做法是配置 preStop 钩子配合优雅退出:先从 Service 摘除,等待 30 秒让连接自然迁移,再发送 SIGTERM。
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 30"]
terminationGracePeriodSeconds: 60
五、效果与复盘
改造上线四周后的对比数据:
- 平均节点数从 20 台降至 11.6 台,峰谷差被弹性池吸收;
- 月度计算资源账单下降约 40%,其中 60% 来自夜间缩容,40% 来自规格优化;
- 接口 P99 延迟从 420ms 降至 310ms,因为扩容更及时,队列积压减少;
- 运维介入次数从每周 3~4 次降到每月 1 次,告警噪音显著下降。
复盘下来,弹性伸缩不是"打开开关"就结束的配置项,而是一套需要持续观测的反馈回路:指标要选对、缓冲要留够、冷却要给足、有状态服务要隔离。把这四件事做扎实,容器化带来的成本红利才会真正落到账单上。对于正准备做云上成本优化的团队,建议先用一周时间采集真实的 CPU/内存分布,再决定 HPA 阈值与节点池规格——数据驱动的参数,永远比拍脑袋的经验更可靠。
- 点赞
- 收藏
- 关注作者
评论(0)