news 2026/8/22 11:28:21

AI全栈知识14:GPU资源弹缩实战 - 从HPA到Cluster Autoscaler

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI全栈知识14:GPU资源弹缩实战 - 从HPA到Cluster Autoscaler

AI全栈知识14:GPU资源弹缩实战 - 从HPA到Cluster Autoscaler

写在前面

GPU贵。一张T4按量付费大概10-30元/小时(不同云厂商价格不同),A100更是几十上百。如果你的AI推理服务24小时跑着,但实际只有白天8小时有流量,那16个小时的钱就白花了。

怎么办?让GPU资源跟着流量走:忙的时候自动加机器,闲的时候自动减机器。这就是"弹缩"。

但GPU弹缩不是简单把CPU弹缩的配置复制过来就行。GPU节点启动慢、成本高、缩容有风险,需要特殊处理。

这篇帮你搞定GPU场景下的完整弹缩方案。


为什么GPU资源必须做弹缩

算笔账

场景:一个AI推理服务,用一张T4 GPU 不做弹缩(24小时运行): 10元/小时 × 24小时 × 30天 = 7200元/月 做弹缩(只在有流量时运行,白天10小时): 10元/小时 × 10小时 × 30天 = 3000元/月 节省:4200元/月(58%)

如果用竞价实例(打3-4折)+ 弹缩,成本还能再降:

竞价实例(3折)+ 弹缩(10小时): 3元/小时 × 10小时 × 30天 = 900元/月 相比全天按量付费节省:87%

不做弹缩 = 烧钱。GPU越贵,弹缩价值越大。


K8s弹缩体系:两层架构

在K8s中,弹缩分两层:

第一层:HPA(Pod水平自动伸缩)

作用:自动调整Pod副本数。流量大了加Pod,流量小了减Pod。

流量增加 → HPA检测到指标超阈值 → 自动增加Pod数量 流量减少 → HPA检测到指标低于阈值 → 自动减少Pod数量

生活类比:超市收银台。顾客多了多开几个窗口,顾客少了关掉几个窗口。

第二层:Cluster Autoscaler(节点自动伸缩)

作用:自动调整节点数量。Pod创建出来但没地方跑(Pending),就自动加节点。节点空了就自动删。

HPA想加Pod → 但集群没有空余GPU节点 → Pod处于Pending状态 Cluster Autoscaler检测到Pending Pod → 向云厂商申请新GPU节点 新节点Ready → Pod调度上去 → 服务恢复

生活类比:停车场。车位满了就扩建新的停车层。空了就关掉省电费。

两层协同工作

用户请求增加 ↓ HPA:推理队列变长了,需要从2个Pod扩到4个 ↓ 调度器:目前只有1张GPU卡,只能跑2个Pod,剩下2个Pod Pending ↓ Cluster Autoscaler:检测到Pending,申请新的GPU节点 ↓ 云厂商:分配一台T4实例,加入集群 ↓ 调度器:把Pending的Pod调度到新节点 ↓ 服务恢复正常 --- 用户请求减少 ↓ HPA:队列空了,从4个Pod缩到2个 ↓ 新节点上的Pod被删掉了,节点空闲 ↓ Cluster Autoscaler:检测到节点空闲超过10分钟,删除节点 ↓ 省钱了

HPA基础:怎么配置Pod自动伸缩

最简单的HPA(基于CPU)

apiVersion:autoscaling/v2kind:HorizontalPodAutoscalermetadata:name:my-app-hpaspec:scaleTargetRef:apiVersion:apps/v1kind:Deploymentname:my-appminReplicas:1maxReplicas:10metrics:-type:Resourceresource:name:cputarget:type:UtilizationaverageUtilization:70# CPU使用率超过70%就扩

意思是:

  • 最少1个Pod,最多10个
  • 当所有Pod的平均CPU使用率超过70%,就加Pod
  • 低于70%就减Pod

这对GPU推理服务够用吗?

不够。因为:

问题原因
GPU推理服务的CPU使用率通常很低瓶颈在GPU不在CPU
CPU没超70%但用户已经在排队了GPU满了,请求堆积
需要看的是GPU相关指标CPU利用率反映不了真实负载

GPU推理服务应该用什么指标做HPA

可选指标对比

指标来源优点缺点
GPU利用率DCGM Exporter直观波动大,不够灵敏
GPU显存使用率DCGM Exporter好理解模型加载后就是固定值,没意义
等待中的请求数vLLM暴露的指标最能反映真实排队情况需要推理框架支持
每秒处理请求数(QPS)自定义反映吞吐量不同请求长度不同,QPS不准
请求延迟P99自定义反映用户体验滞后指标(等慢了才扩,来不及)

最佳实践:用推理队列长度

vLLM暴露了一个关键指标:

vllm:num_requests_waiting # 正在等待处理的请求数

逻辑:队列里有人在等 = 当前Pod处理不过来 = 该加Pod了。

这是"领先指标"(leading indicator),能提前感知压力,比"延迟已经变高了"的滞后指标好。


实战:配置GPU推理服务的HPA

前置条件

要用自定义指标做HPA,需要安装:

1. Prometheus(采集指标) 2. Prometheus Adapter(把Prometheus指标转成K8s metrics API) 3. 推理服务暴露指标(vLLM自带/metrics端口)

架构:

vLLM Pod --暴露指标--> Prometheus --采集--> Prometheus Adapter --转换--> K8s Metrics API --供给--> HPA

第一步:确认vLLM暴露了指标

vLLM启动后默认在端口暴露Prometheus格式的指标:

# 验证指标是否存在curlhttp://vllm-service:8000/metrics|grepnum_requests_waiting

输出类似:

vllm:num_requests_waiting 3

第二步:配置Prometheus采集

# prometheus-scrape-config-job_name:'vllm'metrics_path:/metricsstatic_configs:-targets:['vllm-service:8000']

第三步:配置Prometheus Adapter

# prometheus-adapter-config.yamlapiVersion:v1kind:ConfigMapmetadata:name:prometheus-adapter-configdata:config.yaml:|rules: - seriesQuery: 'vllm:num_requests_waiting' resources: overrides: namespace: {resource: "namespace"} pod: {resource: "pod"} name: matches: "^(.*)$" as: "vllm_requests_waiting" metricsQuery: 'sum(vllm:num_requests_waiting{<<.LabelMatchers>>}) by (<<.GroupBy>>)'

第四步:配置HPA

apiVersion:autoscaling/v2kind:HorizontalPodAutoscalermetadata:name:vllm-hpaspec:scaleTargetRef:apiVersion:apps/v1kind:Deploymentname:vllm-inferenceminReplicas:1maxReplicas:5metrics:-type:Podspods:metric:name:vllm_requests_waitingtarget:type:AverageValueaverageValue:"5"# 每个Pod平均等待超过5个请求就扩behavior:scaleUp:stabilizationWindowSeconds:30# 扩容等30秒确认(避免抖动)policies:-type:Podsvalue:2# 每次最多加2个PodperiodSeconds:60scaleDown:stabilizationWindowSeconds:300# 缩容等5分钟确认(避免缩了又要扩)policies:-type:Podsvalue:1# 每次最多减1个PodperiodSeconds:120

关键配置解释:

配置为什么这样设
minReplicas1至少保持一个Pod(避免冷启动)
maxReplicas5控制最大成本
averageValue5每个Pod平均等5个请求就扩容
scaleUp stabilization30sGPU Pod启动慢,别频繁抖动
scaleDown stabilization300s缩容要谨慎,等5分钟确认真不需要了
scaleDown value1每次只缩1个,避免一下子缩太多

Cluster Autoscaler:自动加减GPU节点

为什么需要节点级别弹缩

HPA只能加Pod。但如果集群里没有空闲GPU节点了,Pod就会一直Pending:

情况: 当前集群:1台T4节点(已经跑了1个vLLM Pod占满GPU) HPA要加Pod → 新Pod需要GPU → 没有空余GPU → Pending 如果没有Cluster Autoscaler: 新Pod一直Pending → 用户一直等 → 直到运维手动加节点 有Cluster Autoscaler: 检测到Pending Pod → 自动申请新T4节点 → Pod调度上去 → 自动恢复

配置示例(AWS EKS)

# cluster-autoscaler配置(节点组)apiVersion:eksctl.io/v1alpha5kind:ClusterConfigmetadata:name:ai-clusterregion:us-east-1managedNodeGroups:# 固定的CPU节点组(不弹缩)-name:cpu-nodesinstanceType:t3.mediumdesiredCapacity:2minSize:2maxSize:2# 可弹缩的GPU节点组-name:gpu-nodesinstanceType:g4dn.xlarge# T4 GPUdesiredCapacity:1minSize:0# 可以缩到0(完全没流量时不花钱)maxSize:4# 最多4台labels:gpu:"true"taints:-key:nvidia.com/gpuvalue:"true"effect:NoSchedule# 只有需要GPU的Pod才调度到这里

关键点:

  • minSize: 0? 完全没流量时GPU节点缩到0台,一分钱不花
  • maxSize: 4? 设上限防止失控
  • taint ? 防止普通Pod跑到GPU节点上占资源

阿里云ACK配置

# 阿里云节点池配置节点池名称:gpu-autoscale-pool 实例类型:ecs.gn6i-c4g1.xlarge(T4) 付费模式:按量付费(或竞价实例) 最小节点数:0 最大节点数:4 扩容策略:当有Pod因GPU不足Pending时自动扩容 缩容策略:节点空闲10分钟后自动缩容

GPU弹缩的特殊问题

问题一:GPU节点启动慢

阶段CPU节点GPU节点
云厂商分配实例30-60秒30-60秒
节点加入集群30秒30秒
拉取镜像10秒(镜像小)2-5分钟(GPU镜像大,几个GB)
模型加载不需要1-3分钟(把模型加载到GPU显存)
总计1-2分钟4-10分钟

从扩容触发到Pod真正能服务,可能要5-10分钟!

解决方案:

方案做法适合
保留最小副本minReplicas=1,不缩到0有基础流量的服务
预热节点保留一台空闲GPU节点常驻对延迟敏感的服务
提前扩容用更敏感的指标,queue=2就扩高峰可预测的场景
定时扩容CronHPA,每天早9点提前扩流量有规律的服务

CronHPA示例(定时扩容)

apiVersion:autoscaling.alibabacloud.com/v1beta1kind:CronHorizontalPodAutoscalermetadata:name:vllm-cron-hpaspec:scaleTargetRef:apiVersion:apps/v1kind:Deploymentname:vllm-inferencejobs:-name:"morning-scale-up"schedule:"0 8 * * 1-5"# 工作日早8点targetSize:3# 提前扩到3个Pod-name:"evening-scale-down"schedule:"0 20 * * 1-5"# 工作日晚8点targetSize:1# 缩回1个Pod-name:"weekend-minimum"schedule:"0 0 * * 0,6"# 周末targetSize:1# 保持最小

问题二:缩容时正在推理怎么办

缩容时如果Pod正在处理请求,直接杀掉会导致请求失败。

解决方案:优雅终止(Graceful Shutdown)

# Deployment配置spec:template:spec:terminationGracePeriodSeconds:60# 给60秒处理完在手的请求containers:-name:vllmlifecycle:preStop:exec:command:-/bin/sh--c-"sleep 10 && kill -SIGTERM 1"# 先等10秒让新请求去别的Pod

同时配合PDB(Pod Disruption Budget):

apiVersion:policy/v1kind:PodDisruptionBudgetmetadata:name:vllm-pdbspec:minAvailable:1# 缩容时至少保留1个Pod在运行selector:matchLabels:app:vllm-inference

问题三:扩容抖动

流量刚超阈值就扩,刚降下来就缩,反复折腾。

解决方案:设置稳定窗口

behavior:scaleUp:stabilizationWindowSeconds:60# 超阈值持续60秒才扩scaleDown:stabilizationWindowSeconds:300# 低于阈值持续5分钟才缩

经验值:

  • 扩容窗口短一些(30-60秒),快速响应
  • 缩容窗口长一些(5-10分钟),避免刚缩了又要扩

竞价实例:GPU省钱利器

什么是竞价实例

云厂商把空闲的GPU实例打折卖(通常3-4折),但随时可能被回收(提前2分钟通知)。

对比按量付费竞价实例
价格原价3-4折
稳定性不会被回收可能被回收(2分钟通知)
适合基础负载(不能断)弹性负载(断了有兜底)

混合策略

基础负载:1台按量付费的GPU节点(稳定,不会被回收) 弹性负载:0-3台竞价实例的GPU节点(便宜,被回收了也没关系)

为什么竞价实例被回收也没关系?

因为有多个Pod + Cluster Autoscaler兜底:

  1. 竞价实例被回收 → 上面的Pod被驱逐
  2. Pod变成Pending → Cluster Autoscaler申请新的竞价实例
  3. 新实例到了 → Pod重新调度上去
  4. 期间其他Pod继续服务(有按量付费的兜底)

AWS配置示例

# 混合节点组managedNodeGroups:# 基础节点(按量,稳定)-name:gpu-ondemandinstanceType:g4dn.xlargedesiredCapacity:1minSize:1maxSize:1capacityType:ON_DEMAND# 弹性节点(竞价,便宜)-name:gpu-spotinstanceTypes:-g4dn.xlarge-g4dn.2xlarge# 多选几种,提高竞价成功率desiredCapacity:0minSize:0maxSize:3capacityType:SPOTlabels:capacity-type:spot

阿里云竞价实例配置

节点池:gpu-spot-pool 实例类型:ecs.gn6i-c4g1.xlarge(T4) 付费模式:抢占式实例(竞价) 保护期:1小时(创建后1小时内不会被回收) 最大价格:按量付费的40% 最小节点数:0 最大节点数:3

成本对比

方案A:全按量付费,2台GPU,24小时 10元 × 2台 × 24h × 30天 = 14400元/月 方案B:1台按量 + 弹缩竞价(白天10小时平均多1台) 按量:10元 × 1台 × 24h × 30天 = 7200元 竞价:3元 × 1台 × 10h × 30天 = 900元 总计:8100元/月 节省:6300元/月(44%)

完整架构图

用户请求 ↓ Ingress / Load Balancer ↓ vLLM Pod × N(N由HPA控制) ↓ ↑ GPU Node Pool Cluster Autoscaler (按量1台 + 竞价0-3台) (检测Pending Pod自动加节点) ↓ Prometheus(采集vLLM指标:queue_length、latency等) ↓ HPA(基于queue_length调整Pod数量)

监控和告警

弹缩做好了还要能看到运行状态:

监控指标说明告警条件
Pod副本数当前有几个Pod在跑达到maxReplicas(扛不住了)
Pending Pod数有几个Pod在等GPU节点持续Pending超过5分钟
节点数量变化今天扩了几次缩了几次频繁扩缩(抖动)
竞价实例回收事件有没有被云厂商回收短时间多次回收
每日GPU成本今天花了多少钱超预算80%
推理队列长度当前排队的请求数持续>10(扩容可能有问题)

Grafana面板建议

第一行:Pod数量趋势 + 节点数量趋势(看弹缩是否正常) 第二行:推理队列长度 + 请求延迟P99(看用户体验) 第三行:GPU利用率 + 显存使用率(看资源效率) 第四行:每小时成本 + 竞价实例回收次数(看钱)

面试怎么说

如果被问"GPU资源怎么做弹缩":

"GPU弹缩分两层:Pod级别用HPA,节点级别用Cluster Autoscaler。

HPA指标不能用CPU利用率(GPU推理服务CPU利用率很低),要用推理队列长度。vLLM暴露了num_requests_waiting指标,队列超过阈值就扩Pod。

Cluster Autoscaler负责在Pod因为没有GPU节点而Pending时,自动向云厂商申请新节点。我会设minSize=0让完全无流量时GPU节点缩到零。

GPU弹缩有几个特殊处理:一是启动慢(5-10分钟),所以用CronHPA提前扩容或保留预热节点。二是缩容要优雅(terminationGracePeriod+PDB),避免杀掉正在推理的Pod。三是用竞价实例省钱,基础负载按量付费,弹性部分用竞价(3-4折),被回收了Cluster Autoscaler会自动补充。

整套方案在我的集群上大约节省了40-50%的GPU成本。"


延伸思考

问题答案
没有K8s能做GPU弹缩吗可以用云厂商的弹性伸缩组(Auto Scaling Group),但没K8s灵活
竞价实例真的会被回收吗高峰期会。T4相对稳定,A100竞价更容易被回收
缩到0台后第一个请求怎么办会等5-10分钟。如果不能接受,minSize设为1保留一台
多个模型共享GPU怎么弹缩用NVIDIA MIG或时间片共享,HPA按每个模型独立配置
弹缩和成本哪个优先先保证用户体验(不排队),再优化成本。宁可多花点钱也别让用户等太久

小结

本篇核心收获:

  1. GPU必须弹缩:不做弹缩 = 烧钱。弹缩+竞价可省40-80%成本
  2. 两层弹缩:HPA管Pod数量,Cluster Autoscaler管节点数量
  3. GPU的HPA指标:不用CPU利用率,用推理队列长度(vllm:num_requests_waiting)
  4. GPU启动慢:5-10分钟,用CronHPA提前扩或保留预热节点应对
  5. 缩容要优雅:terminationGracePeriod + PDB,避免杀掉正在推理的请求
  6. 竞价实例省钱:基础按量+弹性竞价的混合策略,被回收有兜底

下一篇预告

AI全栈知识15:AI应用的可观测性 - Token监控与成本控制

下一篇进入可观测性领域:

  • Token使用量统计和分析
  • AI调用链追踪
  • 成本归因(哪个团队/功能花了多少Token)
  • 异常检测(突然Token暴涨怎么发现)

参考链接

  • K8s HPA官方文档
  • Cluster Autoscaler
  • Prometheus Adapter
  • AWS EKS Spot实例最佳实践
  • vLLM Metrics文档
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/22 11:27:33

从追工具到解问题:AI编程时代开发者的务实工作流构建

1. 从“追工具”到“解问题”&#xff1a;一个老码农的视角转变最近和几个朋友聊天&#xff0c;话题总绕不开“最近又出了个新的AI编程工具&#xff0c;你试了吗&#xff1f;” 从Copilot到Cursor&#xff0c;从Claude到DeepSeek&#xff0c;再到各种层出不穷的本地模型和代码生…

作者头像 李华
网站建设 2026/8/22 11:24:39

【火力盒子】Excel 与 各编程语言中的日期计算公式

如果你需要在表格或代码中批量处理日期差&#xff0c;可以参考以下常用公式和代码片段&#xff1a;1. Excel / WPS 表格公式需求公式 / 函数计算相差总天数DATEDIF(A1, B1, "D") 或直接 B1-A1计算相差月数DATEDIF(A1, B1, "M")计算工作日(排除周末)NETWORK…

作者头像 李华
网站建设 2026/8/22 11:23:57

OpenAI暂停强化学习训练事件解析:AI研发中的安全挑战与工程实践

这次我们来看一个技术圈的热点事件&#xff1a;OpenAI 暂停前沿模型强化学习训练两周。这不是一个可以直接部署的代码项目&#xff0c;而是一个关于顶级AI实验室研发动态的重要信号。对于开发者、研究者和关注AI安全与治理的人来说&#xff0c;理解这一事件背后的技术逻辑、潜在…

作者头像 李华
网站建设 2026/8/22 11:23:46

展厅中的错字之过谁来背?一字谬误,品牌千里失分!

展厅&#xff0c;是企业与城市的公共门面&#xff0c;是沉淀品牌实力、传递产业价值、输出文化内核的权威场域。大到品牌沿革、技术成果、荣誉资质&#xff0c;小到标识注解、标语释义、双语标注&#xff0c;展馆内的每一处文字&#xff0c;都是对外展示的“官方标准答案”。但…

作者头像 李华
网站建设 2026/8/22 11:22:12

分解式假设搜索:解决语义鸿沟的NLP检索新范式

大家好&#xff0c;我是专注于技术实战与经验分享的博主。在信息检索和自然语言处理领域&#xff0c;我们常常面临一个经典难题&#xff1a;用户提出的查询&#xff08;Query&#xff09;与文档库&#xff08;Document&#xff09;中的标准分类体系&#xff08;Taxonomy&#x…

作者头像 李华
网站建设 2026/8/22 11:20:58

AI文章的“出身“决定论:为何能上热榜65名

导语 同样是AI写文章&#xff0c;为什么有的文章是"正确的废话"&#xff0c;有的却能杀进全站热榜&#xff1f; 我发了一篇《三星Q2利润创纪录&#xff1a;HBM4如何重塑存储利润分配》&#xff0c;进了CSDN热榜第65名。它确实是AI写的——但写它的那个AI&#xff0c;…

作者头像 李华