思谋科技:构建易于运维的 AI 训练平台

2023-08-04
孙冀川

伴随着公司业务的发展,数据量持续增长,存储平台面临新的挑战:大图片的高吞吐、超分辨率场景下数千万小文件的 IOPS 问题、运维复杂等问题。除了这些技术难题,我们基础团队的人员也比较紧张,负责存储层运维的仅有 1 名同事,因而组件的易用性,一直也是我们评估的重要维度。

我们尝试过文件系统包括有 NFS、GlusterFS、Lustre 和 CephFS,最终选择了JuiceFS。在这个案例中,我们将为大家介绍工业 AI 平台的存储层的挑战有哪些、 JuiceFS 的应用场景、大规模数据场景为什么使用 SeaweedFS?以及 JuiceFS CSI Driver 使用中遇到的问题。希望这些分享能给社区用户提供一些选型和运维方面的参考。

01 AI 训练平台的存储挑战 

思谋科技的业务主要面向工业场景,涵盖工业质检、智能制造和流程优化等领域。我们的团队主要负责 AI 平台的训练场景,并为所有业务线提供训练平台支持。我们管理整个公司的 GPU 训练集群。平台中处理的数据有如下特点:

  • 单个项目的数据量很小,缓存收益高,优选带缓存的文件系统。在工业场景中,与人脸识别或自然语言处理等场景相比,数据量小。一个客户可能只提供了几百张图像,我们需要利用这些图像来迭代出模型。项目图片少,就有利于我们做本地缓存,所以支持本地缓存的文件系统 JuiceFS,BeeGFS 等,在我们的首要选择列表里。
  • 图像大小没有统一的规格,大小文件均存在。由于我们处于工业场景,不同的工厂、产线与相机产生的图片是千差万别的。例如,我们使用线扫描相机收集的图片、或者 BMP 格式的图像大小很大,几百MB甚至GB,而其他相机拍摄的视频或照片可能只有几k大小。所以我们既要面临大文件的吞吐问题,还要面临海量小文件的 IOPS 问题。
  • 数据量与文件数增长速度非常快,元数据压力大。我们曾与产品经理进行容量预估,发现一个项目在短短一周内就需要处理几十T的数据务。另一个场景,超分辨率领域的数据集具有一个典型的特点,即将视频转化为图片。因此一个视频可能会生成上百万、上千万个文件,文件个数非常大。文件个数对于文件系统元数据压力也很大。因此,我们训练平台对存储平台的容量,以及元数据长时间临界状态的稳定性有很高的要求。
  • 同时,由于我们是自建IDC,没有使用云,所以存储系统运维与扩容是否便捷,也是我们的首要考虑点。

02 存储选型:不只是功能与性能 

为了解决上述问题,我们对一些文件系统进行了评估,包括 NFS、GlusterFS、Lustre 和 CephFS 等,最终选择了 JuiceFS。由于我们团队成员较少且需要快速支持业务上线,我们并没有足够的时间进行选型验证和上线周期的评估,我们对于新组件的测试和上线需要更高效快捷。

当进行产品选型时,不仅需要评估功能和性能,还需要考虑中长期成本、与业务方的沟通等因素,是一个很综合的复杂任务,因此,我们总结了一些选型经验和教训与大家分享:

  • 首先是成本、可靠性和性能之间的权衡。除非公司有充足的资金,否则只能在成本、可靠性和性能之间尽可能满足其中两个因素,而不可能同时满足三个。在成本受限的情况下,我们建议将数据安全性放在高于性能的位置

    通过维护多个集群的经验,我们得出一个观点:性能达到可接受水平即可,不必追求过高的性能。我们对存储总体拥有成本(TCO)的理解是,并非只涉及购买容量和性能方面的价格,而是指越接近资源利用上限的使用,实际持有成本越低。花了大价钱,买了很高的性能,但是却用不上,其实也是一种浪费。
  • 第二点,要尽早让内部的用户接入,因为技术和业务工程师之间存在信息差。举个例子,我们在上线第一套存储系统后遇到了大量用户的投诉。我们最初简单地理解离线训练任务,无论是训练任务还是处理大数据,都是为了实现高利用率和高吞吐。然而,实际情况是用户非常敏感于延迟。任务完成时间,可以参考网易云音乐AI 的这篇: 《网易云音乐机器学习平台实践》 。因此,我们建议需要尽早与用户沟通,了解他们的需求和反馈,以弥补这种信息差。
  • 第三点做好平台一致性,不光是环境一致性,做好也要做到任务运行的一致性。举一个具体例子,大型图片任务在网络上占用了大部分带宽(大象流),从而影响了小型图片任务的完成时间。即使是相同配置的机器,小图片任务完成的时间也会加倍。用户会抱怨为什么在另一台机器上只需要3个小时,而在这台机器上需要6个小时。因此,最好对每个任务都进行 QOS 等机制的限制,以防止出现该种情况,对用户造成使用困扰。
  • 除了以上三个要点外,还有一些小的注意事项。选择具备丰富配套工具和良好集成生态的产品,而不仅仅看文档的数量。我们测试了许多商业存储,但发现它们的文档与其版本也有不匹配的现象。因此,我们更倾向于选择周边工具多的产品,例如Debug工具,监控工具等,因为相比依赖于他人,自己掌握更为可靠。我们选择 JuiceFS 的原因之一是它是少数带有性能调试工具的文件系统——JuiceFS stats 与access log 功能。此外,JuiceFS 还对接了持续剖析平台 Pyroscope,提供持续查看垃圾回收时间以及占用内存较大的块的功能,这可能是许多人不常使用但非常实用的功能。
  • 与用户进行沟通时,使用对方易懂的“用户语言”而非 “技术语言”。在我们交付产品时,我们提到在 IO Size 256k 的情况下,我们可以实现每秒 5GB 的带宽,跑满了网卡上限。然而,实际情况是算法用户并不清楚这个概念。当时我们不知道如何向用户解释。后来,是JuiceFS社区的一篇博客文章:《如何借助 JuiceFS 将 AI 模型训练速度提升 7 倍》,给我们带来了启发。在这篇博客中展示了在 JuiceFS 上使用 ResNet50 模型和 ImageNet 数据集进行训练的完成时间,并与其他文件系统进行了对比。这样的比较,让算法用户更容易理解和评估 JuiceFS 的性能。随后,我们告诉了用户我们新存储平台上,ResNet 50 配合 ImageNet 训练的一些数据。在我们提供了这个对比数据后,我们与内部用户的沟通变得非常顺利,因为算法同学也希望能够加速训练过程。更短的训练时长使他们能够调整更多参数、进行更多的尝试并生成更好的模型。
  • 对于一个大平台,很难在测试场景下模拟所以的使用场景。我们需要先完成,再不断完善。例如上线后,我们发现用户的使用方式并不完全符合我们的预期,他们不仅仅存储数据集,还将anacond等环境安装在存储系统上。这些库都是小文件,而是对时延要求特别高,如果没有缓存到本地,运行性能是无法接受的。而这种场景,在我们测试过程中,是不会考虑到用户会将环境安装到存储里,因为在我们的思维里,大部分的环境都应该使用容器镜像。所以,一定要尽早的扩大测试范围,让更多的用户参与测试与实际使用,这样才能暴露更多的问题。
  • 关于全内存元数据存储:如果元数据过大,意味着这台机器很可能无法完成混部。机器的持有成本非常高,同时一定要测试长时间临界状态下的稳定性。

03 为什么使用 SeaweedFS 作为 JuiceFS 的底层存储 

在我们的存储层中,SeaweedFS 也是一个必不可少的重要组件,并且在以往的社区分享中,对于 SeaweedFS 的介绍比较少,因此在介绍 JuiceFS 的应用场景前,我们需要一些篇幅来介绍为什么会引入 SeaweedFS。

原因一:我们团队没有人具备 Ceph 背景。不同于一些社区案例,如中国电信选择的 ceph (电信案例:JuiceFS 在中国电信日均 PB 级数据场景的应用)。

原因二,当文件数量过亿,原有 MinIO + JuiceFS 出现性能下降。我们是在 2021 年开始使用 JuiceFS,当时底层使用的是 Miinio。但是在海量文件的情况下,在XFS 文件系统文件数量超过一亿时,性能开始下降,已经达不到新集群时的水平。我们进行了测试,至少有 30% 的性能损失。

第三点:我们需要一个简单的架构。当时团队只有不到10个人,需要支持各种项目与任务。因此,我们希望有一个简单的架构,以便我们进行运维工作,对于我们小团队来说,简单意味着安全感。我们测试了很多开源和商业存储方案,最终选择了 SeaweedFS。

关于 SeaweedFS SeaweedFS (https://github.com/seaweedfs/seaweedfs)是高性能分布式存储系统,用于存储块、对象、文件和数据湖,可制成数十亿文件。
  • 选择 SeaweedFS,因为它各项功能都可以通过一个简单的命令启动。对于我们的团队来说,它没有屏蔽一些部署、架构等细节,同时我们的开发同学也能对其进行一些修改工作。
  • 第二点, SeaweedFS 是类 Haystack 架构,它将随机写操作聚合成顺序写操作,具有对硬盘友好的特性。虽然现在 HDD 和 SSD 的价格差距不大,但该架构是在 2021 年完成的,当时因为炒币,硬盘价格处于高点。
  • 第三点 Haystack 架构支持小文件合并。合并后的小文件不再受文件数量的限制,不会遇到像 MinIO 那样写入越多性能越差的情况。实际上,MinIO 对小文件有“负面优化”,将小文件拆分为数据文件和元数据文件。在这种情况下,如果再进行EC(纠删码),文件会被进一步拆分。因此,对于大量小文件的使用场景,我们不推荐使用 MinIO。
  • 第四点,SeaweedFS 支持 S3 接入。支持S3就可以很方便的对接JuiceFS,我们当时看了很多案例博客,主要有两篇文章。一篇是 《同城旅行的对象存储》,他们就是改了 SeaweedFS ,给了我们一些信心。以及《京东登月平台》当时使用的小文件存储选择也是 SeaweedFS。
  • SeaweedFS 的一些不足之处是资料相对较少,文档不太丰富。如果想了解某些功能,需要直接查看源代码。另外,社区的维护相对薄弱,边缘功能存在一些使用问题。在我们的实际应用中,我们发现只有 IO 功能才能正常使用,例如副本机制是可行的,但副本转 EC 的机制无法正常的使用,目前还在持续研究中。另一个问题是多机房同步,想测试多机房同步与备份,在我们的测试中花费了很长时间也无法使其正常工作。此外,它还有冷热数据转换功能,我们也无法成功测试。这可能是由于我们的对其的了解有限,我们仍在努力解决这些问题。

    我们在选择 SeaweedFS 时权衡了其优点和缺点。总而言之,在进行架构选型时不要过早下结论,尽可能推迟做出选择的时间,多做场景测试,多做小范围灰度测试,以便全面评估和考虑各种因素。做决定的时候,多考虑大局,不要局限于几个文件系统,而要考虑选择某个文件系统后,对团队后续的规划与建设是否有影响等。

04 JuiceFS 在思谋的使用场景 


第一个场景:小容量存储,总容量仅为百万到千万文件,百TB级
。在这种情况下,使用 SSD 的成本并不高, 所以我们采用了 Redis + MinIO(SSD) + JuiceFS。结合 MinIO 和 Redis,你会发现它非常好用,而且日常无需太多关注。我们使用的是单点的 Redis,稳定运行了一年多,从未发生过大型宕机,只要进行好内存监控即可,同时控制好文件个数。

第二个场景:大容量存储,数据规模达到 PB 级。这时候就会面临成本压力,我们必须选择 HDD。我们选择了 SeaweedFS(HDD) + TiKV+ JuiceFS 作为该场景下的解决方案。

第三,多套小集群管理。每个用户都部署了一套JuiceFS,但底层都是使用同一个SeaweedFS。我们当时选择这种方案有两个原因。首先是出于历史原因。我们从 JuiceFS v0.17 开始使用时,当时它并不支持目录限额功能。因此,一些算法工程师占用了大量的目录空间。我们需要限制目录限额,但等待功能更新或自己开发限额功能并不切实际。我们的团队主要负责云原生调度,并没有开发存储系统的经验。

因此,我们想出了一个解决办法,管理多套小集群。我们采用了基于一个 TiKV 和一个 SeaweedFS 的模式,为每个用户提供独立的元数据前缀,并管理多套小集群。这种做法有一个好处,在维护集群时,如果 TiKV 规模足够大,即使其中一半宕机也不会有太大影响。当进行用户 JuiceFS 维护时,实际上不会影响其他用户,但众多的文件系统数量,让这种做法的管理过程比较繁琐。

这种使用方式也给我们带来了一些问题,因为每个用户都拥有一个 JuiceFS 目录,所以在挂载 CSI 时,每个 Pod 都有自己的 CSI。而在容器场景下,容器的密度比物理机和虚拟机场景更高。

随着容器数量的不断增加,重客户端文件系统(JuiceFS 是一个典型的重客户端文件系统,所有逻辑都由客户端处理。)与工作负载之间就会争夺有限的资源(内存),这在我们集群已经成为常态问题。内存是无法压缩的资源,所以内存争抢问题可能导致客户投诉——为什么相同的代码在集群的 A 节点上可以运行,而在 B 节点上却会崩溃?用户会质疑为什么无法集群实现的环境一致性等诸多问题。去查看就会发现是 OOM(内存耗尽)的问题,因为 B 节点的资源竞争更为激烈。目前,我们还没有找到一个很好的解决方案。

在使用中,要注意不同存储组件在 Kubernetes 上的适配性。MinIO + Redis 在 Kubernetes上的适配性非常好,而 SeaweedFS + TiKV在 Kubernetes上的适配性就不太理想。目前,我们还没有找到一个很好的方法将 TiKV 部署在 Kubernetes 中,因为涉及到的事务较多且管理上有些宽泛。我们曾尝试使用 TiDB Operator 来部署 TiKV,但尝试后发现存在k8s版本不适配等许多小问题。

05 一些运维实践心得 

存储组件

首先,Redis 和 TiKV 在非临界状态下的延迟几乎相当。如果没有进行测量,很难看出它们之间的性能差异。在 AI 场景中,当读取操作比写入操作多时,像元数据的 mkdir 和 rename 等操作的性能差距可能非常大,因为需要上锁。但在实际读多写少的场景中,我们在监控中发现 Redis 和 TiKV 的性能实际上差不多。

其次,有时我们需要根据情况做出选择和判断。Redis 的运维相对简单,但存在冗余度和高可用性风险。如果公司对 SLA 卡特别严格,实际上使用 TiKV 可能更合适,因为 Redis 并不是解决这个问题的最佳方案。

第三点,关于 TiKV 的文档。尽管 TiKV 是一个非常 Nice 的开源项目,但其文档也相对较少。文档与 TiDB 官网是一起的,官网会列出所有参数,但没有解释这些参数对系统的影响。你需要逐个尝试来了解它们。

第四点,关于 MinIO 和 SeaweedFS 的易用性。我们在实践中得出结论,MinIO 在易用性和数据冗余方面优于 SeaweedFS。在文件数量较少的情况下,我们强烈推荐使用 MinIO。事实上,我们的有些业务在一些实时性、可用性要求不强的环节中都采用了 Redis + MinIO 的组合。只有在数据量较大时,我们才切换到 TiKV+SeaweedFS 的组合。

JuiceFS CSI Driver

首先,当我们采用 CSI 动态配置时,无法关闭 SubPath 功能。我们的初衷是能够查看文件系统中的所有数据,因此我们当时通过修改 CSI 源代码来关闭 SubPath 功能。

其次,在将系统部署到预生产环境后,我们在短时间内创建了大量的持久卷声明(PVC)并进行挂载,导致系统卡死。经过定位,我们发现在 v0.17.1 版本的控制器中存在 Create/DeleteSubPath 操作,这导致了在控制器容器中同时挂载/卸载多个JuiceFS文件系统,从而导致控制器的容器资源不足并进入假死状态。我们及时通知了CSI的维护者,社区在下一个版本中进行了修复。

第三,就没有部署 TiDB 的 TiKV 集群而言,会导致 TiKV 中的数据没有进行垃圾回收(GC)。因此经常会看到人们在 TiKV 群里询问为什么 TiKV 的容量持续上升而不下降。但是实际上,我们并没有遇到这种情况,可能是因为我们使用了较高版本的TiKV。我注意到JuiceFS的最新版本中也添加了 GC 功能。在 JuiceFS v1.0.0 中,设置了上传/下载限制后,会出现大文件读写超时失败的问题,这导致我们的QOS设置遇到了问题,我们目前采用的还是从网络层面限制,后续会对这里进行优化。

在本次分享中, 并没有分享我们的架构。如果大家对我们的架构感兴趣,可以查看云之声的案例,大家的架构基本上都是相似的,AI 私有化存储方面的差异并不大。

06 未来展望 

首先,处理一下重客户端与任务进行资源争抢的问题。因为如果遇到整机内存超售的情况,尤其是在大型节点和高压力任务下,往往容易导致任务宕机。在今年FAST 23,我们看到了阿里一个解决方案,Fisc: A Large-scale Cloud-native-oriented File System。但对于一般的公司来说,这种方法的实现成本确实非常高。

第二,适配 JuiceFS 的新版本 v1.1,原因是它解决了目录配额的问题。我们目前正在探索是否可以在不迁移的数据的情况下,将多个JuiceFS 合并为一个JuiceFS,并开启目录限额,以此来降低我们的运维压力。

第三,关于 Redis 和 TiKV 的延迟,在非临界状态下它们的延迟相近。然而,TiKV的部署运维非常复杂,鉴于我们在其他项目中使用了 CockroachDB,我们正在考虑是否可以将元数据切换到CockroachDB 上。我们的场景对元数据的性能要求并不是特别高,我们的业务主要是读取操作,写入操作的速度慢并不会影响后续读取操作。

关于思谋科技

思谋科技(SmartMore),成立于2019年,智能制造的持续创新者,以“致力持续创新,创造卓越价值”为使命。目前,思谋已通过自研的智能工业平台、智能传感器产品以及智能一体化设备,服务了卡尔蔡司、空客、博世、佳能、大陆集团、舍弗勒、宝洁、联合利华等来自全球的超过200家行业头部企业,以技术促进更高效、更灵活、更先进智造的发展。

关于作者

  • 孙冀川,思谋科技基础设施团队(Ti Team)负责人,负责计算与存储基础设施平台的设计与维护

视频回顾

相关博客

Conda + JuiceFS :增强 AI 开发环境共享能力

2024-12-04
本文简要分享了在多机环境下,如何利用 JuiceFS 复用 Conda 虚拟环境的具体方法与注意事项。希望这篇文章中的技巧和经验能够为读者的日常开发和团队协作提供帮助,并提升工作效率。我们鼓励感兴趣…

海柔仿真系统存储实践:混合云架构下实现高可用与极简运维

2024-11-08
海柔科技仿真平台的数据特征包括:大量小文件、并发写入、跨云架构等。经过对比 Longhorn、Ceph 等多种系统后选择了 JuiceFS

好未来:多云环境下基于 JuiceFS 建设低运维模型仓库

2024-11-06
好未来基于 JuiceFS 开发了一个模型仓库,支持用户训练过程存储 checkpoint,并且控制面支持用户从各个云环境上传并统一管理模型。通过 JuiceFS CSI 组件,好未来将模型仓库挂载…

JuiceFS CSI:Mount Pod 的平滑升级及其实现原理

2024-10-30
JuiceFS CSI Driver 在 v0.25.0 版本中,实现了 Mount Pod 的平滑升级,即在应用不停服的情况下升级 Mount Pod。