混合云AI智算平台,最近几乎是算力圈最热的关键词。它不是一个单点产品,而是一整套基础设施方案:公有云的弹性、私有云的可控、统一调度策略,全部被推进同一个资源池里。你可以把敏感数据留在私有云上训练,让高峰期多出来的任务自动溢到公有云GPU节点,整个过程中用户几乎无感知。大模型训练、AI Agent推理、AI测试开发、多AI协作,这些场景需要的其实不只是“有卡可用”,而是“卡能不能随时被用得满、用得稳、用得起”。这篇文章不打算念产品通稿,而是我从实际搭建混合云AI智算平台过程中整理出来的设计思路、关键参数、配置方法和避坑记录。适合正在做算力选型、搞GPU资源池化的同行,也适合刚接手AI平台建设、想快速建立全局观的朋友。
1. 整体设计:为什么混合云比纯私有云或纯公有云更能打
1.1 算力需求本身就是矛盾的
AI平台的算力需求,表面上是一个容量规划问题,实际上是一堆互相打架的约束。
先说弹性。大模型训练是有波峰波谷的,发布会之前要跑评测、做对齐,算力需求突然就拉满;日常开发阶段,大家可能只是小批量调参,资源又闲得发慌。纯私有云对这种突发流量很痛苦,你要么按峰值一次性采购,结果大部分时间在浪费;要么就让大家排队,研发体验直接崩掉。公有云的优势是几分钟就能开出上百张卡,但长期跑训练,单价并不便宜。
再说数据安全。很多行业的数据是不能出私有云范围的,比如医疗影像、金融交易数据、政企内部语料。但大模型训练又恰恰需要海量算力,不可能把敏感数据拷贝到公有云的存储里再训练。所以数据在哪儿、算力在哪儿,这两个问题是绑在一起的。
最后是成本结构。AI训练的成本大头是GPU折旧和电力,不是软件License。若所有业务都跑在公有云上,账单会非常难看;全放私有云,又面临利用率低。混合云把“稳态负载”放在私有云,把“潮汐负载”或“探索性负载”放到公有云,才能让单位算力成本真正降下来。
1.2 混合云的核心不是“打通网络”,而是“统一抽象”
很多团队容易把混合云理解为“拉一根专线、做一层网络互通”。真做起来会发现,这只是最基础的一步。用户要的是“我只看到一个资源池”,而不是今天去这个控制台提交任务、明天去另一个控制台看日志。
我比较推荐“控制集群 + 成员集群”的分层结构。控制集群上跑平台服务,比如认证、项目空间、配额管理、任务入口;成员集群可以有一个私有云集群,也可以挂一个或者多个公有云集群。控制集群本身不跑训练任务,避免平台自身故障放大到业务侧。成员集群只负责执行,每个集群内部保留自己的调度能力,但任务应该进哪个集群,由上层统一决策。
这里的关键点在于:算力并不是“均匀分布”在底下的集群里,而是通过标签和容量信息被抽象成一张资源逻辑视图。比如私有云集群有64张A100,公有云集群有128张L40S,每个GPU节点都打上“型号、显存、是否支持RDMA、所属项目”等标签。调度层看到的是这些标签,而不是具体IP。只有这样,用户在平台上提交一个需要8张卡的任务时,系统才会自动计算哪个集群能满足,哪个集群排队最短。
1.3 “领导者”不是说出来的,是调度精度决定的
标题里写“领导者”,如果只是宣传口径,那没什么意思。真正配得上这个称谓的平台,靠的是调度精度和故障自愈能力。
打个比方:如果把GPU比作自来水,私有云和公有云就是两个水库,调度器就是水厂管网。差的管网要么压力不均,要么哪天某个水库检修,整片区域停水;好的管网能做到跨水库互相补水,用户打开水龙头只关心水量和水压。AI智算平台也一样,节点宕机、GPU卡故障、网络闪断都是常态,平台能不能自动把任务迁走、重新排队、快速拉起,这才是“领导者”和“玩具平台”的分水岭。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心细节:GPU资源池化、调度与数据流的处理逻辑
2.1 把GPU当成“液体”,而不是“铁块”
私有云建设最容易犯的错,是把GPU按物理机器分给人。张三这台机器上有8张卡就归张三,哪怕他只用1张,剩下7张也闲着。资源利用率上不去,很正常。
通用做法是GPU资源池化。按粒度从粗到细,可以分三种:
- 整卡分配:最小的调度单位是一张GPU卡,适合大模型训练、分布式推理。
- GPU切分:用MIG或vGPU把一个物理卡切成多个小显存实例,适合小模型推理、在线服务。
- 时间片共享:多个任务轮流用同一张卡,适合开发调试。
实际使用中,大模型训练最好给整卡,因为张量并行、流水线并行的卡间通信频率极高,切分和时间片都会导致通信抖动。推理场景则可以大胆用MIG或者vGPU,因为单个推理请求占用显存小,切分后反而能提高吞吐。但要注意,MIG会锁死显存分区,动态调整不方便;时间片共享则存在上下文切换开销。不要一上来就开时间片,先看真实负载。
做成池子之后,不是只要用Kubernetes管理就行。还需要把GPU的“健康状态”纳入调度输入。比如一张卡出现ECC错误,或者驱动异常,调度器必须能感知并把它从资源池里摘掉,否则任务一跑就Crash,用户体验极差。
2.2 调度器选型背后的权衡:为什么我们选了Volcano
Kubernetes默认调度器是可以用的,但要直接拿着做AI平台,很快会遇到三个问题:
- 多卡任务要求“全有或全无”(Gang Scheduling)。一个需要8张卡的任务,如果只等到5张就会被调度,然后卡在那里等待,其他任务又占着另外3张,最后谁也跑不起来。
- 缺少队列和优先级机制。多人训练时,小任务可能长期饿死,或者紧急任务被排队堵住。
- 资源分配策略不够灵活。默认调度倾向于均匀分散,但训练任务更希望把卡集中在一个节点组里,减少跨机通信。
我们最终选了Volcano。它提供了PodGroup的概念,可以一次调度一组Pod,等全部条件满足再执行;也支持队列(Queue)、优先级、抢占。相比Kueue,Volcano对批量任务的支持更成熟,社区案例也多。
下面是一个简单的队列配置示例:
yaml复制apiVersion: scheduling.volcano.sh/v1beta1
kind: Queue
metadata:
name: training-queue
spec:
weight: 10
capability:
cpu: "400"
memory: 1024Gi
nvidia.com/gpu: 64
队列里capability字段限定了这个队列最多能拿多少GPU。好处是:销售、研发、算法各组分别建队列,互不抢资源,同时允许某个队列空闲时被其他队列借用。
任务提交时,我们会在平台里自动生成一个PodGroup:
yaml复制apiVersion: scheduling.volcano.sh/v1beta1
kind: PodGroup
metadata:
name: llm-finetune-job
spec:
minMember: 8
minResources:
nvidia.com/gpu: "8"
cpu: "120"
memory: 512Gi
queue: training-queue
调度器看到这个PodGroup后,会同时寻找8个满足条件的Pod资源位置。只要不满足,任务就保持在Pending状态,不会出现半启动的僵尸任务。
单靠Volcano还不够,跨集群时还需要一个“上层大脑”。我们目前用Karmada做多集群统一协调,它把多个Kubernetes集群抽象成一套API,支持按集群标签分发资源、跨集群弹性扩容。这样Volcano负责单集群内的细粒度调度,Karmada负责把任务整体分到合适的集群,分工相对清晰。
2.3 数据面才是隐藏的“性能杀手”
在混合云AI智算平台里,最容易忽视的是数据流设计。很多人觉得,GPU越贵越重要,但实测下来,很多训练任务GPU利用率低,不是因为卡不行,而是因为数据加载跟不上,GPU在那儿空转等数据。
核心建议如下:
- 训练数据如果以小文件为主,用对象存储加多线程预取更合适。
- 如果是大文件、checkpoint频繁读写,首选并行文件系统或分布式文件系统,例如Lustre、JuiceFS、WEKA之类的方案。
- 公有云和私有云之间的存储不要直接硬连,因为网络延迟和带宽都可能成为瓶颈。更好的做法是:私有云主存储只放敏感数据和最终checkpoint,公有云侧放只读热数据缓存。
我给的落地形态是:私有云文件存储 + 公有云对象存储 + 一套元数据同步服务。数据集上传后先落私有云,然后异步复制到公有云;训练任务如果在公有云节点上跑,优先从公有云侧读取已复制的副本,任务结束后只把结果写回私有云。这样既保证了数据安全,又避免了跨云读数据的高延迟。
镜像分发同样容易踩坑。训练镜像动辄十几个GB,如果每次扩容都从私有云拉镜像,节点冷启动会非常慢。我们用了Dragonfly做P2P镜像分发,新节点加入后,不只从仓库拉,还能从周围的同行节点拉镜像层,扩容时间从原来的十几分钟降到两三分钟。
3. 实操过程:从零搭建混合云AI智算平台的关键步骤
3.1 网络和硬件规划:尽量把麻烦留在前期
网络是所有环节里最不敢后期将就的部分。我的经验是,在画拓扑的第一天就要想清楚三类流量:
- 业务管理流量:用户访问平台、提交任务、看日志。
- 存储流量:读写数据集、checkpoint。
- 训练通信流量:GPU之间的NCCL通信,东西向流量极大。
尽量把训练通信流量隔离到独立子网,并且使用RDMA网络。现在用得比较多的是RoCE v2,好处是成本比InfiniBand低,但要求交换机开启PFC和ECN,否则拥塞丢包会让分布式训练频繁NCCL超时。
硬件选型方面,GPU型号要匹配场景:
| 场景 | 推荐配置 | 说明 |
|---|---|---|
| 大模型预训练 | A100/H100 80G,多机互联 | 通信需求极高,最好用NVLink+RDMA |
| 微调和推理 | L40S/A10,性价比优先 | 不需要超大显存,注重吞吐 |
| 小规模实验/测试 | 消费级GPU或共享切分实例 | 开发调试够用,成本低 |
RoCE交换机的缓存建议留大一些,否则广播风暴一来,整个训练集群都会卡死。
3.2 平台软件栈部署:分层不要混
每个集群内的软件栈,我习惯按四层来装:
- Kubernetes集群本身:建议稳定版本,不要追新,插件兼容性比新特性重要。
- GPU资源层:NVIDIA device plugin负责把GPU上报给Kubernetes,DCGM exporter负责采集显存、温度、功耗、利用率等指标。
- 调度层:Volcano队列和PodGroup,再加Karmada做跨集群编排。
- 平台接入层:统一认证、项目空间、配额、Notebook、任务提交、日志查询。
平台接入层尽量用开源组件拼装,而不是自己从零写。比如Notebook用JupyterHub,训练任务模板用Kubeflow的Pipeline或自定义CronJob,日志用Loki加Grafana。只要保证这些组件都复用同一个Kubernetes API,就不会被某个厂商锁死。
部署顺序也有讲究。先装GPU驱动和容器运行时,再起Kubernetes控制面,然后是device plugin,最后才是平台组件。如果先装平台再补驱动,很容易出现GPU资源上报正常但任务一跑就报错的情况。
3.3 一次训练任务从提交到运行,到底发生了什么
以“在8张A100上微调Llama-3-8B”为例,完整流程如下:
第一步,用户创建项目,选择镜像和数据集。平台会申请一个PVC,把数据集挂载到任务Pod里。
第二步,平台根据用户填写的资源请求,生成Volcano的PodGroup。这里我们能估算一下显存:模型权重为FP16时,8B参数大约占16GB;梯度再占16GB;优化器如果用AdamW,每个参数还需要保存FP32的权重副本和一阶、二阶动量,这部分大约每个参数12字节,总计96GB。所以8B模型微调,单卡80GB根本放不下,必须用ZeRO把优化器状态分片到多卡。8张A100总共640GB显存,扣除中间激活值之后才比较从容。这个估算过程我每次都会给用户讲一遍,让他们知道,为什么平台要求至少8卡起步,为什么“能跑起来”和“能高效跑起来”完全不是一回事。
第三步,Karmada看到跨集群调度请求,先判断私有云集群剩余容量是否可以容纳这8卡。如果私有云不够,再去看公有云节点池,并把任务分发过去。
第四步,Volcano在目标集群上找到足够的GPU节点,创建训练任务。任务启动前,训练框架会通过NCCL建立通信组。这里容易踩坑:如果跨节点通信走RoCE但交换机没有开启PFC,NCCL会反复超时,卡在等待状态。
第五步,训练过程中,平台里的一个Sidecar容器会定期把checkpoint上传到对象存储。这是应对公有云抢占式实例的关键,不是可选项。
整个链路看似简单,但每一环节都需要监控。我们做了三类指标:GPU利用率和温度;网络丢包和拥塞;数据加载时延。这三类指标同时看,能快速定位绝大多数问题。
3.4 弹性伸缩不是“有按钮就行”,要配合成本策略
公有云的弹性是混合云最大的红利,但也最容易失控。弹性扩缩容需要设置两类策略:
一类是“容量触发”,当某个队列的排队任务超过阈值,自动扩容节点池。注意,GPU节点的初始化时间比普通CPU节点长,所以阈值不要设得太高,否则用户已经等得不耐烦了,节点还没就绪。我们一般把阈值设在队列容量的70%左右。
另一类是“成本触发”,对于可以容忍中断的训练任务,使用公有云的抢占式实例或Spot实例,价格低很多。但这要求平台必须支持自动保存checkpoint,并且节点被回收后,任务能自动重新排队再恢复。我给训练框架加了一个环境变量,用来标识“当前任务是否允许中断”;如果允许,平台会每5分钟保存一次checkpoint,并把断点信息写入元数据。
关于成本,还有一个容易被忽略的点:计费要按项目拆分。GPU卡租出去,不能只记一个总账单。我们按项目标签统计每个任务占用GPU的卡时数,再乘以当月GPU单价,就能看到哪个项目在烧钱。没有这一步,优化成本就是空谈。
4. 常见问题与排查技巧实录
4.1 GPU利用率低:先查数据管线,再查调度
我见过最多的现象是,训练任务跑着,但GPU利用率长期在30%以下。很多人第一反应是换更大的Batch Size,实际上要先看监控图。
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| GPU利用率突然掉到0又拉满 | 数据加载慢,CPU吃不下 | 查看数据读取耗时、预取队列大小 |
| 多卡利用率参差不齐 | 部分卡因数据Shuffle不均匀或网络延迟 | 检查NCCL通信耗时、RoCE丢包 |
| 单卡利用率高但整体上不去 | 任务本身串行或多进程竞争 | 看CPU核数和内存是否够,看是否做了算子融合 |
有一次,我们某个训练任务利用率低,排了一整天,最后发现是数据集存在慢速机械盘上,训练时大量小文件随机读,数据加载线程全部卡在I/O上。换到JuiceFS缓存后,利用率直接从35%涨到80%以上。所以,GPU利用率低不要先怀疑代码,先怀疑“数据到不了GPU手里”。
4.2 节点异常和任务卡死的处理
GPU节点在机房运行久了,很难保证不出问题。常见的故障整机表现为“任务长时间无日志输出”或“NCCL超时”。我们的做法是,用DCGM采集GPU的Xid错误,一旦检测到Xid错误,立即给节点打上污点并停止调度新任务,同时把已有任务重新排队。
注意一点:不是所有Xid错误都一定要换卡。有些Xid错误是驱动bug或温度问题,清掉GPU进程后可能恢复。我们写了一个自动健康检查脚本,每10分钟做一次“小显存张量分配+释放”的探针测试,连续失败两次才把节点标记为故障。这样既避免了误伤,也能挡住真正坏掉的卡。
训练任务hang住时,最实用的命令是先看“卡在哪个阶段”:
bash复制kubectl exec -it <training-pod> -- nvidia-smi
如果进程还在,看GPU使用率;如果GPU上根本没进程,说明任务还在等数据或等通信。此时再检查Pod日志和NCCL debug。很多分布式训练卡死,都是因为两个节点之间的网络不通,而不是训练代码本身的问题。
4.3 公有云节点访问私有云存储很慢
跨云存储慢的问题几乎必然会遇到。公有云的GPU节点物理上在公有云机房,去访问私有云的文件存储,即使有专线,延迟也不乐观。最有效的办法就是前面提到的“数据副本前置”:公有云节点池挂载一个对象存储桶,训练数据提前同步过去,任务运行时只读本地云上的桶。
如果某些数据敏感,不能复制到公有云,那就不要让任务跑到公有云上,把NS调度到私有云集群。这也是为什么调度器一定要支持“按数据位置调度”,而不是只看GPU数量。
4.4 避坑清单:这些细节决定了平台的上限
先说驱动和容器运行时版本。强烈建议用官方源装驱动,不要图省事用系统自带驱动。很多离奇的GPU故障,最后都查到是驱动与CUDA版本不匹配。
再讲时间片共享。训练任务千万别开时间片,除非是单纯写代码调试。原因很简单:NCCL的通信对延迟很敏感,一旦GPU时间片被抢占,整个分布式训练的同步点就会被拉长,性能下降不是线性而是断崖式的。
镜像仓库也要提前规划。团队不同、框架版本不同,镜像会快速膨胀。我们规定每个人必须基于基础镜像做增量,禁止把数据集打进镜像。否则每次扩容都要下载几十GB镜像,节点永远等不起来。
最后是配额。混合云平台的配额要按“CPU、内存、GPU、存储、对象存储流量”分别设置,不能只限制一张GPU卡。否则一个用户在公有云上疯狂读写对象存储,成本可能比GPU本身还高。
最后再分享一个实际体会
混合云AI智算平台这个东西,表面上是在做技术架构,实际上是在把内部流程重做一遍:谁有权限申请算力,申请多少,任务排队多久,成本算到哪个项目。这些流程不梳理清楚,再好的调度器也白搭。我个人的建议是,第一步先把GPU资源池化,用一套配额把预算卡住;第二步再做跨云调度,让任务能自动溢出;最后再去优化GPU利用率。顺序不要反。
如果要给一个最实用的小技巧,那就是:从一开始就把所有GPU节点的标签打好,包括型号、显存、网络类型、所属集群、是否可被Spot任务占用。标签打得越细,后面做调度策略、成本可视化、容量预测的时候就越省力。等真正遇到大规模并发任务时,你会感谢当时的自己。
