在云上做分布式训练,真正拖住你的往往不是模型代码,而是容器。
每个容器都要对齐同一套 CUDA runtime、对应编译的 PyTorch、NCCL、EFA userspace 库、把 NCCL 接到 EFA 的 aws-ofi-nccl 插件,再加一个集群 operator 认可的 Ray 版本。任何一层版本错位,八卡训练就会在跨节点通信那一刻崩掉。于是训练一个大模型之前,团队往往先要养一个“镜像工程”,它和你要训练的模型毫无关系,却吃掉大量时间。
AWS 的做法是把这套脏活打包成一张镜像。Ray Train Deep Learning Container(DLC)由 AWS 组装、测试、发布在 Amazon ECR Public 并持续打补丁。训练团队的身份随之改变:从镜像构建者,变成镜像消费者。
一个不构建镜像的样本
AWS 官方博客给出了一个完整样本。用这张镜像在 Amazon EKS 上微调 Qwen2.5-1.5B,训练代码只有一个函数,集群只有一个 RayCluster manifest 加一个变量文件,全程不构建任何镜像。
硬件是两台 g6.12xlarge 实例、八块 NVIDIA L4 GPU,位于同一可用区。控制平面由 AWS 管理,一个 m7i.xlarge CPU 系统节点跑 KubeRay operator 和 Ray head,两台 GPU 节点启用 EFA。KubeRay 从一个 manifest 把集群搭起来,Ray Train 在每个 GPU 上放一个 worker,一共八个,节点间的集合通信直接走 EFA。
结果很直接。只用四个环境变量打开镜像自带的 EFA 路径,代码一行不改,跨节点吞吐量比 TCP 翻倍。
容器的“版本税”
分布式训练最难的不是算法,而是让八台机器上的容器长在同一个环境里。CUDA、cuDNN、NCCL、PyTorch、Ray、EFA 驱动,任何一层版本不匹配,错误都要等到跨节点 all-reduce 时才暴露。更麻烦的是,这套栈不是静态的。NVIDIA 发新版 CUDA,PyTorch 升级,NCCL 修复通信 bug,镜像就得重建、重测、重发布。对大多数训练团队来说,这是必须做但毫无差异化的工作。
Ray Train DLC 的价值在于把这条供应链收走。标签 public.ecr.aws/deep-learning-containers/ray:train-ml-cuda-v1.1 里已经装好 Ray 2.58.0、PyTorch 2.13.0、torchvision 0.28.0、CUDA 13.0.2、NCCL 2.29.7,以及 EFA installer、libfabric 和 aws-ofi-nccl。AWS 把它们当作一个整体测试,而不是让用户自己拼兼容性。
Kubernetes 不懂 Ray 集群
Kubernetes 原生不知道什么是 Ray 集群。它不知道 head 和 worker 的启动顺序,不知道 worker 要连 head 的地址,也不知道 pod 挂了怎么重建一个 Ray 节点。KubeRay 是一个开源 Kubernetes operator,它给 Kubernetes 加了一个 RayCluster 资源。你在一个 manifest 里描述 head 组和 worker 组,KubeRay 负责创建 pod、以正确角色启动 Ray、把 worker 指向 head,并替换失败的 pod。
同一个镜像同时跑 head 和 worker,变的是配置:实例类型、每 pod 分到的 GPU 数、NCCL 用哪种传输、作业需要哪些额外 Python 包。这些都从镜像外部注入,镜像本身不动。
四个环境变量换来的两倍吞吐
EFA 是 AWS 自研的高性能网络接口,绕过操作系统内核直接把数据送进应用空间,适合 NCCL 这种对延迟和带宽敏感的集合通信。但 EFA 不是插上就用。容器里要有 EFA userspace 库、libfabric、把 NCCL 接到 EFA 的 aws-ofi-nccl 插件,还要让 NCCL 知道该走哪张网卡。
样本里只动了四个环境变量。NCCL_DEBUG 设为 INFO,打印选中的传输,方便排错。NCCL_SOCKET_IFNAME 指向 eth0,告诉 NCCL 用 pod 的 eth0 做 socket 通信。FI_PROVIDER 设为 efa,让 libfabric 只用 EFA。NCCL_NET_PLUGIN 设为 ofi,加载 AWS OFI 插件。
请求 vpc.amazonaws.com/efa 资源是让 EFA device plugin 把接口挂载进容器的关键。少了这一行,NCCL 看不到 EFA,会默默回退到普通 socket,吞吐量直接掉一半。
这套方案最漂亮的地方在于,硬件、传输、Python 依赖全部从镜像外部配置。想从 g6 换到 p5 或其他支持 GPUDirect 的实例族,不用改镜像,也不用改训练代码,只要改 manifest 里的变量。
成本账
两台 g6.12xlarge 合计约 9.50 美元/小时,再加上控制平面和 NAT Gateway 的费用。对实验性微调来说,这个门槛足够低。更重要的是,省下的不是这几块钱,而是维护镜像供应链的人力。当团队不再需要专人盯 CUDA 和 NCCL 的版本兼容,工程师才能把时间花在模型和数据上。
复杂度往上收
AWS 正在把 AI 基础设施的复杂度一层层往上收。以前训练团队要自己拼 CUDA、NCCL、EFA、Ray 的兼容性,现在一张 DLC 镜像全包。以前要在 Kubernetes 上自己写 operator 管理 Ray 集群,现在 KubeRay 一个 manifest 搞定。以前要调一堆底层参数才能跑满 EFA,现在四个环境变量就能拿到两倍吞吐。
这对中小团队尤其重要。大公司有专门的 infra 团队维护镜像和通信栈,小团队没有。当云厂商把这些脏活标准化,小团队也能用同样的工具跑多节点训练。差距从“有没有镜像工程师”,变成“会不会用现成工具”。
AI 竞赛的下半场,胜负不只写在模型参数里,也写在容器镜像和网卡驱动里。当云厂商把分布式训练的脏活收进一张镜像,真正的竞争才回到模型和数据本身。






快报