记一次解决用AMI首次启动的AWS EC2实例的 EBS Volume 访问慢的问题

问题缘起

最近在 AWS 上部署深度学习模型时,遇到了一个让人困惑的现象:明明是配置很高的 EC2 实例,为什么从AMI Launch之后,首次加载模型的速度出奇地慢(花了我半个多小时,一般整个推理也不到1分钟)?更奇怪的是,第二次加载时速度就恢复正常了。这个问题困扰了我好一阵子,直到深入研究 AWS 的技术文档才恍然大悟。

问题排查

通过查阅 AWS EBS 的技术文档,终于找到了问题的症结所在。原来,当我们从 Snapshot 创建新的 Volume 时,AWS 采用了一种"延迟加载"的机制:存储块并不会立即从 Amazon S3 完整下载到 Volume,而是在首次访问时才会触发下载。这种机制虽然能让 Volume 创建过程变快,但代价就是首次访问时会遇到明显的延迟。

正如 AWS 文档所说:

对于从 Snapshot 创建的 Volume,存储块必须从 Amazon S3 拉取并写入到 Volume 中,然后才能访问它们。这个预加载动作需要时间,会导致首次访问时 I/O 操作的延迟显著增加。
参考

解决方案

既然找到了原因,解决方案就很明确了:我们需要提前预热(Pre-warm)这个 Volume。说白了,就是在正式使用之前,先触发一次完整的数据读取,让所有数据块都预先加载到位。

这里介绍两种预热方法:

方案一:使用 dd 命令(简单但稍慢)

这是 Linux 系统自带的命令,用起来直截了当:

sudo dd if=/dev/nvme0n1 of=/dev/null bs=1M

方案二:使用 fio 工具(推荐,更快更强大)

fio 需要先安装,但功能更强大:

sudo fio --filename=/dev/nvme0n1 --rw=read --bs=1M --iodepth=32 --ioengine=libaio --direct=1 --name=volume-initialize

安装方法:

  • Amazon Linux:sudo yum install -y fio
  • Ubuntu:sudo apt-get install -y fio

fio 命令看起来参数不少,我们来一一解读:

  • --filename=/dev/nvme0n1:指定要预热的设备
  • --rw=read:只读模式
  • --bs=1M:每次读取block size为 1MB
  • --iodepth=32:并行处理 32 个请求
  • --ioengine=libaio:使用异步 I/O
  • --direct=1:直接读取,绕过系统缓存

如何监控预热进度?

预热过程可能持续几分钟到几小时不等。这里分享两个监控方法:

  1. fio 命令中加入 --status-interval=1 参数,每秒显示进度:
sudo fio --filename=/dev/nvme0n1 --rw=read --bs=1M --iodepth=32 --ioengine=libaio --direct=1 --name=volume-initialize --status-interval=1
  1. 另开一个终端窗口,用 iostat 命令监控:
sudo iostat -x nvme0n1 1

注意事项

在动手操作前,有几点需要特别注意:

  1. 确认设备名称:使用 lsblkdf -h 仔细核对设备名,就像确认钥匙是否对应正确的锁。

  2. 谨慎处理 Root Volume:如果是根目录所在的 Volume(/),要格外小心,确保只执行读取操作。

  3. 耐心等待:预热时间取决于几个因素:

    • EC2 的网络带宽
    • Volume 的 IOPS 配置
    • Volume 的大小

知识要点总结

  1. 为什么选 fio

    • 支持多线程,速度更快
    • 异步 I/O,效率更高
    • 进度监控更直观
    • 可配置项更丰富
  2. 最佳实践

    • 从 Snapshot 创建新 Volume 后,最好立即进行预热
    • 选择业务低峰期进行预热
    • 可以将预热步骤加入系统初始化脚本
  3. 收益

    • 消除首次访问的性能延迟
    • 提供稳定一致的 I/O 性能
    • 改善用户体验

结语

这个问题的解决过程,让我对 AWS EB预热这个解决方案虽然简单,却能带来立竿见影的效果。

希望这篇文章能帮助遇到类似问题的同学。

posted @ 2024-11-05 22:28  LexLuc  阅读(12)  评论(0编辑  收藏  举报