ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

AI云平台搭建实战:从GPU资源池到多租户调度与排错

AI云平台搭建实战:从GPU资源池到多租户调度与排错 一份财报让 AI 云再次成为技术圈讨论的焦点。CoreWeave、Nebius 这两家以大规模 GPU 算力为核心业务的云服务商在财报公布后双双受到市场关注许多讨论从“它们为什么涨”延伸到了“AI 云平台到底是怎么搭起来的”。本文不分析股价只从工程角度拆解 AI 云它和传统云平台的差异、底层硬件与软件栈、一个可运行的 GPU 云最小案例以及多租户、监控和排错中最容易踩的坑。读完这篇文章你能形成一条清晰的 AI 云平台认知主线从 GPU 资源怎么被池化到 Kubernetes 怎么调度任务再到监控、计费和排错怎么做。即使你没有管理过数千卡集群也可以在本地小集群上复现整个流程并把这些经验迁移到真实项目中。1. 先理解 AI 云到底是什么和传统云平台差在哪1.1 AI 云不是“有 GPU 的云”AI 云的概念很容易被理解为“云主机上加一块 GPU”这个理解在小型实验环境里说得通但放到生产环境就不够用了。AI 云是一类以加速计算为核心、面向大规模模型训练和推理场景的云服务平台。它的核心资源不是普通 CPU 实例而是 GPU、高性能网络和高速存储组成的算力集群。一个 AI 云平台要解决三件事让用户在几分钟内拿到可用算力而不是几天。让分布式训练任务能稳定占用几十、几百甚至上千张卡。让算力、存储、网络和配额可计量、可隔离、可计费。跟传统 IaaS 对比差异会更清楚维度传统云AI 云核心资源CPU、内存、普通磁盘GPU、显存、高速网络性能瓶颈单节点 CPU 或 IO多节点通信和显存容量典型任务Web 服务、数据库、微服务模型训练、微调、推理调度单位容器、虚拟机容器但要求感知 GPU 和拓扑网络要求千兆、万兆即可RDMA、低延迟高带宽故障影响服务重启即可长训练任务中断可能损失数小时这里想强调一点AI 云平台的价值不在于“能不能跑一个 GPU 容器”而在于大规模、多租户、可观测和高可用。没有这些能力一个 GPU 节点和一个 AI 云平台之间还差着一整套系统工程。1.2 CoreWeave 和 Nebius 为什么被放在一起讨论CoreWeave 和 Nebius 都属于一类典型的 AI 云服务商面向 AI 训练和推理场景提供 GPU 算力资源。公开信息显示这类公司通常不按传统云厂商“大而全”的方式铺开所有产品而是把资源集中到高性能计算、GPU 集群和专业调度服务上。财报之所以能点燃市场对 AI 云的热情是因为财报背后反映的是 AI 算力需求的增长速度。对工程师来说真正值得关注的是这种需求给基础设施带来的压力GPU 怎么分配、任务怎么排队、断点怎么恢复、成本怎么归属。这些问题不会因为厂商股价波动而变化它们是 AI 云平台建设的长期课题。从技术栈看CoreWeave、Nebius 这类平台和传统 HPC 集群有不少渊源但和传统超算中心又有明显区别它们更强调容器化、可编程、API 化交付用户不是登录一台机器跑作业而是通过接口申请资源、拉取镜像、提交训练任务。这种模式决定了 AI 云平台的工程实现至少包含以下层次。2. AI 云平台的核心技术栈GPU、高速网络和分布式存储2.1 GPU 资源池驱动、容器和可调度性AI 云最底层是物理节点上的 GPU。常见的 GPU 型号包括 A100、H100、A800、L40S 等不同型号在显存、带宽、算子能力上有明显差异。平台至少要能回答三个问题集群里有哪些型号的 GPU、每台机器上有几块、每块 GPU 当前是否可用。底层条件按顺序需要满足操作系统安装了 GPU 驱动nvidia-smi能正常输出设备信息。容器运行时使用 NVIDIA Container Toolkit让容器内可以看到 GPU。Kubernetes 的 NVIDIA Device Plugin 把 GPU 上报成节点资源。调度器根据资源模型分配 GPU。NVIDIA Container Toolkit 安装完成后需要在容器运行时侧配置。以 Docker 为例通常是安装nvidia-container-toolkit后让 Docker 使用nvidiaruntime 作为默认 runtime。生产环境里如果使用 containerd还要在config.toml中配置对应的插件。这一步和普通容器不同不是“启动一个镜像”就能用 GPU 的。Device Plugin 的作用不是调度 GPU而是把 GPU 信息注册到 Kubernetes 节点上。它通过 gRPC 向 kubelet 上报设备列表。没有 Device Pluginnvidia.com/gpu这个资源永远不会出现在节点上任务就会一直 Pending。很多初学 Kubernetes GPU 调度的人在这点上看不清结果怀疑是调度器的问题实际上 GPU 根本没有被感知到。2.2 高速网络AI 云的隐藏瓶颈单卡训练常见场景但大模型训练一定涉及多机多卡。多卡通信依赖 NCCL、MPI 这类通信库而通信库的性能取决于网络。一个 GPU 任务的执行过程是每张卡算完自己的梯度然后通过 allreduce 把梯度同步给其他卡这个过程占用大量带宽和消息量。因此 AI 云平台普遍采用 RDMA 网络常见实现有两种InfiniBand专用网络性能好成本高。RoCEv2基于以太网的 RDMA部署灵活但需要处理 PFC 流控、ECN 标记等问题。不管哪种方案网络拓扑都要考虑“阻塞比”也就是 leaf 上联带宽和下行带宽的比例。如果上联带宽不够多节点训练时通信会严重降速。实践中很多团队发现训练任务跑了却怎么都达不到预期吞吐排查到最后大概率是网络链路瓶颈或者拥塞导致的重传。2.3 分布式存储数据集、日志和模型权重都要有去处AI 训练任务的存储需求不是“买一块云硬盘挂上去”那么简单。训练期间产生的数据分几类训练数据集总量大读多写少需要高吞吐。模型 Checkpoint训练过程中周期性保存一个 checkpoint 可能几十 GB 到 TB 级。日志和指标不断写入体量也很大。推理服务模型文件需要快速加载到显存。这些数据分散在不同节点上但用户希望像看一个统一目录一样访问它们。常见方案是对象存储搭配并行文件系统或者使用 JuiceFS 这类分布式缓存方案。设计时要注意分离“容量”和“吞吐”对象存储存冷数据缓存或并行文件系统跑热数据。一个值得吸收的经验是不要在训练容器里用本地盘保存唯一的 checkpoint。节点故障会把训练成果一起带走。生产环境必须要有远程持久化路径并且训练框架要配置好 Checkpoint 保存目录。3. 搭一个最小可用的 GPU 云环境跑通训练任务3.1 环境准备没有大规模集群也能先验证下面这个案例用于说明思路适合在实验环境或者小规模测试集群里复现。不需要真实采购数百卡三台机器即可一个控制平面节点两个带 GPU 的工作节点。前置条件操作系统建议 Ubuntu 22.04 LTS内核和 libc 满足 Docker 和 Kubernetes 要求。Kubernetes 版本建议 1.26 以上具体以官方支持矩阵为准。每台 GPU 节点安装 GPU 驱动并确认nvidia-smi输出正常。网络节点间可以互通20GbE 以上更好。安装顺序建议安装 Docker 或 containerd。安装 NVIDIA Container Toolkit。初始化 Kubernetes 集群。安装 CNI 网络插件。部署 NVIDIA Device Plugin。验证 GPU 资源可调度。这一步的顺序不能乱。先装运行时、后装 Container Toolkit或者装完 Device Plugin 才发现驱动版本不对都会导致排查成本上升。3.2 让 Kubernetes 识别 GPU 资源安装 Device Plugin 最常用的方式是直接使用官方 DaemonSet。创建部署文件后通过kubectl apply提交。常见的 manifest 名称是nvidia-device-plugin.yml它会以 DaemonSet 方式在每个节点上运行一个 Pod将 GPU 注册给 kubelet。部署完成后用下面的命令检查节点资源kubectl describe node gpu-node-01 | grep nvidia正常的输出会显示nvidia.com/gpu: 8 nvidia.com/gpu: 0第一行是节点被发现的 GPU 总数第二行是当前可分配数量。如果这个字段不出现说明 Device Plugin 没有成功运行。此时先查看 Device Plugin Pod 的日志kubectl logs -n kube-system -l namenvidia-device-plugin常见错误是驱动未安装或者 container runtime socket 路径不对。Device Plugin 默认通过/var/run/dockershim.sock或 containerd 的 socket 与运行时通信不同运行时配置需要调整环境变量。3.3 编写一个使用 GPU 的训练 Pod资源识别成功后可以用一个最小 PyTorch 训练任务验证。写一个gpu-test.yamlapiVersion: v1 kind: Pod metadata: name: gpu-training-test spec: restartPolicy: OnFailure containers: - name: pytorch image: pytorch/pytorch:2.1.0-cuda12.1-cudnn8-runtime command: [python, -c] args: - | import torch if not torch.cuda.is_available(): raise SystemExit(CUDA is not available in container) print(GPU count:, torch.cuda.device_count()) print(GPU name:, torch.cuda.get_device_name(0)) x torch.rand(1024, 1024, devicecuda) y torch.matmul(x, x) print(matmul shape:, y.shape) resources: limits: nvidia.com/gpu: 1注意资源声明。limits.nvidia.com/gpu是必须的Kubernetes 只有看到这个字段才会把 GPU 设备挂载给容器并通过环境变量NVIDIA_VISIBLE_DEVICES让容器内只看到被分配的那张卡。提交并等待kubectl apply -f gpu-test.yaml kubectl get pod gpu-training-test kubectl logs gpu-training-test正常日志会输出 GPU 名称、显存矩阵相乘结果和 shape。到这里最小的“GPU 云”闭环已经跑通用户提交资源申请调度器分配 GPU容器内完成计算。3.4 从单个 Pod 到训练任务为什么要引入队列调度单 Pod 验证通过后很容易让人产生“AI 云已经搞定”的错觉。实际上单个 Pod 只解决资源申请不解决资源竞争和排队。生产环境里几十个团队同时提交任务时需求会发生明显变化大任务和小任务不能互相饿死。任务需要排队不能让所有任务一窝蜂争抢资源。训练任务往往是多个 Pod 组成一个分布式 Job要保证整体调度一致性。任务失败后要支持重试和排队而不是依赖管理员手动删 Pod。这些问题需要引入专门的调度组件。目前常见的方案包括Kueue面向 Kubernetes 的 Job 排队系统支持 ClusterQueue、LocalQueue、Workload 等概念。Volcano更贴近 HPC 场景的批处理调度器支持 gang scheduling、队列和优先级。自研调度器大型云厂商常基于 Kubernetes 调度框架二次开发。以 Kueue 为例它的工作方式是为用户创建一个名为 LocalQueue 的资源对象再通过 ClusterQueue 绑定集群整体配额。用户提交 Job 时指定kueue.x-k8s.io/queue-nameKueue 负责决定任务何时启动、需要多少资源以及是否准入。这种设计的好处是用户不用关心集群总资源只看自己队列的配额管理员可以在 ClusterQueue 上设置公平性和优先级。对于 AI 云平台来说这一层是必须的否则集群只能算“GPU 宿主机池”。4. 多租户隔离、配额和计费是 AI 云落地最难的部分4.1 算力配额先把“谁能用多少卡”说清楚多租户环境下最优先解决的问题是配额。没有配额一个团队就能把集群所有 GPU 占满。Kubernetes 原生提供 ResourceQuota但它管不住“多个任务联合占用”的复杂场景。Kueue 或 Volcano 这类调度器可以把配额抽象成两级ClusterQueue管理员定义整个集群资源池例如total: nvidia.com/gpu64。LocalQueue用户或团队使用的一个队列绑定到某个 ClusterQueue并定义该团队最多可以用多少。集群管理员要决策的另一个维度是“任务失败后配额怎么释放”。如果任务因为某个节点故障退出调度器要能够把相关资源重新回收而不是等任务超时。排队系统在解决这类问题时会引入停止、重试和优先级等状态机。生产环境中配额设计直接影响集群利用率和用户体验。4.2 隔离策略不只是资源隔离还要看安全和故障爆炸半径多租户隔离有几个层次资源隔离CPU、内存、GPU 数量、显存。网络隔离不同租户的 Pod 不能互相访问。存储隔离数据集和 Checkpoint 的权限隔离。故障隔离一个租户的任务不能影响另一个租户的节点稳定性。Kubernetes Namespace 是基础但 Namespace 不是隔离边界。如果没有 NetworkPolicy不同 Namespace 的 Pod 仍然可以互相通信。对于 AI 云平台还需要在容器侧关注 GPU 显存隔离。NVIDIA 官方提供的 MIGMulti-Instance GPU可以把物理 GPU 切分成多个小实例适合推理场景和细粒度显存隔离但它不适合所有型号和所有任务。4.3 计费数据没有准确计量就没有成本归属计费是 AI 云平台最容易低估的部分。要计费必须先有准确的资源使用数据。计量维度通常包括维度数据来源说明GPU 型号节点标签H100/A100/L40S 单价不同使用时长Pod 创建和删除时间按秒计费更精细GPU 数量调度器已分配资源实际分配数而不是申请数存储用量分布式存储接口快照和备份也计入网络流量网络流量采集一般只计跨机房或公网流量实现时通常用 Kubernetes 事件和 Prometheus 指标组合一个组件监听 Pod 的创建、删除事件生成使用明细另一个组件从节点监控采集 GPU 利用率用于效率分析和成本优化展示。常见做法是把计费明细写入 ClickHouse 或关系数据库再通过报表接口输出。这里有一个常见坑直接用 Pod 状态作为计费依据忽略 Pod 已结束但容器仍在清理的阶段或者忽略 GPU 已分配但利用率极低的时段。计费应该按“资源被占用的时间”计算而不是按“任务有效计算时间”。否则系统会漏掉大量闲置成本。5. AI 云里的高频故障队列不前进、显存泄露、网络降速5.1 Pod 一直 Pending卡在排队状态现象任务提交很久Pod 一直是 Pendingkubectl describe显示没有可用节点。按以下顺序排查查看kubectl get events是否提示资源不足。检查nvidia.com/gpu在当前节点是否可分配而不是总数。确认是否被队列调度器挂起LocalQueue 是否有配额。检查是否有节点污点或亲和性规则阻止调度。检查kubectl get resourcequota看 Namespace 配额是否耗尽。队列场景里最常见的现象是任务没有报错但一直停在 Pending。此时要看调度器日志以及 Workload 对象的状态。Kueue 会为每个任务创建 Workload查看它的状态kubectl describe workload workload-name关注status.conditions和admission字段。如果长时间没有admitted条件说明资源配额不足或队列配置错误。5.2 显存泄露训练时间越长可用显存越少现象单一任务运行数小时后显存占用持续上升最终 OOM 被杀死。可能原因PyTorch 代码中创建了 Tensor 但没释放。DataLoader 子进程持有 GPU 上的租户上下文。框架自身的缓存管理器在分布式环境没有正确清空。监控到的是残留进程占用而不是当前任务占用。排查方法nvidia-smi如果看到“No running processes”但显存仍被占用说明存在残留进程或 zombie 进程。先查 PIDnvidia-smi --query-compute-appspid,used_memory --formatcsv再用 PID 查容器。如果显存是随着 Step 稳步上升需要检查训练循环里是否每一步都往 GPU 上追加新节点、是否把中间结果保存到了self、是否在推理时开启了梯度计算。训练循环里应确保每次反向传播后梯度释放模型参数和优化器状态是唯一长期驻留显存的对象。5.3 网络性能差多机训练吞吐不升反降现象增加到多机后训练时间没有按预期缩短甚至变长。先做网络层验证。如果使用 InfiniBand检查链路状态ibstatus如果使用 RoCE检查网卡统计ethtool -S eth0 | grep -i discard\|error\|cnp然后用 NCCL 自带测试工具做 allreduce 性能测试nccl-tests/build/all_reduce_perf -b 8M -e 1G -f 2 -g 8性能下降的常见原因NCCL 没有识别到 RDMA 设备走了 TCP fallback。多个任务抢占同一个 leaf造成拥塞。网卡固件、驱动、环境变量NCCL_IB_DISABLE配置错误。MTU 不一致导致分片重传。生产环境里建立网络基线的做法是在集群上线前跑一轮all_reduce_perf保存结果。之后每次扩容、升级驱动或调整拓扑都用同一命令跑看数据是否退化。没有基线就无法判断训练变慢是不是网络造成的。5.4 镜像拉取慢大规模并行任务启动时集中拉镜像现象训练任务启动后大量 Pod 处于ContainerCreating节点镜像下载占满带宽。应对方案预先在节点上缓存基础镜像。使用本地镜像仓库和镜像预热工具。训练基础镜像不要频繁变动标签使用可重复的版本号。避免在训练容器启动时安装依赖把依赖固化到镜像里。镜像问题是 AI 云平台最常见的“非 GPU 故障”。很多团队把精力放在 GPU 调度上却忽略了大规模任务并发启动时的镜像分发瓶颈。6. 学习环境和生产环境的差异决定了这套方案能不能真正落地6.1 场景差异对照事项学习/实验环境生产 AI 云集群规模1 到 3 台节点数十到数千台节点调度器默认调度器即可需要 Kueue、Volcano 或自研调度安全隔离Namespace 足够需要网络策略、RBAC、审计日志存储本地盘即可并行文件系统加对象存储监控看 nvidia-smiPrometheus DCGM 告警计费不需要必须有计量和成本报表高可用允许重启需要故障域、断点续训、自动恢复变更发布随意调整需要镜像灰度、版本回滚、权限审批生产环境建议至少补齐以下能力配置外置化集群参数不能写死在容器里。日志采集和监控告警要覆盖 GPU 利用率和显存。权限控制到 Namespace 和 ClusterQueue 级别。异常处理要包含任务失败自动重启、队列重试和 Checkpoint 恢复。扩容前先跑网络基线测试。数据备份和快照策略要覆盖模型权重和实验结果。6.2 生产发布前的最小检查清单在把 AI 云服务开放给内部用户前可以用这张清单逐项确认。检查项检查方式达标标准GPU 资源可见kubectl describe node每个节点都有 nvidia.com/gpu驱动与运行时匹配nvidia-smi和容器内nvidia-smi输出一致容器可见 GPUDevice Plugin 健康Pod 日志无 error启动后无持续报错多队列调度提交两个队列的任务配额内正常、配额外排队网络基线all_reduce_perf多机吞吐符合预期显存指标DCGM 导出的指标GPU 利用率和显存按时序可见存储持久化训练写 checkpoint 并读取重启后数据可恢复计费明细运行测试任务记录入账、时长准确权限隔离跨 Namespace 访问被拒绝或告警这张清单不是一次性项目而是每次扩容、升级驱动、更换存储或调整调度策略后都要重跑一遍的回归项。7. 最佳实践把 AI 云做成可复用平台而不是一堆脚本7.1 直接使用被验证过的组件少自己造轮子GPU 调度、网络监控、镜像分发这些领域都有成熟组件。我的建议是第一版尽量使用社区方案把 Kubernetes、Device Plugin、Kueue、Prometheus、DCGM 组合起来。只有当性能需求或业务模型明显超出社区方案能力时才考虑自研调度器或监控系统。自研的代价不只是开发还包括长期维护和升级兼容。很多团队在自研调度器上投入大量人力最后发现问题往往不在调度算法而在资源上报、故障恢复和可观测性这些基础能力上。7.2 训练任务要有断点续训能力大模型训练最怕的是跑了两天节点故障导致任务整体失败。平台侧能做的关键事情是配置 Checkpoint 远程持久化。训练框架启动时支持从指定 Checkpoint 恢复。调度器在任务失败后自动重建 Pod而不是停在那里等人处理。建议训练脚本在每次保存 Checkpoint 后输出版本号并由平台负责记录当前最优可用版本。这样即使任务中途失败也能从最近一次完整保存的状态恢复而不是从头开始。7.3 成本控制要落到 GPU 利用率优化成本不是“少买卡”而是提高卡的有效利用率。需要看几个指标实际 GPU 利用率DCGM 提供的利用率。显存分配率和显存使用率。任务排队时间。资源碎片率。把集群利用率做成看板后就可以推动用户做三件事使用更合适的 GPU 卡型、避免无用长占、用分时调度共享不连续的 GPU 片段。这些优化措施比单纯压价格更有价值。7.4 扩展方向从 GPU 云到完整 AI 平台下一层要思考的是用户拿到 GPU 后资源申请、环境准备、实验管理怎么统一起来。常见的扩展路径训练平台把训练脚本包装成可复用的任务模板。推理平台把模型部署成在线服务并支持自动扩缩容。数据集管理提供数据集版本和数据加载库。模型仓库统一管理模型权重、版本和元数据。这时 AI 云就不再只是“算力租赁”而是一个稳定的 AI 开发基础设施。CoreWeave、Nebius 这类公司受市场关注本质上也说明市场在为一个趋势投票AI 的竞争正在从模型算法延伸到基础设施效率。对工程师来说能够把 GPU 资源变成可靠、可观测、可计费的平台能力就是最值得积累的长期方向。
返回列表