目录
当您的 CI 在 AWS 上耗时过长时,问题可能出在 EBS 上
你在 EC2 服务器上运行测试套件或 Docker 镜像打包,速度却异常缓慢。
- Docker pull 仅验证已下载的镜像就耗时 15 分钟,而实际下载仅用了 1 分钟。
- Apt 或 dnf 安装又需要 15 分钟。
- Pip install 或 conda install 耗时更久。
这是一台内存充足的高速机器 —— 实际上,您可能正是因为 Travis CI 或 Circle CI 构建器性能不足而特意选择了定制机器。然而,即便如此,任务完成依然耗时漫长。
为什么?
很可能问题出在您的 EBS 磁盘的 IOPS 上。
IOPS 成为瓶颈
您的 EC2 虚拟机配备了一块虚拟硬盘,通常是 AWS 的 EBS 卷。这些硬盘每秒的I/O操作次数(“IOPS”)有限,即每秒的读写次数受到限制。
对于默认的通用型 gp2 磁盘类型,存在两个限制:
- 标准 IOPS 为每 GiB 存储提供 3 次 IOPS,无论卷大小如何,最低保证 100 IOPS。例如,一个 100GiB 的 EBS 卷将实现 300 IOPS;而一个 500GiB 的卷则能达到 1500 IOPS。
- 突发 IOPS 为 3000。
突发 IOPS 的运作机制是,您会获得 540 万信用额度,该额度以每秒 3000 的速度被消耗。一旦信用额度耗尽,您将回到最低 IOPS 水平,随着时间的推移,信用额度会逐渐恢复。(具体详情可参阅 AWS 文档)。
对于应用服务器而言,这一机制运作良好:一旦应用程序启动运行,便不会进行大量 I/O 操作。然而,对于持续集成(CI)工作负载 —— 如测试和打包 —— 有限的 IOPS 可能会成为性能瓶颈。
当你下载 Docker 镜像、操作系统包或 Python 包时,会进行大量的磁盘 I/O 操作。这些包被写入磁盘,随后又被重新读取,接着被解压,大量小文件被写入磁盘。所有这些操作累积起来相当可观。
几个并发的 CI 运行可能会耗尽你所有的突发 IOPS—— 如果你有一个 100GiB 的硬盘,你的 IOPS 会突然从 3000 降至 100。现在安装软件包所需的时间可能会延长多达 30 倍,因为磁盘的读写速度大幅下降。
诊断
通常来说,如果您的 EBS 卷容量较小(因为其 IOPS 会较低),这个问题更有可能发生。如果软件包安装特别缓慢,您可能会察觉到这一情况正在发生。
但你也可以明确地进行检查。
在 AWS 控制台的 EC2 部分,进入 “卷” 选项,查看特定卷的 “监控” 标签页。其中一张图表名为 “突发余额”。若该余额已趋于平稳并显示为 0%,则意味着当前您已无信用额度可用,正在以最低的 IOPS 运行。
解决问题
针对现有的 EBS 卷,最简便的解决方法是扩大您的 gp2 卷容量。例如,500GiB 将提供 1500 IOPS,相比 100GiB 时的 300 IOPS,这是一个更为合理的最低值。其他解决方案包括:
-
您可以切换至 io1 类型的 EBS 卷,它具备可配置的专用 IOPS,但仅为了运行测试,可能不值得承担这一额外成本。
-
您可以转而使用本地实例存储。某些 EC2 实例配备了专用的 NVMe SSD 存储,提供远高于此的 IOPS,例如 c5d 或 m5d 实例。
若您的测试套件在 EC2 上运行异常缓慢,请务必排查此问题。我曾见证一个 Docker 构建过程从超过一小时(具体时长不明,因当时已超时未完成)缩短至仅需 15 分钟 —— 而诊断并解决该问题仅占用您 5 分钟时间。