GPU利用率不到30%?华为云国际站:Kubernetes多租户算力调度与碎片治理实战
GPU利用率不到30%?Kubernetes多租户算力调度与碎片治理实战
走访过不少AI创业团队后会发现一个尴尬的数据:花真金白银买的A100、H100集群,在Kubernetes里跑了几个月,GPU平均利用率长期卡在20%-40%。硬件成本没打折扣,算力产出却打了对折。一套真正落地的Kubernetes GPU利用率优化策略,从来不是改几个调度参数那么简单,它得从多租户争抢、调度器“盲区”和碎片黑洞这三条线索开始梳理。

为什么你的Kubernetes集群GPU利用率只有30%
GPU利用率低不是某一项配置出错,而是几股力量叠加的结果——默认调度器的粗粒度分配、任务形状不一致、以及长期被忽略的碎片累积。云原生社区里不少公开案例(如阿里云、字节跳动的技术博客)都指向同一个结论:不引入GPU共享与碎片整理机制,单靠Kubernetes原生调度,利用率天花板就是40%左右,很难再往上走。
什么是“整卡独占”带来的隐性浪费
Kubernetes Device Plugin默认以整卡为单位分配GPU,一个Pod哪怕只用300MB显存跑一个轻量推理服务,也会在调度层面标记占用整张卡。于是常见一幕是:节点上有8张A100,7张被推理服务“空转”占着,第8张被一个大模型训练任务吃满——整体算力利用率看着还行,但实际大量SM单元处于闲置。这里容易掉进一个误区:显存利用率高不等于计算核心在干活。很多推理场景显存拉得很高,但GPU SM利用率不到10%。如果不把监控维度从“显存”切换到“SM活跃时间占比”,团队还会误以为资源规划很健康。
多租户资源竞争如何把“饿死”小任务变成常态
多租户场景下,大模型训练往往需求整卡甚至多机多卡,且对性能抖动极度敏感;推理、数据处理类任务则零散、频繁启停。原生的FIFO调度逻辑下,一旦训练Pod抢不到足够整卡就会Pending,而此时集群里可能散落着五六张卡被小Pod零星占用。调度器不感知算力余量,也不具备抢占与回填能力,造成一种“明明有空卡,大任务却排不上”的假性资源不足。如果再看等待队列,轻量推理Pod又因为资源配额被训练任务逼成饥饿状态——两头都在争,两头都没跑满,这就是很多集群利用率上不去的真实状况。

碎片化如何一点点蚕食GPU算力
碎片不止指显存碎片,更致命的是拓扑层面的分配不均。举例来说,某节点两张GPU上各跑了一个占50%算力的推理任务,剩余两张完全空闲,此时来了一个需要整卡的高优任务,会卡在节点亲和性上无法调度。这种“4张卡有半卡闲却被当成无卡可调”的场景,在采用Spread策略的集群里高频出现。碎片还会随时间累积:Pod删除后GPU资源状态更新有延迟,新的Pod可能被挤到别的节点,导致碎片像雪球一样越滚越大。阿里的公开实践里提到,未做碎片整理时,集群中常有超过20%的GPU资源“看得见用不着”,直到引入Koordinator的Descheduler做周期性重调度,才把这些空洞填平。
Kubernetes GPU调度核心机制与瓶颈分析
当集群中GPU平均利用率长期徘徊在20%~40%,首先该审视的是调度层本身的设计缺陷。不少团队把原因归结为业务模型不合理,却忽略了Kubernetes原生调度器在GPU管理上存在三个根本性短板——它们往往比硬件成本更直接地吃掉算力回报。
默认调度器的GPU分配缺陷
原生调度器采用整数卡分配模型,一个Pod哪怕只占用10%的算力,也会独占整张GPU。这导致大量推理任务显存飘高但计算核心空转,更严重的是,大模型训练需要多卡时,无法灵活聚合被小任务零散占用的卡资源,集群出现“有卡却无法调度”的假性资源耗尽。很多团队监控面板上,GPU核利用率曲线长期在30%以下波动,显存占用率却超过80%,正是粗粒度分配造成的典型错位。
设备插件与资源上报机制
NVIDIA device plugin仅上报GPU数量、型号、显存总量等静态信息,并不反映实时算力利用率或显存动态。这种“只看户口不看健康状态”的上报方式,让调度器一直拿着过时的资源清单做决策。即便一张卡已被高显存、低算力的任务占满,plugin仍然汇报为“已分配”,调度器便不再向其派发新Pod,导致节点层面一半卡累死、一半卡闲死,负载极度不均衡。
节点级拓扑与跨NUMA问题
GPU卡与CPU、内存之间的物理拓扑(PCIe Switch、NVLink、NUMA节点)直接影响数据传输延迟和带宽。在多卡训练场景中,如果Pod被调度到跨NUMA或非本地PCIe Switch连接的GPU上,将造成明显性能抖动。然而,默认拓扑管理器只能约束CPU与内存的亲和性,对GPU拓扑感知基本空白,导致多卡分配常常无法保证最优互联,训练吞吐量可能下降10%~30%。对追求极致性能的AI团队来说,这是极易被忽视的隐形成本。

多租户场景下如何配置GPU共享与隔离
多租户GPU调度的核心矛盾不在技术实现,而在团队对“共享”的理解偏差。很多团队一上来就问“能不能一张卡跑多个训练任务”,但问题本身就有毛病——训练任务对显存带宽和计算核心的争抢远比推理任务敏感,硬塞进同一张卡只会互相拖慢,最后谁的模型都出不来。真正有效的多租户调度,是先给任务分好类:那些可以共享的(批处理推理、调试型Notebook),和不该共享的(长周期训练、在线服务SLA敏感的负载),然后才谈得上用什么机制去切分。
基于时间片的GPU共享方案
时间片方案的本质是“轮流上桌吃饭”,调度器按固定间隔把GPU计算核心的使用权切给不同容器。这套机制通过NVIDIA MPS或开源方案如HAMi实现,能在毫秒级完成上下文切换,小型推理任务的并发密度可以拉得很高。但要注意一个容易翻车的点:时间片切换只切计算时间,不切显存。如果某个容器申请了整张卡80%的显存做推理缓存,即使它当前不在计算核心上跑,其他容器也要等它把显存放掉才能上车。所以时间片方案搭配显存配额才是完整解法——Volcano社区的做法是把“显存配额+算力占比”绑定成调度参数,Pod申请时就得说清楚自己吃多少显存、占多少时间片,调度器再根据这两个维度做准入判断。
MIG与vGPU的多租户隔离
MIG(多实例GPU)是NVIDIA在A100/H100上做的一个物理级切分能力,直接把一张卡拆成最多7个独立的GPU实例,每个实例有自己专属的显存、缓存和计算单元,互不干扰。这跟vGPU那种驱动层软隔离有本质区别——vGPU的隔离靠的是NVIDIA驱动做流量控制,训练任务对PCIe带宽的争抢有时会把隔离效果打穿;而MIG的物理隔离相当于把一张卡变成几张独立的小卡,多租户之间连故障域都是分开的。但MIG的代价是切分后单实例性能上限被锁死,大模型的分布式训练反而不如直接用整卡。这就回到前面的判断:不是什么任务都适合切。推理、微调、轻量开发环境用MIG隔离效果好得让人意外;而几百GB参数的大模型训练,最好的多租户策略是给它独占两张整卡,别去跟共享任务抢那点碎片算力。如果硬件不支持MIG,退而求其次选vGPU,但要在调度器里补一套拓扑感知逻辑,把任务调度到PCIe Switch同侧的GPU上,避免跨NUMA节点的带宽损耗。这套选型过程如果拿不准,找像云老大这类多云服务商做个GPU算力评估能省不少弯路——不同厂商对MIG支持的规格、驱动版本、Kubernetes适配程度都不太一样,自己一个个踩坑成本太高。

碎片治理:GPU算力资源碎片的识别与回收
如果说调度策略解决的是“如何分蛋糕”的问题,那碎片治理要解决的就是“蛋糕渣粘在盘子上刮不下来”的问题。一个残酷的现实是:即使部署了GPU共享调度器,集群里仍然可能出现“GPU在逻辑上被占满,但实际算力使用率不到15%”的荒诞场景。这是因为碎片不是一次性的故障,而是调度系统的慢性病——任务大小随机、生命周期不一、释放时机不固定,三次随机因素的叠加效应下,任何静态策略都会逐渐失效。我们见过最典型的案例,一个70卡规模的A100推理集群,上线三个月后碎片率从5%攀升到23%,相当于16张卡看似已被分配,却无法被任何一个新任务使用。
碎片产生的三大原因
第一个原因最直观:任务粒度与GPU物理单元的错配。一个推理任务可能只需要2GB显存和5%算力,但Kubernetes默认调度器眼里最小粒度就是1张整卡,小任务撒上去后整张卡就算“已用”,剩余的显存和算力处于“有主却闲置”的状态。第二个原因是释放滞后性,Pod删除后device plugin未必立刻更新可分配资源量,调度器在下一个同步周期才会感知到变化,这个时间窗口足够让一个新的大任务误判资源不足而排队等待。第三个原因经常被忽视:节点间负载不均导致的结构性碎片。如果一个集群同时运行训练和推理两类负载,Binpack策略把推理全挤在某几张卡上,训练任务独占另外几张卡,中间那几张半满不满的卡就成了无人能用的缝隙。
定期重调度与碎片整理工具
解决碎片问题不能只靠首次调度的优化,必须引入一套“定期打扫房间”的机制。Koordinator开源项目的descheduler组件提供了一个叫defrag的插件,它的逻辑很直白:每隔一段时间扫描各节点的GPU分配状态,找到那些利用率长期徘徊在30%以下、但上面挂了好几个小Pod的GPU,然后在低峰窗口期把这些Pod迁移、聚合、腾出完整GPU。听起来简单,但实际执行时踩坑率极高。迁移过程中如何保证推理服务不中断?Pod驱逐后调度器会不会又把它重新撒回碎片位置?这些问题都要求defrag算法与调度策略联动,而非独立运行。一个行业里的务实做法是:先用Grafana把集群级的碎片率(已分配但不可被大任务利用的GPU算力总量)可视化出来,设定阈值触发defrag,再通过优先级的差异化保证核心业务不受干扰。
不过坦白讲,自建一套完整的碎片监控与自动整理体系,对中小团队来说工程成本确实不低。从部署device plugin到调试descheduler参数,再到搭建Grafana看板和告警规则,保守估计也需要一个资深SRE投入两到三周。如果团队内部没有专职做GPU运维的人,可以考虑借助外部服务商完成这层“脏活”——比如云老大这类多云服务商在做GPU集群托管时,通常会标配这些碎片监控告警和定期整理策略,团队只需要关注任务本身有没有按时跑完。
实战案例:从30%到80%的GPU利用率优化
GPU闲置并不是一个“买多了”的问题,而是调度逻辑与业务负载错配的结构性问题。我们观察到的典型案例来自一家自动驾驶公司,训练集群长期在20卡规模下跑感知模型,Kubernetes默认调度器按整卡分配,一个训练任务即使只用8GB显存也会独占一张A100,导致大量碎片。推理任务插进来时,调度器没有显存感知能力,只能随机找空卡,训练与推理混部后性能抖动到不可用。这类困境不是个例——很多AI团队建集群时忽略了调度器的选型,直到利用率卡在30%以下才意识到瓶颈不在硬件,在分配机制。
某自动驾驶训练集群的改造
这个团队面对的核心矛盾是:训练任务要整卡算力,推理任务只需要2-3GB显存,但默认调度器把它们一视同仁。改造方案分两步走:先部署Volcano集成GPU Share Daemon,实现按显存比例分配(如推理Pod申请15%算力、500MB显存),一张卡能同时跑6-8个推理实例;再启用Binpack策略,优先将小任务塞满同一张GPU,释放剩余整卡给训练任务。投入运行后,之前因为“没整卡”排队3小时的训练任务,调度等待降到15分钟以内。
混合负载场景下的调度策略
训练和推理混部最大的坑,是时间片共享造成训练延迟放大。这个案例的策略值得借鉴:训练任务走MIG物理隔离,每张A100切为3个独立实例,各占18GB显存,互不干扰;推理任务走软件层显存配额加NVIDIA MPS的时间片复用,利用推理任务80%时间在等待I/O的特点,让多个推理Pod轮转占用计算核心。同时为紧急的在线推理设置高优先级,启用抢占机制——低峰训练的Pod被临时驱逐,释放资源给线上服务,待低负载后再通过调度器自动回填。这种分层隔离加动态抢占的架构,本质上是在性价比和性能SLA之间找平衡点。
性能收益与成本对比数据
改造后的效果用几个数字就能说明问题:集群GPU平均利用率从32%提升到78%,最高峰时段能冲到85%;推理任务P99延迟没有恶化,训练任务的迭代速度反而因为调度等待减少而加快约40%。从成本端看,原先支撑同等业务量需要28张A100,优化后只用18张就绰绰有余。按云上A100单卡月租估算,这10张卡的节省直接把集群回本周期缩短了6个月。对于那些租GPU算力而非买硬件的团队来说,这种提升的意义更直接——如果你通过云老大这类服务商按需租卡,利用率每提高10个百分点,月支出就减少一截。选型时别只看显卡型号和单价,调度方案的健壮性,才是决定长期成本曲线的隐藏变量。
持续优化:GPU利用率监控与调度策略迭代
很多团队把 GPU 共享调度器部署上线后就认为问题解决了,实际上这只是起点。我们在多个生产集群中观察到,碎片会在几小时内重新积累到让大型训练任务无法调度的程度——不是因为调度器算法有缺陷,而是任务负载本身就是动态变化的:早高峰推理请求密集、午间模型训练批量提交、夜间数据预处理占用显存。这种波动性决定了 GPU 利用率优化不是一个一次性工程,需要建立“监控—分析—调参—验证”的闭环。
一个值得警惕的数据是:即使接入了 Volcano 或 HAMi 的共享调度能力,相当一部分集群在运行两周后利用率仍会回落至 40% 以下。原因往往是团队只接入了调度器,却没做二次配置。比如 Binpack 策略的权重没有根据实际任务大小分布调整,导致小任务被 scatter 到多张卡上平铺;又或者 GPU 共享的时间片默认值过大,推理任务在低负载时仍按固定比例切分,白白浪费算力。因此,持续迭代调度策略比选型调度器本身更关键。
关键指标与可视化看板搭建
监控 GPU 利用率最容易踩的坑是只看平均核心利用率。某个推理集群曾连续一周显示 GPU 平均利用率 75%,但细查发现其中 4 张卡长期低于 15%,原因是有两个 daemonset 把这几张卡“占坑”了。建议至少采集三个维度的指标:GPU 计算核心利用率、显存带宽使用率、任务排队时长。用 Prometheus 采集 NVIDIA DCGM 数据,再通过 Grafana 做 per-GPU 热力图,能直观看到集群碎片化的物理分布——哪些卡的碎片被浪费,哪些节点已成调度死角,一目了然。
看板之外,告警规则同样需要精细设计。一个来自运维实践的经验是:利用率低于 30% 的单卡如果持续超过 4 小时,大概率不是“任务已跑完”,而是卡被异常占用或产生了无法调度的碎片。这类问题的治理窗口很窄,拖到第二天可能整集群的调度效率都会受影响。像 yunlaoda 这类服务商在做 GPU 集群架构评估时,通常会把监控看板搭建列为交付标准之一,因为这直接决定了后续碎片治理的响应速度。
自动扩缩容与算力弹性
单纯靠调度策略打补丁解决不了根本问题——算力供给如果不能随任务压力伸缩,碎片治理就是在有限的资源池里做填空题。目前业界较成熟的方案是结合 KEDA 或自定义 HPA 指标,让 GPU 节点池根据任务排队深度自动扩缩。具体操作是:当 Volcano 的 pending 队列中等待超过 5 分钟的任务积压到一定阈值,触发节点自动扩容;反之,当所有 GPU 卡的使用率连续低于一定水位,触发缩容。
但弹性扩缩在实践中有一个容易被忽略的成本陷阱:GPU 节点从启动到 Ready 通常需要 3-8 分钟,这期间积累的等待任务如果贸然被调度到新节点,可能导致“抖动”——即任务刚在新节点启动,老节点碎片又被释放出来,最终两头分散。解决思路是让调度器感知节点“预热”状态,新节点加入后先标记为 unschedulable,待驱动加载完毕、显存就绪后再开放调度,避免任务被反复迁移。如果团队缺乏这类调优经验,找云老大这类有多云服务经验的供应商统一规划算力池,能在扩容策略配置上少走弯路。
更多推荐
所有评论(0)