

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

# 应用程序扩展和性能
<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 等方法）下载模型，以优化高吞吐量传输。对于经常更新的大型模型，我们建议从这种方法开始。这样可以专注于容器镜像 code/runtime，无需重建即可轻松更新模型，支持通过存储元数据进行版本控制，但它会引入潜在的网络故障（需要重试逻辑），需要身份验证和缓存。

要了解更多信息，请参阅 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-based 设置、用于生产级功能的专用模型服务器以及用于实现高性能和效率的专用推理引擎。每种方法都需要权衡设置复杂性、性能和资源利用率。请注意，由于依赖关系，服务框架可能会增加容器映像的大小（多 GB），这可能会影响启动时间，请考虑使用构件处理技术进行解耦来缓解这种情况。从最少到最推荐的选项按推荐顺序列出：

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

 **使用专用的模型服务框架（例如 TensorRT-LLM，TGI）**采用专门的服务器（如 TensorRT-LLM 或 TGI）进行机器学习推理，管理模型加载、路由和优化。这些支持诸如 safetensors 之类的格式，以及可选的编译或插件。
+  **优点**：提供批处理（static/in飞行或连续）、量化（INT8、FP8、GPTQ）、硬件优化（NVIDIA、AMD、英特尔、推理）和多 GPU 支持（并行度）。Tensor/Pipeline TensorRT-LLM 支持多种模型（LLM、 Encoder-Decoder），而 TGI 则利用 HuggingFace 集成。
+  **缺点**： TensorRT-LLM 需要编译而且是 NVIDIA-only；TGI 的批处理效率可能较低；两者都会增加配置开销，并且可能不适合所有模型类型（例如，非变压器）。
+  **建议**：适用于需要生产能力（例如 A/B 测试或具有兼容硬件的高吞吐量）的 PyTorch/TensorFlow 型号。

 **使用专门的高吞吐量推理引擎（例如 vLLM）利用高级推理引擎，例如** vLLM，优化 LLM 服务、飞行中批处理和量化（INT8 PagedAttention、、AWQ），可与 EKS 自动缩放集成。 FP8-KV
+  **优点**：高吞吐量和内存效率（可节省 40-60% 的 VRAM）、动态请求处理、令牌流、单节点 Tensor 并行多 GPU 支持以及广泛的硬件兼容性。
+  **缺点**：针对仅限解码器的变压器（例如 LLaMA）进行了优化，对非变压器型号效果较差，需要兼容的硬件（例如 NVIDIA GPU）和设置工作。
+  **建议**：在 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)。

### 减少图像拉取延迟
<a name="_reduce_image_pull_latency"></a>

对于在私有子网中运行的 EKS 集群，请为 Amazon ECR 配置 VPC 接口终端节点，以保持 AWS 私有网络上的图像拉取流量，从而减少延迟并消除 NAT 网关数据处理费用。有关设置说明[，请参阅为 Amazon ECR 创建 VPC 终端节点](https://docs.aws.amazon.com/AmazonECR/latest/userguide/vpc-endpoints.html)。

此外，如果您的工作负载依赖于来自外部注册表的上游容器映像，请考虑使用 [ECR pull th](https://docs.aws.amazon.com/AmazonECR/latest/userguide/pull-through-cache.html) rough cache 在私有 ECR 注册表中代理和缓存这些映像。

### 优化图像拉取的网络带宽
<a name="_optimize_network_bandwidth_for_image_pulls"></a>

拉取大型容器镜像时，EKS 工作节点可用的网络带宽会直接影响训练和推理工作负载的启动时间。所有当前一代的 Nitro-based 实例都使用弹性网络适配器 (ENA)，但可用带宽因实例大小而有很大差异，因此了解基准带宽和突发带宽之间的区别至关重要（参见 [Amazon EC2 实例网络带宽](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-network-bandwidth.html)）。为了最大限度地缩短工作负载的准备时间，请选择具有足够基准网络带宽的实例大小（相对于您的映像大小和拉取并发性）。

### 使用 SOCI 快照器拍摄图像 Pre-pull
<a name="_using_soci_snapshotter_to_pre_pull_images"></a>

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

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

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

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

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 snapshotter 并行模式的 Karpenter 蓝图](https://github.com/aws-samples/karpenter-blueprints/tree/main/blueprints/soci-snapshotter)。 pull/unpack 
+ 有关配置 Bottlerocket 进行并行拉动的信息，请参阅 Bottlerocket 中的 s [oci-snapshotter](https://bottlerocket.dev/en/os/1.44.x/api/settings/container-runtime-plugins/#tag-soci-parallel-pull-configuration) Pallel Pull Unpack 模式 Documentation.o

### 将 EBS 快照用于映像 Pre-pull
<a name="_using_ebs_snapshots_to_pre_pull_images"></a>

您可以为缓存的容器映像拍摄 Amazon Elastic Block Store (EBS) 快照，然后在 EKS 工作节点上重复使用此快照。这样可以确保在节点启动时在本地预取图像，从而缩短 pod 初始化时间。有关使用 [Karpenter 和 EKS [Terraform Blueprints 管理托管节点组的更多信息，请参阅使用 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)中。

### 使用容器运行时缓存存储 Pre-pull 镜像
<a name="_using_the_container_runtime_cache_to_pre_pull_images"></a>

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

Pre-pulling 无论需要哪种映像，所有变体都可确保快速启动。例如，在需要使用 10 种不同技术构建 100,000 个小型模型的大规模并行机器学习工作负载中，通过在大型集群（例如数千 DaemonSet 个节点）中预先拉取 10 张图像可最大限度地缩短 pod 启动时间，从而避免按需拉取，从而在不到 10 秒的时间内完成。使用容器运行时缓存方法无需管理 EBS 快照，可确保您始终使用最新的容器映像版本，但是对于节点可扩展 in/out的实时推理工作负载 DaemonSets，由 Cluster Autoscaler 等工具添加的新节点可能会在预 DaemonSet 拉取完成映像拉取之前调度工作负载 pod。无论如何，这都可能导致新节点上的初始 Pod 触发拉动，从而可能延迟启动并影响低延迟要求。此外，当磁盘使用率超过特定阈值或超过配置的最大未使用年限时，kubelet 图像垃圾回收会通过删除未使用的图像来影响预拉取的图像。在缩放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`并使用`containerd`临时 NVMe 实例存储磁盘以获得更高的磁盘性能。容器拉取过程包括从注册表下载容器镜像，然后将其层解压缩为可用格式。要优化解压缩期间的 I/O 操作，您应该评估哪些方法可以为容器主机的实例类型提供更高的 I/O 性能和吞吐量：具有本地存储的 [NVMe 支持实例与 EBS 卷](https://docs.aws.amazon.com/en_us/documentdb/latest/developerguide/db-instance-nvme.html)的实例。 IOPS/throughput对于具有 NVMe 本地存储的 EC2 实例，可以考虑为 kubelet () `/var/lib/kubelet`、containerd () 和 Pod logs (`/var/lib/containerd`) 配置节点的底层文件系统，以使用临时 NVMe 实例存储磁盘来实现更高的性能和吞吐量。`/var/log/pods` I/O 

节点的临时存储空间可以在请求临时存储的 Pod 和下载到节点的容器镜像之间共享。[如果将 Karpenter 与 Bottlerocket 或 AL2023 EKS 优化的 AMI 一起使用，则可以在中[EC2NodeClass](https://karpenter.sh/docs/concepts/nodeclasses/#specinstancestorepolicy)进行配置，方法是将StorePolicy 实例设置为 RAID0，或者如果使用托管节点组，则可以将StoragePolicy 本地[NodeConfig](https://eksctl.io/usage/node-bootstrapping/#configuring-the-bootstrapping-process)设置为用户数据的一部分。](https://docs.aws.amazon.com/ebs/latest/userguide/raid-config.html) AL2023