2. 数据存储层集成
机器学习工作负载对存储的需求从来不是单一的。数据摄取阶段需要高吞吐、低成本的对象存储;单机训练需要低延迟、高IOPS的块设备;多节点共享训练需要并发可写的文件系统;而大规模分布式训练又要求存储层能够提供数百GB/s的聚合带宽。AWS 提供了四类核心存储服务来覆盖这些场景:S3、EBS、EFS 和 FSx for Lustre。理解它们的定位差异,并掌握在 SageMaker、EC2 训练实例上的实际挂载方式,是构建高效 ML 数据平台的基础。
四类存储的本质差异
S3 是对象存储,数据以 key-value 形式存放,通过 HTTP API 访问,天然支持无限容量和 11 个 9 的持久性,是数据湖的事实标准。EBS 是块存储,挂载到单台 EC2 实例后表现为一块裸磁盘,提供稳定的 IOPS 和低延迟,但同一时刻只能挂载到一个实例(io2 多挂载等特例除外)。EFS 是托管的 NFS 文件系统,可被成百上千个 EC2 实例或容器同时挂载,适合共享代码、检查点和中小规模数据集。FSx for Lustre 是高性能并行文件系统,专为 HPC 和分布式训练设计,能够与 S3 建立数据仓库链接,实现按需加载和结果回写。
S3 数据湖的访问模式与优化
在 ML 工作负载中,S3 通常作为数据湖的底座。训练任务读取 S3 数据有两种主流方式:一是通过 boto3 或 SageMaker SDK 在 Python 中按需下载;二是通过 s3fs 或 Mountpoint for Amazon S3 将存储桶挂载为本地文件系统。前者适合小批量、随机访问的场景,后者适合需要 POSIX 接口的框架(如 PyTorch DataLoader 直接读取文件路径)。
需要注意的是,S3 的 GET 请求有延迟,单流吞吐受限于单连接带宽。当训练任务需要读取数万个小文件时,逐个 GET 会产生大量请求开销。此时应使用 S3 的批量操作或先通过 AWS DataSync、DistCp 将数据同步到 FSx for Lustre,再让训练任务从 Lustre 读取。另一个关键优化是合理设置 S3 前缀分区,避免请求热点。例如将 s3://bucket/dataset/year=2024/month=01/day=15/ 作为分区路径,使 GET 请求分散到不同分区上。
EBS 在单机训练中的角色
EBS 卷挂载到 EC2 后,表现为块设备。对于单机训练,EBS 通常承担三类职责:存放操作系统和训练框架、作为本地缓存加速数据读取、以及存放临时检查点。gp3 卷默认提供 3000 IOPS 和 125 MB/s 吞吐,可独立调整至 16000 IOPS 和 1000 MB/s,适合大多数训练场景。io2 Block Express 则提供更高的 IOPS 和更低的延迟,适合对随机读写敏感的小文件训练。
挂载 EBS 的标准流程是:创建卷并附加到实例后,使用 lsblk 确认设备名(如 /dev/nvme1n1),然后格式化并挂载。以下是一个典型操作序列:
# 确认新卷设备名
lsblk
# 格式化为 ext4(仅首次使用)
sudo mkfs -t ext4 /dev/nvme1n1
# 创建挂载点并挂载
sudo mkdir /mnt/data
sudo mount /dev/nvme1n1 /mnt/data
# 验证挂载与可用空间
df -h /mnt/data
如果希望实例重启后自动挂载,需要将设备 UUID 写入 /etc/fstab。使用 blkid 获取 UUID 后添加一行:UUID=xxxx /mnt/data ext4 defaults,nofail 0 2。其中 nofail 选项确保卷不可用时实例仍能正常启动。
EFS 的共享挂载实践
EFS 适合多实例共享同一份数据的场景,例如多个 SageMaker 训练作业共享代码仓库、多个推理容器共享模型文件。EFS 的挂载需要先创建挂载目标(Mount Target),每个可用区一个,然后通过 NFSv4 协议挂载。挂载命令格式为:
sudo mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 \
fs-0123456789abcdef0.efs.us-east-1.amazonaws.com:/ /mnt/efs
其中 rsize 和 wsize 设置为 1MB 可以提升大文件传输效率,hard 确保 NFS 请求在超时后持续重试而不是返回错误。EFS 的性能模式分为通用型和 Max I/O,前者延迟更低,后者吞吐更高但延迟略高。对于训练场景,如果主要是顺序读取大文件,Max I/O 更合适;如果涉及大量元数据操作(如遍历目录),通用型更优。
FSx for Lustre 与 S3 的联动
FSx for Lustre 的核心价值在于两点:一是提供亚毫秒级延迟和数百 GB/s 的聚合带宽,二是支持与 S3 建立数据仓库链接。创建文件系统时指定 S3 桶路径,Lustre 会自动将 S3 对象的元数据导入,训练任务首次访问某个文件时,Lustre 从 S3 按需加载数据到文件系统;训练结束后,可以通过 hsm_archive 命令将结果回写到 S3。
挂载 Lustre 文件系统的命令如下:
sudo mount -t lustre -o noatime,flock \
fs-0123456789abcdef0.fsx.us-east-1.amazonaws.com@tcp:/fsx /mnt/fsx
其中 flock 选项启用文件锁,对于 PyTorch DistributedDataParallel 等需要文件锁的框架是必需的。挂载后,训练脚本可以直接将 /mnt/fsx 作为数据目录,框架会以本地文件系统的方式访问数据,而底层由 Lustre 负责从 S3 拉取。
选型决策与组合策略
实际生产环境中,四类存储往往组合使用。一个典型的分布式训练流水线可能是:原始数据存放在 S3 数据湖中,通过 DataSync 或 Lustre 链接同步到 FSx for Lustre;训练实例挂载 Lustre 作为主数据源,同时挂载 EBS 作为本地缓存和临时目录;检查点和最终模型写入 EFS 或直接回写 S3。这种组合兼顾了 S3 的低成本持久化、Lustre 的高吞吐、EBS 的低延迟和 EFS 的共享便利。