

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 应用程序扩展和性能
<a name="aiml-performance"></a>

**提示**  
 通过 Amazon EKS 研讨会@@ [探索](https://aws-experience.com/emea/smb/events/series/get-hands-on-with-amazon-eks?trk=4a9b4147-2490-4c63-bc9f-f8a84b122c8c&sc_channel=el)最佳实践。

## 管理 ML 构件、提供框架和启动优化
<a name="_managing_ml_artifacts_serving_frameworks_and_startup_optimization"></a>

在 Amazon EKS 上部署机器学习 (ML) 模型需要仔细考虑如何将模型集成到容器映像和运行时环境中。这确保了可扩展性、可重复性和高效的资源利用率。本主题介绍了处理机器学习模型工件、选择服务框架以及通过预缓存等技术优化容器启动时间的不同方法，所有这些方法都是为减少容器启动时间而量身定制的。

### 在部署中处理 ML 模型构件
<a name="_handling_ml_model_artifacts_in_deployments"></a>

一个关键的决定是如何自己处理机器学习模型工件（例如权重和配置）。选择会影响映像大小、部署速度、模型更新频率和操作开销。请注意，在提及存储 “模型” 时，我们指的是模型工件（例如训练过的参数和模型权重）。在 Amazon EKS 上处理机器学习模型工件有不同的方法。每种方法都有其权衡取舍，最佳选择取决于模型的大小、更新节奏和基础设施需求。请考虑以下方法，从最低到最受推荐：
+  **将模型烘焙到容器镜像中：在镜像**构建过程中，将模型文件（例如.safetensors、.pth、.h5）复制到容器镜像（例如 Dockerfile）中。该模型是不可变图像的一部分。对于更新频率较低的小型号，我们建议使用这种方法。这可以确保一致性和可重复性，不提供加载延迟，简化依赖关系管理，但会导致图像大小变大，构建和推送速度变慢，需要重新构建和重新部署才能更新模型，而且由于注册表拉取吞吐量，因此不适合大型模型。
+  **在运行时下载模型：在**容器启动时，应用程序通过初始化容器或入口点中的脚本从外部存储（例如 Amazon S3，由 S3 CRT 支持，使用适用于 S3 CSI 驱动程序的 Mountpoint、AWS S3 CLI 或 s5cmd OSS CLI 等方法）下载模型，以优化高吞吐量传输。对于经常更新的大型模型，我们建议从这种方法开始。这使容器镜像专注于代码/运行时，无需重建即可轻松更新模型，支持通过存储元数据进行版本控制，但它会引入潜在的网络故障（需要重试逻辑），需要身份验证和缓存。

要了解更多信息，请参阅 EKS 人工智能研讨会中的[加速拉取流程](https://awslabs.github.io/ai-on-eks/docs/guidance/container-startup-time/accelerate-pull-process)。

### 为机器学习模型提供服务
<a name="_serving_ml_models"></a>

在 Amazon EKS 上部署和提供机器学习 (ML) 模型需要选择适当的模型服务方法来优化延迟、吞吐量、可扩展性和操作简便性。选择取决于您的模型类型（例如语言、视觉模型）、工作负载需求（例如实时推理）和团队专业知识。常见的方法包括基于 Python 的原型设计设置、用于生产级功能的专用模型服务器以及用于实现高性能和效率的专用推理引擎。每种方法都需要权衡设置复杂性、性能和资源利用率。请注意，由于依赖关系，服务框架可能会增加容器映像的大小（多个 GBs），这可能会影响启动时间，请考虑使用构件处理技术进行解耦来缓解这种情况。从最少到最推荐的选项按推荐顺序列出：

 **使用 Python 框架（例如 FastAPI、 HuggingFace Transformers with PyTorch）**使用 Python 框架开发自定义应用程序，在容器化节点设置中嵌入模型文件（权重、配置、标记器）。
+  **优点**：原型设计简单，仅限 Python，无需额外基础架构，与所有 HuggingFace 模型兼容，Kubernetes 部署简单。
+  **缺点**：仅限于单 request/simple 批处理、令牌生成速度慢（没有经过优化的内核）、内存效率低下、缺乏扩展/监控以及启动时间长。
+  **建议**：用于需要自定义逻辑集成的初始原型设计或单节点任务。

 **使用专用的模型服务框架（例如 Tensorrt-LLM、TGI）采用像 Tensorrt-llm 或 TGI** 这样的专用服务器进行机器学习推理、管理模型加载、路由和优化。这些支持诸如 safetensors 之类的格式，以及可选的编译或插件。
+  **优点**：提供批处理（static/in-flight or continuous), quantization (INT8, FP8, GPTQ), hardware optimizations (NVIDIA, AMD, Intel, Inferentia), and multi-GPU support (Tensor/Pipeline并行性）。Tensorrt-LLM 支持不同的模型（Encoder-Decoder）LLMs，而 TGI 则利用集成。 HuggingFace 
+  **缺点**：Tensorrt-LLM 需要编译并且仅限 Nvidia；TGI 的批处理效率可能较低；两者都会增加配置开销，并且可能不适合所有模型类型（例如，非变压器）。
+  **建议**：适用于需要生产能力（例如 A/B 测试或具有兼容硬件的高吞吐量）的 PyTorch/TensorFlow 型号。

 **使用专门的高吞吐量推理引擎（例如 vLLM）利用高级推理引擎，例如** vLLM，优化 LLM 服务、飞行中批处理和量化（ PagedAttentionINT8、-KV、AWQ），可与 EKS 自动缩放集成。 FP8
+  **优点**：高吞吐量和内存效率（可节省 40-60% 的 VRAM）、动态请求处理、令牌流、单节点 Tensor 并行多 GPU 支持以及广泛的硬件兼容性。
+  **缺点**：针对仅限解码器的变压器（例如 LLa MA）进行了优化，对非变压器型号效果较差，需要兼容的硬件（例如 NVIDIA GPUs）和设置工作。
+  **建议**：在 EKS 上进行大容量、低延迟 LLM 推理的首选，可最大限度地提高可扩展性和性能。

## 优化容器镜像提取时间
<a name="_optimizing_container_image_pull_times"></a>

大型容器镜像可能会导致冷启动延迟，从而影响 pod 的启动延迟。对于延迟敏感型工作负载，例如水平扩展的实时推理工作负载，Pod 的快速启动至关重要。考虑以下方法来优化容器镜像的提取时间：

### 缩小容器镜像大小
<a name="_reducing_container_image_sizes"></a>

在启动期间减小容器镜像的大小是缩小镜像的另一种方法。您可以在容器镜像构建过程的每个步骤中进行缩减。首先，请选择包含所需依赖项最少的基础映像。在映像构建过程中，仅包含必需的基本库和工件。构建图像时，请尝试组合多个`RUN`或`COPY`命令来创建较少数量的较大图层。对于 AI/ML 框架，使用多阶段构建来分隔构建和运行时，仅复制所需的工件（例如，注册表或本地上下文的 via`COPY —from=`），并选择诸如仅限运行时的图像之类的变体（例如，`pytorch/pytorch:2.7.1-cuda11.8-cudnn9-runtime`3.03 GB 与 devel 为 6.66 GB）。要了解更多信息，请参阅 EKS 人工智能研讨会中的[缩小容器映像大小](https://awslabs.github.io/ai-on-eks/docs/guidance/container-startup-time/reduce-container-image-size)。

### 使用 SOCI 快照器预提取图像
<a name="_using_soci_snapshotter_to_pre_pull_images"></a>

对于无法轻易最小化的超大图像，您可以使用在并行拉取和解压缩模式下配置的开源 Seekable OCI (SOCI) 快照器。此解决方案允许您使用现有映像，而无需重新构建或修改构建管道。当将具有非常大的映像的工作负载部署到高性能 EC2 计算实例时，此选项特别有效。它适用于高吞吐量网络和高性能存储配置，就像扩展 AI/ML 工作负载一样。

SOCI 并行 pull/unpack 模式通过可配置的并行化策略提高 end-to-end图像拉取性能。更快的映像提取和准备速度直接影响您部署新工作负载和高效扩展集群的速度。图像拉取有两个主要阶段：

 **1。将图层从注册表提取到节点**   
为了优化图层抓取，SOCI 在每层创建多个并发 HTTP 连接，使下载吞吐量成倍超过单一连接限制。它将大图层拆分成块，然后通过多个连接同时下载它们。这种方法有助于使您的可用网络带宽饱和，并显著缩短下载时间。这对于单层可能有几千兆字节 AI/ML 的工作负载特别有价值。

 **2。拆包并准备这些图层以创建容器**   
为了优化图层解包，SOCI 会同时处理多个图层。它使用可用的 CPU 内核同时解压缩和提取多个图层，而不是等待每层完全解压后再开始下一层。这种并行处理将传统的 I/O 绑定拆包阶段转变为 CPU 优化的操作，可随可用内核进行扩展。系统会仔细协调这种并行化，以保持文件系统的一致性，同时最大限度地提高吞吐量。

SOCI parallel pull 模式使用双阈值控制系统，该系统具有用于下载并发性和解包并行性的可配置参数。这种精细控制允许您微调 SOCI 的行为，以满足您的特定性能要求和环境条件。了解这些参数有助于优化运行时间，以获得最佳的拉取性能。

 **参考** 
+ 有关解决方案和调整权衡的更多信息，请参阅 [SOCI 项目存储库](https://github.com/awslabs/soci-snapshotter)中的[功能文档](https://github.com/awslabs/soci-snapshotter/blob/main/docs/parallel-mode.md)。 GitHub
+ 有关在 Amazon EKS 上使用 Karpenter 的动手示例，请参阅使用 [SOCI 快照并行模式的 Karpenter 蓝图](https://github.com/aws-samples/karpenter-blueprints/tree/main/blueprints/soci-snapshotter)。 pull/unpack 
+ 有关配置 Bottlerocket 进行并行拉取的信息，请参阅 Bottlerocket 文档中的[社交快照器 Parallel Pull Unpack 模式。O](https://bottlerocket.dev/en/os/1.44.x/api/settings/container-runtime-plugins/#tag-soci-parallel-pull-configuration)

### 使用 EBS 快照预拉镜像
<a name="_using_ebs_snapshots_to_pre_pull_images"></a>

您可以为缓存的容器映像拍摄 Amazon Elastic Block Store (EBS) 快照，然后在 EKS 工作节点上重复使用此快照。这样可以确保在节点启动时在本地预取图像，从而缩短 pod 初始化时间。有关使用适用于托管[节点组的 Karpenter 和 EKS [Terraform 蓝图的更多信息，请参阅使用 Bottlerocket 数据量缩短亚马逊 E](https://aws-ia.github.io/terraform-aws-eks-blueprints/patterns/machine-learning/ml-container-cache/) KS 上的容器启动时间](https://aws.amazon.com/blogs/containers/reduce-container-startup-time-on-amazon-eks-with-bottlerocket-data-volume/)。

要了解更多信息，请参阅 EKS 人工智能研讨会中的[使用 containerd 快照](https://awslabs.github.io/ai-on-eks/docs/guidance/container-startup-time/accelerate-pull-process/containerd-snapshotter)和使用 EBS 快照将[容器映像预加载到 Bottlerocket 数据卷](https://awslabs.github.io/ai-on-eks/docs/guidance/container-startup-time/accelerate-pull-process/prefecthing-images-on-br)中。

### 使用容器运行时缓存预拉镜像
<a name="_using_the_container_runtime_cache_to_pre_pull_images"></a>

你可以使用 Kubernetes 资源（例如 DaemonSet 或 Deployment）将容器镜像预拉到节点上，以填充节点的容器运行时缓存。容器运行时缓存是由容器运行时管理的本地存储（例如，c [ontainerd](https://containerd.io/)），从注册表中提取图像后存储在那里。 预拉可确保图像在本地可用，从而避免 pod 启动期间的下载延迟。 当图像经常更改（例如频繁更新）、未预先配置 EBS 快照时、构建 EBS 卷比直接从容器注册表中提取更耗时，或者节点已经在集群中并且需要使用多个可能的映像之一按需启动 pod 时，这种方法特别有用。

无论需要哪张图片，预先拉出所有变体都可确保快速启动。例如，在需要使用 10 种不同技术构建 100,000 个小型模型的大规模并行机器学习工作负载中，通过在大型集群（例如数千 DaemonSet 个节点）中预先拉取 10 张图像可最大限度地缩短 pod 启动时间，从而避免按需拉取，从而在不到 10 秒的时间内完成。使用容器运行时缓存方法无需管理 EBS 快照，可确保您始终使用最新的容器映像版本 DaemonSets，但是对于节点缩放in/out, new nodes added by tools like Cluster Autoscaler may schedule workload pods before the pre-pull DaemonSet completes image pulling. This can cause the initial pod on the new node to trigger the pull anyway, potentially delaying startup and impacting low-latency requirements. Additionally, kubelet image garbage collection can affect pre-pulled images by removing unused ones when disk usage exceeds certain thresholds or if they exceed a configured maximum unused age. In scale-in/out模式的实时推理工作负载，这可能会在空闲节点上移出图像，这需要在随后的扩展过程中重新拉取，并降低缓存对于突发工作负载的可靠性。

有关将图像预拉入容器运行时缓存的示例，请参阅 [AWS GitHub 存储库](https://github.com/aws-samples/aws-do-eks/tree/main/Container-Root/eks/deployment/prepull)。

## 考虑 NVMe 使用 kubelet 和 containerd 存储
<a name="_consider_nvme_for_kubelet_and_containerd_storage"></a>

考虑配置`kubelet`并使用临时 NVMe 实例存储磁盘`containerd`以获得更高的磁盘性能。容器拉取过程包括从注册表下载容器镜像，然后将其层解压缩为可用格式。要优化解压缩期间的 I/O 操作，您应该评估哪些因素可以为容器主机的实例类型提供更高的 I/O 性能和吞吐量：具有本地存储的[NVMe 备份实例与 EBS 卷 I](https://docs.aws.amazon.com/en_us/documentdb/latest/developerguide/db-instance-nvme.html) OPS/吞吐量。对于具有 NVMe 本地存储空间的 EC2 实例，可以考虑为 kubelet () `/var/lib/kubelet`、containerd (`/var/lib/containerd`) 和 Pod logs () 配置节点的底层文件系统，以使用临时 NVMe 实例存储磁盘来实现更高的性能和吞吐量水平。`/var/log/pods` I/O 

节点的临时存储空间可以在请求临时存储的 Pod 和下载到节点的容器镜像之间共享。如果将 Karpenter 与 Bottlerocket 或 AL2023 EKS Optimized 一起使用，则[EC2NodeClass](https://karpenter.sh/docs/concepts/nodeclasses/#specinstancestorepolicy)可以通过设置 instanceStorePolicy 为[RAID0](https://docs.aws.amazon.com/ebs/latest/userguide/raid-config.html)或者（如果使用托管节点组）通过将输入设置[NodeConfig](https://eksctl.io/usage/node-bootstrapping/#configuring-the-bootstrapping-process)为用户数据的一部分 localStoragePolicy 来进行配置。 AMIs 