加速 AI 训推:Lepton AI 如何构建多租户、低延迟云存储平台

Lepton AI 是一款面向开发者的 AI 平台,旨在提供易用、高效且可扩展的基础设施能力。该平台适用于各种训练、推理需求,GPU充足,在保证高性能的同时,能够灵活应对不断变化的工作负载。用户可以快速在 Lepton 平台上部署推理服务和执行训练任务,无需关注基础设施和稳定性问题。

作为一家初创公司,Lepton AI 致力于在云端为企业提供领先的 AI 推理与训练技术,而在存储这类基础设施建设,希望能够在市场上找到合适的供应商,以保障更高效的产品研发。JuiceFS 非常契合 Lepton AI 的需求。基于 JuiceFS,Lepton AI 利用其高性能的缓存机制显著加速了文件操作,显著降低了由于对象存储引发的延迟问题,并与此前使用的 AWS EFS 相比,存储成本降低了 30 到 50 倍。

JuiceFS 最近增加的新特性,按需读取对象存储上已有数据并进行缓存,使得 Lepton 可以不用预先从客户的已有存储复制数据,更加提高了 JuiceFS 的可用性。目前,Lepton AI 在 JuiceFS 上存储的文件规模已达到数十亿个文件,同时 JuiceFS 的性能表现也非常优秀,满足了系统对高吞吐量和低延迟的要求

01 Lepton AI 平台的存储需求

Lepton AI 平台的用户数据主要分为三类:

  • 训练数据,例如大量的图片。这些数据主要是只读的,在训练过程中,我们会从中读取一部分数据进行模型训练。
  • 快照数据(Snapshot),用户在训练过程中会定期保存一些中间结果,以便在出现故障时能够从之前的快照继续训练。例如,若在训练过程中出现 GPU 故障,用户可以从最近的快照恢复并继续训练。此类数据通常是只写的,只有在保存快照时进行写入,读取则较为有限。
  • 训练出来的模型数据,这些模型在训练完成后主要是读取,完成写入操作后一般不会进行修改,因此这类数据也是以写为主,读取较为频繁,但修改操作较少。

针对以上这些需求,对存储系统提出的挑战如下:

应对不稳定的 GPU :Lepton 的客户主要使用 H100 GPU,但这一型号的 GPU 存在较大的不稳定性。GPU 出现故障后,需要将整台机器下线进行修复,无论是更换 GPU 卡还是更换与 GPU 相关的其他组件。修复过程中,机器无法访问磁盘,因此无法像传统的分布式存储系统那样简单地进行数据存储。这会导致大量数据的移动和备份问题,增加了数据丢失的风险。

数据迁移问题:我们服务的很多客户会直接要求迁移大量数据到我们的系统。然而,直接将海量数据复制到我们平台并不现实,尤其是当客户有成千上亿个小文件时。例如,我们曾有一个客户,文件数量高达数十亿个,文件复制速度非常缓慢。由于这种数据迁移的高耗时,我们无法要求客户先完成数据迁移再开始使用我们的平台。实际上,很多客户更倾向于先试用平台,确认其效果后再决定是否进行全面的数据迁移。

多租户问题:在多租户环境下,客户的 GPU 分布在不同的位置和数据中心。我们在美东、美西以及欧洲等地区均有数据中心,这导致不同区域之间的延迟较大。如果使用传统的大型文件系统,这将使得多租户管理变得尤为复杂。需要解决的数据隔离、访问控制和延迟问题,增加了存储系统的设计复杂性。

数十亿小文件的读写性能问题:存储大量小文件时,读写性能会受到严重影响。由于每个小文件的访问时间较短,存储系统需要处理大量的文件操作,这会大大降低整体的读写效率。因此,如何高效处理数十亿小文件的存储和访问,成为系统设计中的一大挑战。

02 存储架构设计与选型

存储架构设计

为了解决这些问题,我们理想中的存储架构是这样的:

  1. 云存储与本地缓存结合:我们将数据存储在云端,使用本地磁盘作为分布式缓存。这样可以避免 GPU 故障导致的磁盘不可读问题,并提升系统的整体稳定性与性能。

  2. 支持多租户环境:为每个客户创建独立的文件系统,允许在各自的文件系统中调整性能,简化安全性管理。由于每个文件系统对应一个独立的用户,彼此无法访问,安全性得到保障。

  3. 提高读性能:本地磁盘作为分布式缓存,提高读性能。

  4. POSIX API 兼容性:我们需要 POSIX API,以便用户的代码无需迁移,可以直接在我们的平台上读取数据。

我们评估了现有的开源系统及一些服务商,最终发现 JuiceFS 完全符合我们的需求,而且 JuiceFS 的表现稳定,价格也非常合理。

费用比较:AWS EFS vs JuiceFS

我们最初尝试过 AWS EFS,并对比了 EFS 与 JuiceFS 的价格。存储方面,JuiceFS 将数据存储到 object store 中,价格大约是 EFS 的十分之一,明显更便宜。至于数据传输,EFS 在 AWS 内部有固定费用,而数据出 AWS 则另行收费。但随着规模的扩大,我们的大部分 GPU 并不在 AWS 中,而是外部租用的数据中心中。因此,EFS 的数据进出费用变得非常昂贵。

相比之下,使用 JuiceFS 让我们可以自主选择后端对象存储。我们选择了 Backblaze 和 Cloudflare,它们不收取数据传输费用,因此整体成本比使用 EFS 低了30 到 50 倍

03 在 Kubernetes 中使用 JuiceFS 的实践技巧

CSI 还是 HostPath?

我们最初使用 JuiceFS 时遇到的第一个问题是,JuiceFS 支持两种设置方式:CSI 和 HostPath。为了处理分布式缓存问题,如果使用 CSI,客户端将运行在 Kubernetes 的 pod 中,并且当 pod 生命周期结束时,缓存的数据将无法读取。因此,我们认为使用 HostPath 更为合适。

我们选择将 JuiceFS 挂载到 GPU 机器的某个路径上,并设置分布式缓存。这样,当 Kubernetes 启动 pod 时,Pod 可以直接挂载该路径并访问 JuiceFS 中的数据。与此同时,我们在启动 pod 时也为多租户环境做了一些隔离措施。

JuiceFS 如何挂载到主机上?

我们的做法是在 Kubernetes 中创建了一个 CRD,叫做 LeptonNodeGroup。这个 NodeGroup 是一个 GPU 集群,与 Kubernetes 集群不同,它的功能相对较小。例如,一个客户在我们的平台上租用了 1000 张 GPU 卡,这 1000 张卡位于同一个数据中心。我们会为这 1000 张卡创建一个单独的 CR,其中存储了这些 GPU 的配置,包括 JuiceFS 的相关配置。

我们使用了一个 DaemonSet 来挂载 JuiceFS。这个 DaemonSet 中的每个 Pod 都运行在特权模式下,它会监视 LeptonNodeGroup。当发现该 LeptonNodeGroup 中的 JuiceFS 配置发生变化时,Pod 会通过 setns 系统调用进入到节点的命名空间,并通过 systemd 来挂载 JuiceFS。我们已经运行了这个方案超过一年,结果表明系统稳定且易于使用,整体表现良好,除了少数小问题外。

数十亿小文件处理

如前所述,我们需要处理大量的小文件,其中有几个客户提供了几十亿个小文件。虽然我们知道使用大文件会更高效,但客户的需求使得我们不得不处理这些小文件,且我们无法选择客户的数据格式。经过测试,我们发现如果直接将这些文件复制到 JuiceFS 中,几乎不可能在合理的时间内完成。

JuiceFS 提供了一个导入功能,能够直接从客户原先存储在 S3 上的小文件中导入数据,速度非常快。然而,对于处理几十亿个文件来说,这个速度仍然不够快。在 S3 中,文件名的导入过程可能需要一天时间,尽管通过一些优化手段,时间可以缩短至大约十个小时。如果不进行任何优化,整个过程可能需要 3 到 5 天。

为了解决这个问题,我们尽量将 JuiceFS 的元数据服务与我们的 GPU 机器部署在同一数据中心,以减少延迟。我们花了一些时间来解决 GPU 机器的不稳定问题,因为我们无法在自己的集群中仅依赖 CPU 机器,所以选择从其他厂商租赁机器,并通过调整网络拓扑,最终在同一数据中心找到了合适的机器。虽然这些机器不是通过内网连接,但性能和延迟仍然非常低,能够满足需求。

此外,在与 JuiceFS 团队的讨论后,他们实现了 lazy load 功能,使得在导入文件时,不需要先将所有文件和元数据加载进来就可以直接使用。这个功能是最近几个月才推出的,我们还没有对其进行详细测试,但初步感觉它能够有效地提升效率。

性能表现

我们公司已经使用 JuiceFS 一年多了,整体使用效果不错,虽然我们没有进行详细的性能测试,但客户的反馈比较满意。我们测试性能使用的 GPU 集群有 32 个节点,每个节点配备 8 张 H100 卡,共计 256 张卡。

在单台机器上读取数据时,性能大约可以达到 2 GB/s。这个性能主要受限于机器的带宽,我们的带宽为 40 Gbps,但还跑了一些其他任务,因此实际速度为 2 GB/s 左右。

在延迟方面,P99 延迟通常控制在 10 毫秒以内,平均延迟大约为 3 到 5 毫秒,因为访问元数据服务器时会增加约 2 毫秒的延迟。对于训练来说,这个延迟基本上是可以接受的,用户可以顺利地进行数据读取。

写入性能方面,能够达到 1 GB/s,但有时会受到对象存储延迟和吞吐量的限制。

03 未来计划

我们计划继续优化存储流程,进一步自动化现有的操作,以支持更多的多租户用户。目前,一部分流程已经实现了自动化,但仍有一些操作是手动完成的。例如,创建对象存储的 bucket 目前是手动完成的,而在 JuiceFS 中的文件系统创建过程中,有些步骤已经实现了自动化。我们还需要进一步完善自动化流程。

另外,使用 JuiceFS 后,我们面临分布式缓存稳定性的问题。由于 GPU 故障需要下线修复,这会导致数据需要进行重新平衡。为了避免数据重新平衡,我们需要将数据存储为多个副本。但存储多份数据会占用更多的磁盘空间,且有时可能导致空间不足。如何解决这个问题,目前我们还在探索中。

希望这篇内容能够对你有一些帮助,如果有其他疑问欢迎加入 JuiceFS 社区与大家共同交流。