Skip to main content

2016年前后起,OpenAI便开始基于KubernetesK8S)构建其AI研究基础设施,并将集群规模逐步从数百节点扩展至7500个节点,先后支撑了GPT-3CLIPDALL·E等大规模模型的训练。2021年之后,OpenAI公开资料的重点逐渐从Kubernetes控制平面扩展转向更大规模的算力供给、超算网络可靠性和推理效率:包括AzureOCI容量扩展、Stargate基础设施项目、与多家硬件和云厂商合作开发的MRCMultipath Reliable Connection)网络协议,以及与Broadcom合作的Jalapeño推理芯片。

大多数团队在建设AI训练集群时,不可能像OpenAI一样一步到位地投入超算级资源,而是从小规模Kubernetes集群起步,随着业务增长逐步扩容。OpenAI走过的弯路——etcd打满、API Server内存爆炸、网络性能折损、GPU悄无声息地坏掉——恰恰是每个处于扩容阶段的团队都会面临的真实问题。本文基于OpenAI历年官方博客和公开技术文章,系统梳理其选择Kubernetes的决策逻辑、规模扩张中的技术挑战与工程解法,为有意构建或扩展AI训练集群的团队提供有据可查的实践参考。

为什么选择Kubernetes而非Slurm

AI训练领域,Slurm是高性能计算(HPC)社区最广泛使用的作业调度框架,拥有几十年的成熟积累。相较于传统HPC作业调度体系,OpenAI官方文章强调Kubernetes更适合其研究实验的快速迭代和工程扩展需求,其核心原因如下。

研究迭代速度优先

OpenAI的主要工作性质是基础研究,工作负载持续变化。研究人员每天都在尝试新的模型结构、训练方案和并行策略,对基础设施的要求不是极致的调度效率,而是快速迭代、低操作摩擦、灵活适应Kubernetes在这些方面提供了显著优势:

  • 容器化统一了依赖管理:每个实验的运行时依赖(Python版本、CUDA版本、依赖库)均封装在镜像中,研究员无需与集群管理员协商软件环境。
  • 声明式API降低了接入门槛:研究人员通过YAML描述计算需求,无需学习Slurm复杂的sbatch脚本和分区策略。
  • 生态丰富:监控(Prometheus/Grafana)、日志(Fluentd)、存储(PersistentVolume)等云原生生态可直接复用。

官方博客原文表述如下:

Kubernetes provides a fast iteration cycle, reasonable scalability, and a lack of boilerplate which makes it ideal for most of our experiments.

云原生与多租户支撑

OpenAI公开文章中的最大Kubernetes集群运行在Azure云上,同时也提到团队运行过其他云上和物理硬件集群。后续网络实践中,OpenAI使用Azure VMSS(虚拟机扩缩容组)的原生Pod网络能力和对应CNI插件;在资源隔离上,则通过NamespaceTaint/Toleration等机制支撑多团队使用。

工作负载特征适配

OpenAI的工作负载有几个区别于典型企业Kubernetes使用场景的特点,这些特点恰好规避了Kubernetes在通用场景下的弱点:

特征说明
Pod独占整机大型训练任务每个Pod占满一整台节点,避免了NUMA/CPU争用和碎片化
全平分带宽网络集群拥有全bisection bandwidth,无需拓扑感知调度
少量超大型任务调度压力呈脉冲式,并发任务数相对有限
Blob存储为主数据集和Checkpoint直接读写对象存储,减少了对分布式文件系统的依赖

这些特征让Kubernetes调度器的压力远低于通常预期,使得K8S在该场景下运行得相当稳定。

OpenAI AI 训练基础设施演进

OpenAI公开披露的AI训练基础设施经历了以下主要阶段:

遭遇的挑战与解决方案

etcd扩展性问题

问题描述: 集群超过500个节点后,研究人员开始频繁遇到kubectl命令超时。增加kube-apiserver副本数只能暂时缓解,并非治本之策。

根因排查: 通过Prometheus监控和audit-log发现,etcd的写入延迟飙升至数百毫秒。虽然节点使用了P30 SSD(理论5000 IOPS),但etcd是顺序I/O模式,受写入延迟限制,实际只使用了约10%的可用IOPS

解决方案:

阶段问题解决方案
500节点网络SSD延迟2msetcd目录迁移至本机SSD200µs延迟)
1000节点kube-apiserver读取etcd500MB/s降低Fluentd/Datadogapiserver的轮询频率
1000节点Kubernetes Events写入高峰冲击主etcdEvents独立存放到单独的etcd集群
1000节点etcd触达2GB硬存储上限导致级联故障通过--quota-backend-bytes扩大存储限制;自动扩缩容器增加安全检查

Events拆分到独立etcd集群的配置方式如下:

--etcd-servers-overrides=/events#https://etcd0.example.com:2381;https://etcd1.example.com:2381;https://etcd2.example.com:2381

API Server内存压力

问题描述:7500节点规模下,每个API Server进程堆内存使用量高达70GB

根因分析: API Server内存消耗与集群节点数线性增长。同时,对kubeletnode-exporter等覆盖所有节点的ServiceEndpoints WATCH操作会在节点增删时触发 $O(N^2) 级别的通知风暴,在高峰期带宽超过1GB/s

解决方案: 升级至Kubernetes 1.17后启用EndpointSlices,将WATCH带宽压力降低了 1000 。同时,OpenAI对所有DaemonSet避免直接交互API Server,对确实需要节点级WATCH的场景引入中间缓存层(如Datadog Cluster Agent模式)。

网络性能瓶颈

2500节点阶段 —— Flannel性能不足:

直接机器间带宽为10-15Gbit/s,但Flannel封装后Pod间带宽只有约2Gbit/s。短期解决方案是为通信密集型Pod设置hostNetwork: truednsPolicy: ClusterFirstWithHostNet,绕过Flannel

7500节点阶段 —— 改用原生网络:

随着集群规模扩大(约200,000IP地址),Flannel路由方案面临路由数量限制。OpenAI切换至Azure VMSS原生Pod网络和对应的CNI插件,实现了Pod与宿主机网络同等的吞吐量。避免封装带来的额外好处包括:

  • MTU碎片化问题
  • 网络策略和流量监控更直观
  • 支持灵活叠加VPN/隧道

同时,OpenAI使用iptables mangle规则对流量打标,结合开源iptables-exporter接入Prometheus,实现按NamespacePod级别的网络用量可视化。

镜像拉取问题

Dota项目的容器镜像约17GB。在没有镜像缓存的新节点上,OpenAI观察到该镜像经常需要约30分钟才能完成拉取和解压,导致Pod长时间停留在Pending状态;更麻烦的是,kubelet默认串行拉取镜像,使这个大镜像会阻塞同节点上的其他镜像拉取。OpenAI通过以下方式系统性解决了镜像拉取问题:

措施效果
--serialize-image-pulls=false + 切换overlay2多镜像并发拉取,不再互相阻塞
Docker root移至本机SSD拉取和解压速度大幅提升
--image-pull-progress-deadline=30m避免大镜像拉取、解压或排队时间过长时被误判为无进度失败
max-concurrent-downloads=10提高并行拉取队列吞吐量
基础设施镜像预加载进VM镜像消除gcr.io配额限制和冷启动延迟

ARP缓存溢出

问题描述: Pod数量增多后,DNS解析间歇性失败,dmesg日志出现neighbor table overflow!

根因分析: Kubernetes中每个Pod都有独立IP,大集群中ARP缓存条目数量远超内核默认限制。

解决方案: 将节点sysctl阈值从Linux常见默认值(gc_thresh1=128gc_thresh2=512gc_thresh3=1024)大幅调高:

# 邻居表条目数低于该值时,内核通常不会主动触发垃圾回收。
net.ipv4.neigh.default.gc_thresh1 = 80000

# 邻居表条目数超过该值后,内核会更积极地回收旧条目。
net.ipv4.neigh.default.gc_thresh2 = 90000

# 邻居表硬上限;超过该值后,新邻居条目可能无法创建,并出现 neighbor table overflow!。
net.ipv4.neigh.default.gc_thresh3 = 100000

这些参数控制的是Linux IPv4 neighbor table,不只包括传统ARP条目,也包括Kubernetes节点上Pod与节点通信过程中产生的邻居表项。这也是HPC集群中的常见调优项,在Pod数量多的Kubernetes场景下同样适用。

需要注意的是,不同发行版或云厂商镜像可能会调整默认值,生产环境应以节点上实际sysctl net.ipv4.neigh.default.gc_thresh*输出为准。

监控系统Prometheus扩展问题

问题描述: 集群规模增大后,Prometheus内存持续增长直至OOM崩溃;崩溃后重放WAL(Write-Ahead-Log)需要数小时才能恢复服务。

根因与解决方案:

问题根因解决方案
OOM崩溃 Grafana调用/api/v1/series?{le!=""}导致Prometheus无限消耗内存OpenAIPrometheus提交补丁,为该API强制加上Context超时
WAL重放慢 Prometheus并发重放时过度使用所有CPU核心,在高核数服务器上因锁争用性能崩溃设置GOMAXPROCS=24限制并发度,重放速度显著提升
指标数据过多 kube-prometheus默认采集了大量不实际使用的细粒度指标通过Prometheus relabel_config规则丢弃不需要的指标

创新工程实践

除了解决上述问题,OpenAI还构建了多项具有行业参考价值的创新机制。

GPU健康检测:Preflight系统

问题背景: GPU故障不总是以DCGM可以捕捉的错误码形式出现,部分GPU问题需要独占运行测试程序才能发现。

架构设计:

被动健康检测(Passive Healthcheck): 持续运行的后台检测,包含:

  • 基础系统资源(网络可达性、磁盘健康)
  • GPU XID错误(通过DCGM导出DCGM_FI_DEV_XID_ERRORS指标进入Prometheus
  • 云厂商维护事件(VM即将重启或迁移的预警)

检测到异常时自动Cordon节点,严重故障则触发Pod驱逐。超过7SLA后强制销毁虚拟机。

主动GPU测试(Active GPU Test): 节点首次启动时运行完整GPU验证套件(Preflight),确保硬件和驱动行为符合预期。此后通过CronJob周期性对随机节点进行抽样测试,覆盖DCGM无法捕捉的潜在问题。

团队资源管理:Team Taint机制

问题背景: Kubernetes原生没有类似Slurm的公平调度队列机制,研究团队难以公平获取所分配的算力配额。

解决方案: 开发team-resource-manager服务,基于ConfigMap中声明的(节点选择器, 团队标签, 配额数量)三元组,动态为节点打上openai.com/team=<teamname>:NoScheduleTaint。结合Admission Webhook,在作业提交时自动按提交者的团队成员身份注入对应的Toleration,实现了轻量级的多团队隔离。

低优先级的跨团队借用容量也得以支持:低优先级Pod携带any容忍度,可以调度到任意团队的节点上,但正式作业可随时抢占。

气球部署:防止空闲节点被缩容

问题背景: OpenAI使用cluster-autoscaler动态扩缩容,但空闲节点会被自动缩容,而VM重新启动需要较长时间(冷启动延迟),影响作业快速调度。

解决方案:CPUGPU主机各创建一个"Balloon Deployment",副本数等于集群最大容量,每个副本是一个低优先级、占位Pod,确保自动扩缩容器认为所有节点均处于使用状态而不触发缩容。当真实作业到来时,调度器直接抢占并驱逐这些低优先级气球Pod

关键细节: 使用Deployment而非DaemonSet(避免被计为节点活跃负载),并配置Pod anti-affinity确保气球Pod均匀分布到所有节点上。

协同调度:解决Gang Scheduling死锁

问题背景: MPI训练任务要求StatefulSet中所有成员Pod同时运行才能开始工作。若两个作业各自申请100%集群容量,Kubernetes默认调度器可能各调度一半,导致双方都无法运行,陷入死锁。

解决方案: 采用Kubernetes 1.18引入的调度器插件架构,集成Coscheduling Plugin,实现Gang Scheduling语义:只有当一个作业的所有Pod都能被调度时,才实际调度该作业,否则等待。这避免了资源被部分占用导致的全局死锁。

架构全景回顾

下图展示了OpenAI7500节点规模下Kubernetes集群的核心架构与创新组件分布:

关键经验总结

OpenAIKubernetes大规模实践为业界提供了以下值得借鉴的经验:

领域核心经验
存储etcd必须使用本机SSDEvents应独立集群,及时扩大存储配额
API ServerEndpointSlices是大集群必备,避免DaemonSet直接监听API Server
网络在大规模场景下原生Pod网络优于Overlay,调整ARP缓存阈值
监控Prometheus需限制/api/v1/series资源消耗,控制GOMAXPROCS
GPU管理结合被动(DCGM)和主动(Preflight/CronJob)检测,节点入场验证不可省略
资源隔离Team TaintResourceQuota更灵活,适合研究型多团队场景
调度稳定性Gang Scheduling是多Pod协作训练任务的刚需,避免资源死锁
弹性扩缩容气球部署可有效防止自动缩容引入的VM冷启动延迟

参考资料