当前位置:首页 > 问答 > 正文

去哪儿网用Kubernetes和Ceph搭建GPU云平台的那些事儿,实践经验分享

(根据QCon全球软件开发大会的演讲内容整理)

大家好,我是去哪儿网的工程师,今天想和大家聊聊我们是怎么把那些昂贵的GPU卡管起来的,也就是用Kubernetes和Ceph搭建GPU云平台的过程,这里面踩了不少坑,也积累了一些经验,希望能给大家一些参考。

我们为什么非要搞这个?

最开始,我们的GPU机器都是谁用谁申请,物理机直接给,这带来了很多头疼的问题,首先就是资源浪费太严重了,一台八卡GPU服务器,可能一个人只用其中一两张卡,剩下的就白白空着,机器又贵,成本压力巨大,环境乱七八糟,每个开发同学用的驱动版本、CUDA版本、深度学习框架版本都可能不一样,装环境就得花大半天,还经常冲突,最后是运维困难,没有统一的平台,出了问题排查起来像大海捞针。

我们的目标很明确:第一,要把GPU资源像切蛋糕一样分给大家用,提高利用率;第二,要给开发同学一个开箱即用的环境,别再折腾装驱动了;第三,要有统一的调度和监控,让我们能看清楚资源到底用在了哪里。

技术选型:为什么是Kubernetes加Ceph?

选Kubernetes几乎是顺理成章的事,当时公司已经在大规模用Kubernetes管理在线业务了,团队对这套东西很熟悉,Kubernetes的调度能力非常强,能帮我们自动把计算任务分配到有资源的GPU节点上,它的生态很好,有现成的设备插件可以用来发现和管理GPU卡。

存储方面是个大难题,AI训练要读写大量的数据,比如图片、模型文件,如果把这些数据都放在每个计算节点本地,管理起来会非常混乱,而且数据共享也是个问题,我们考察了NFS,但担心它可能成为性能瓶颈,最终选择了Ceph,主要是看中它的扩展性和可靠性,Ceph能提供一个统一的存储池,所有GPU节点都能像访问本地硬盘一样去读写数据,容量不够了加机器就能扩容,数据还有多副本,不容易丢。

实践中遇到的“坑”和我们的解决办法

说起来都是泪,理想很丰满,现实很骨感。

  1. GPU资源隔离的“坑” 最开始我们以为用了Kubernetes的GPU插件就万事大吉了,但很快发现,虽然Kubernetes能保证一张卡只被一个任务占用,但无法限制卡上的计算资源和显存使用,一个任务可能把整张卡的显存占满,或者把GPU的计算核心打到100%,导致同节点上其他任务虽然在自己的卡上运行,但因为GPU散热、电源等硬件资源争抢,性能受到严重影响,这就像你和你室友共用一个电闸,他开个高功率的电暖气,你家的灯可能都会变暗。 我们的办法:我们引入了NVIDIA的容器运行时工具包,利用其提供的显存和计算能力限制功能,这样,我们可以给每个任务分配固定的显存上限和计算单元百分比,实现了更细粒度的隔离,避免了“坏邻居”问题。

  2. Ceph性能调优的“坑” 刚上线时,很多同学抱怨训练速度比在本地慢了好多,一排查,瓶颈果然在Ceph存储上,AI训练的特点是会产生大量的小文件随机读写(尤其是读),而默认配置下的Ceph更擅长处理大文件顺序读写。 我们的办法:我们做了很多针对性的调优。更换了更快的SSD硬盘做Ceph的日志盘,提升写入性能。调整了Ceph的底层参数,像filestore max sync intervaljournal max write bytes,让它在处理小文件时更“卖力”,最重要的是,我们在GPU计算节点上部署了Ceph的客户端缓存,把经常读取的热点数据缓存在本地内存或SSD上,大大减少了对后端存储集群的直接访问,训练速度一下子就上来了。

  3. 镜像管理的“坑” AI训练的镜像动辄几十个GB,因为里面包含了各种庞大的深度学习框架和库,这么巨大的镜像在节点间拉取非常慢,严重影响任务启动速度。 我们的办法:我们采用了镜像预热的策略,提前把一些基础的公用的AI框架镜像推送到所有GPU节点上,对于用户自定义的镜像,我们优化了镜像构建,采用分层构建,尽量复用基础层,我们也利用了Kubernetes的镜像延迟删除功能,避免一个任务刚用完,镜像就被删掉,下一个同类任务又要重新拉取。

总结一下

搞这套平台,最大的收获不是技术有多牛,而是真正把资源利用率和开发效率提上去了,我们的GPU利用率有了非常明显的提升,开发同学提交一个训练任务只需要几分钟,环境问题也基本消失了。

回头看,关键点在于:第一,隔离要做好,不能让任务之间互相干扰;第二,存储是生命线,必须花大力气调优,缓存是神器;第三,镜像要瘦身,加快启动速度,这套系统还在不断优化中,比如我们在探索更高效的调度策略,让资源利用率更高,希望我们的这些经验,能给正在或者打算做类似事情的团队一些帮助,谢谢大家。 结束)

去哪儿网用Kubernetes和Ceph搭建GPU云平台的那些事儿,实践经验分享