更新于 2025 年 5 月 8 日 • 作者: Fog Dong 和 Sherlock Xu
您在 Kubernetes 上启动了一个 Llama 3.1 8B 容器,但启动却花费了 10 分钟。为什么?显然,容器基础设施在 GenAI 工作负载下表现不佳。
快速冷启动对于确保您的部署能够快速响应流量变化而不会出现大量延迟至关重要。通过按需启动实例,您可以动态扩展并避免过度配置计算能力。这种响应性在保持高水平服务的同时降低了成本。
认识到这一点,我们彻底重新设计了 LLM 冷启动策略,从拉取镜像到将模型权重加载到 GPU 内存。最终,我们开发了一种解决方案,实现了 25 倍的冷启动速度提升,并支持真正的按需模型加载。
* 确切的 LLM 冷启动持续时间可能因您的网络或磁盘带宽、GPU 性能和模型大小而异。
在这篇博文中,我们将分享我们是如何做到的。首先,让我们看一些基本问题。
用于服务 GenAI 工作负载的容器通常比简单的 Web 应用程序容器大得多。例如,一个 Llama 3.1 8B 容器可能包含
这将总大小增加到 20.2 GB,在许多情况下,随着模型大小的增长还会更高。相比之下,一个 python3.10-slim 容器可能只有大约 154 MB。
在 LLM 容器部署的上下文中,冷启动意味着 Kubernetes 节点之前从未运行过此部署。因此,它没有本地容器镜像,并且必须从头下载和初始化镜像层。
相比之下,热启动意味着节点之前已经加载过模型或构建过容器镜像。在这种情况下,容器镜像已缓存在节点上,并且模型文件可能在页面缓存中可用。
容器镜像由多个压缩层组成,每个层通常以压缩 tarball(例如 gzip
或 zstd
)的形式存储在注册中心(例如 Docker Hub)中。此外,镜像还包含一个 JSON 清单,列出了其层、基础镜像和配置详细信息。
这种分层架构虽然对于版本控制和共享公共组件很有效,但在扩展以容纳大型 AI 模型时会带来挑战。让我们详细分解一下 LLM 容器在 Kubernetes 上启动时究竟发生了什么。
对于 Llama 3.1 8B,冷启动时间线可能如下所示
Deployment Timeline: Image Pull: 5–6 min ███████ Layer Extract: 3–4 min ████ Config & Start: ~2 min █ ───────────────────── Total: ~11 min
需要注意的是,延迟不是由计算或推理引起的,而仅仅是由于准备容器启动。
现在我们已经介绍了基础知识,让我们深入探讨减慢 LLM 容器启动速度的主要瓶颈。
容器注册中心和运行时最初是为小型镜像(例如 Web 应用程序)设计的。它们在处理 LLM 推理工作负载时可能面临性能挑战。
gzip
或 zstd
等压缩格式,解压步骤通常是 CPU 密集型的。仅解压一个 50GB 的模型在现代 CPU 上可能需要 5-8 分钟。大多数容器存储驱动不适用于处理大型 GenAI 模型文件
.safetensors
文件)。LLM 在部署过程中模型文件的传输和加载方式带来了独特的挑战
这些限制加在一起可以极大地延长启动过程,即使在高带宽网络上也是如此。除了延迟之外,它们还会产生连锁问题:网络饱和、磁盘 I/O 峰值以及基础设施成本增加(由于过度配置资源来管理这些低效率)。
为了加速 LLM 容器启动,我们必须从根本上重新考虑容器镜像的拉取方式和模型权重的加载方式。
第一个挑战是容器注册中心镜像下载速度慢。鉴于上述限制,我们探索了一种替代方案:直接从对象存储系统拉取容器镜像,例如 Google Cloud Storage (GCS) 和 Amazon S3。
对于 Llama 3.1 8B 容器,对象存储的速度明显更快,我们在测试中镜像拉取时间降至约 10 秒。
方法 | 速度 (取决于机器/网络) | 时间 |
---|---|---|
云注册中心拉取 (GAR/ECR) | 60 MB/秒 | ~350 秒 |
内部注册中心拉取 (Harbor) | 120 MB/秒 | ~170 秒 |
直接 GCS/S3 下载 | 2 GB/秒 或更高 | ~10 秒 |
我们将速度提升归因于
Range
请求,充分利用网络带宽。尽管下载速度更快,但我们注意到解压步骤明显减慢了速度,常常将整体有效吞吐量减半。解压期间的磁盘 I/O 仍然是一个关键瓶颈。
这使得解压步骤成为我们的下一个优化目标。
我们的突破性进展在于我们意识到可以通过重新思考容器如何访问其文件系统来完全绕过解压。这就是 FUSE(用户空间文件系统) 改变游戏规则的地方。
FUSE 允许非特权用户创建和挂载自定义文件系统,而无需内核级代码或 root 权限。基于 FUSE 的工具,如 stargz-snapshotter
,允许容器按需访问镜像数据,无需预先解压所有层。这避免了 CPU 密集型的解压和过多的磁盘 I/O。
通过 FUSE,我们优化了工作流程,实现了模型的按需访问。我们没有将每一层都解压到磁盘,而是将镜像层以未压缩、可查找的 tar 格式保存在对象存储中。这使得容器可以像访问本地文件一样访问它们,将它们视为可查找、惰性加载的文件数据库,即使底层数据仍然远程存在。这意味着容器只有在实际需要时才会从远程存储流式传输单个文件块或数据块。
以可查找的 tar 格式为基础,我们将模型权重与容器镜像分离,并实现了直接加载到 GPU 内存。
在未经优化的情况下,模型权重会被下载、写入磁盘,然后加载到 GPU 内存。这是一个缓慢的过程,因为它涉及顺序操作且 I/O 密集。
我们通过引入零拷贝、基于流的模型加载简化了这一步骤。这意味着模型文件可以直接从远程存储流式传输到 GPU 内存,无需中间的磁盘读写。通过这些优化,我们使 Llama 3.1 8B 的冷启动时间加快了 25 倍。请注意,确切的 LLM 冷启动持续时间可能因您的网络或磁盘带宽、GPU 性能和模型大小而异。
缩短 LLM 容器冷启动时间不仅是一项技术优化,也是您产品的战略优势。对于部署 LLM 的企业来说,更快的冷启动意味着更低的基础设施成本、更高的工程灵活性和更好的用户体验。
通过分享我们的经验,我们希望帮助其他在部署大规模 AI 工作负载时面临类似挑战的人。我们相信这些技术可以惠及更广泛的 AI 工程社区,支持在 Kubernetes 上进行更具可扩展性和成本效益的 LLM 部署。
查看以下资源了解更多信息