

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# 애플리케이션 조정 및 성능
<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 모델 아티팩트를 처리하고, 프레임워크 제공을 선택하고, 사전 캐싱과 같은 기술을 통해 컨테이너 시작 시간을 최적화하는 다양한 접근 방식을 설명합니다.이 모든 방법은 컨테이너 시작 시간을 줄이도록 조정되었습니다.

### 배포에서 ML 모델 아티팩트 처리
<a name="_handling_ml_model_artifacts_in_deployments"></a>

핵심 결정은 ML 모델 아티팩트(예: 가중치 및 구성)를 직접 처리하는 방법입니다. 선택 사항은 이미지 크기, 배포 속도, 모델 업데이트 빈도 및 운영 오버헤드에 영향을 미칩니다. "모델" 저장을 참조할 때는 모델 아티팩트(예: 훈련된 파라미터 및 모델 가중치)를 참조합니다. Amazon EKS에서 ML 모델 아티팩트를 처리하는 방법에는 여러 가지가 있습니다. 각 모델에는 장단점이 있으며, 최상의 장단점은 모델의 크기, 업데이트 주기 및 인프라 요구 사항에 따라 달라집니다. 가장 적게 권장되는 것부터 가장 권장되는 것까지 다음과 같은 접근 방식을 고려하세요.
+  **모델을 컨테이너 이미지로 베이킹**: 이미지 빌드 중에 모델 파일(예: .safetensors, .pth, .h5)을 컨테이너 이미지(예: Dockerfile)에 복사합니다. 모델은 변경 불가능한 이미지의 일부입니다. 자주 업데이트하지 않는 소형 모델의 경우이 접근 방식을 사용하는 것이 좋습니다. 이렇게 하면 일관성과 재현성이 보장되고, 로드 지연이 없으며, 종속성 관리를 간소화할 수 있지만 이미지 크기가 커져 빌드 및 푸시 속도가 느려지고, 모델 업데이트를 위해 재구축 및 재배포가 필요하며, 레지스트리 풀 처리량으로 인해 대규모 모델에 적합하지 않습니다.
+  **런타임 시 모델 다운로드**: 컨테이너 시작 시 애플리케이션은 init 컨테이너 또는 진입점의 스크립트를 통해 외부 스토리지(예: Mountpoint for S3 CSI 드라이버, Amazon S3 S3)에서 모델을 다운로드합니다. S3 업데이트가 빈번한 대규모 모델의 경우이 접근 방식부터 시작하는 것이 좋습니다. 이렇게 하면 컨테이너 이미지가 코드/런타임에 초점을 맞추고, 재구축 없이 모델을 쉽게 업데이트할 수 있으며, 스토리지 메타데이터를 통한 버전 관리를 지원하지만, 인증 및 캐싱이 필요한 잠재적 네트워크 장애(재시도 로직 필요)가 발생합니다.

자세한 내용은 AI on EKS 워크숍의 [풀 프로세스 가속화](https://awslabs.github.io/ai-on-eks/docs/guidance/container-startup-time/accelerate-pull-process)를 참조하세요.

### ML 모델 제공
<a name="_serving_ml_models"></a>

Amazon EKS에서 기계 학습(ML) 모델을 배포하고 제공하려면 지연 시간, 처리량, 확장성 및 운영 간소화를 최적화하는 적절한 모델 제공 접근 방식을 선택해야 합니다. 선택은 모델 유형(예: 언어, 비전 모델), 워크로드 요구 사항(예: 실시간 추론) 및 팀 전문 지식에 따라 달라집니다. 일반적인 접근 방식에는 프로토타이핑을 위한 Python 기반 설정, 프로덕션급 기능을 위한 전용 모델 서버, 고성능 및 효율성을 위한 특수 추론 엔진이 포함됩니다. 각 방법에는 설정 복잡성, 성능 및 리소스 사용률의 장단점이 포함됩니다. 제공 프레임워크는 종속성으로 인해 컨테이너 이미지 크기(여러 GBs 늘릴 수 있으며, 이는 시작 시간에 영향을 미칠 수 있습니다. 이를 완화하기 위해 아티팩트 처리 기술을 사용한 분리를 고려하세요. 옵션은 최소 권장부터 가장 권장까지 나열됩니다.

 **Python 프레임워크 사용(예: FastAPI, PyTorch를 사용하는 HuggingFace 변환기)** 컨테이너화된 노드 설정 내에 모델 파일(가중치, 구성, 토큰화기)을 포함하는 Python 프레임워크를 사용하여 사용자 지정 애플리케이션을 개발합니다.
+  **장점**: 간편한 프로토타이핑, 추가 인프라 없이 Python 전용, 모든 HuggingFace 모델과 호환, 간단한 Kubernetes 배포.
+  **단점**: 단일 요청/단순 일괄 처리, 느린 토큰 생성(최적화된 커널 없음), 메모리 비효율성, 규모 조정/모니터링 부족, 긴 시작 시간으로 제한합니다.
+  **권장 사항**: 사용자 지정 로직 통합이 필요한 초기 프로토타이핑 또는 단일 노드 작업에 사용합니다.

 **전용 모델 서비스 프레임워크(예: TensorRT-LLM, TGI) 사용** ML 추론을 위해 TensorRT-LLM 또는 TGI와 같은 특수 서버를 채택하고 모델 로드, 라우팅 및 최적화를 관리합니다. 이러한는 선택 사항인 컴파일 또는 플러그인과 함께 Safetensor와 같은 형식을 지원합니다.
+  **장점**: 일괄 처리(정적/비행 중 또는 연속), 양자화(INT8, FP8, GPTQ), 하드웨어 최적화(NVIDIA, AMD, Intel, Inferentia) 및 다중 GPU 지원(Tensor/Pipeline Parallelism)을 제공합니다. TensorRT-LLM은 다양한 모델(LLMs, Encoder-Decoder)을 지원하는 반면, TGI는 HuggingFace 통합을 활용합니다.
+  **단점**: TensorRT-LLM은 컴파일이 필요하며 NVIDIA 전용입니다. TGI는 일괄 처리에서 덜 효율적일 수 있습니다. 둘 다 구성 오버헤드를 추가하고 일부 모델 유형(예: 비변환기)에 맞지 않을 수 있습니다.
+  **권장 사항**: A/B 테스트 또는 호환되는 하드웨어를 사용한 높은 처리량과 같은 프로덕션 기능이 필요한 PyTorch/TensorFlow 모델에 적합합니다.

 **특수한 고처리량 추론 엔진(예: vLLM) 사용** vLLM과 같은 고급 추론 엔진을 활용하여 PagedAttention을 사용한 LLM 서비스, 진행 중인 배치 및 양자화(INT8, FP8-KV, AWQ)를 최적화하고 EKS Auto Scaling과 통합 가능합니다.
+  **장점**: 높은 처리량 및 메모리 효율성(40\$160% VRAM 절감), 동적 요청 처리, 토큰 스트리밍, 단일 노드 Tensor 병렬 다중 GPU 지원, 광범위한 하드웨어 호환성.
+  **단점**: 디코더 전용 변환기(예: LLaMA)에 최적화되어 있고 비변환기 모델에 덜 효과적이므로 호환되는 하드웨어(예: NVIDIA GPUs)와 설정 작업이 필요합니다.
+  **권장 사항**: EKS에서 지연 시간이 짧은 대용량 LLM 추론을 위한 최고의 선택으로 확장성과 성능을 극대화합니다.

## 컨테이너 이미지 풀 타임 최적화
<a name="_optimizing_container_image_pull_times"></a>

컨테이너 이미지가 크면 콜드 스타트 지연이 발생하여 포드 시작 지연 시간에 영향을 미칠 수 있습니다. 가로로 확장되는 실시간 추론 워크로드와 같이 지연 시간에 민감한 워크로드의 경우 빠른 포드 시작이 중요합니다. 컨테이너 이미지 풀 타임을 최적화하려면 다음 접근 방식을 고려하세요.

### 컨테이너 이미지 크기 줄이기
<a name="_reducing_container_image_sizes"></a>

시작 시 컨테이너 이미지 크기를 줄이는 것은 이미지를 더 작게 만드는 또 다른 방법입니다. 컨테이너 이미지 빌드 프로세스의 모든 단계에서 줄일 수 있습니다. 시작하려면 필요한 종속성 수가 가장 적은 기본 이미지를 선택합니다. 이미지 빌드 중에는 필요한 필수 라이브러리와 아티팩트만 포함합니다. 이미지를 빌드할 때 여러 `RUN` 또는 `COPY` 명령을 결합하여 더 많은 수의 더 큰 계층을 생성해 보세요. AI/ML 프레임워크의 경우 다단계 빌드를 사용하여 빌드와 런타임을 분리하고, 필요한 아티팩트만 복사하고(예: 레지스트리 또는 로컬 컨텍스트`COPY —from=`의 경우를 통해), 런타임 전용 이미지와 같은 변형을 선택합니다(예: 3.03GB`pytorch/pytorch:2.7.1-cuda11.8-cudnn9-runtime`에서 대 6.66GB에서 개발). 자세한 내용은 AI on 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>

쉽게 최소화할 수 없는 매우 큰 이미지의 경우 병렬 풀 및 언패킹 모드로 구성된 오픈 소스 SOCI(Sekable OCI) 스냅샷 생성기를 사용할 수 있습니다. 이 솔루션을 사용하면 빌드 파이프라인을 재구축하거나 수정하지 않고도 기존 이미지를 사용할 수 있습니다. 이 옵션은 매우 큰 이미지가 있는 워크로드를 고성능 EC2 컴퓨팅 인스턴스에 배포할 때 특히 효과적입니다. 대규모 AI/ML 워크로드와 마찬가지로 처리량이 많은 네트워킹 및 고성능 스토리지 구성에서도 잘 작동합니다.

SOCI 병렬 풀/언팩 모드는 구성 가능한 병렬화 전략을 통해 end-to-end 이미지 풀 성능을 개선합니다. 이미지 가져오기 및 준비 속도가 빨라지면 새 워크로드를 배포하고 클러스터를 효율적으로 확장할 수 있는 속도에 직접적인 영향을 미칩니다. 이미지 풀에는 두 가지 주요 단계가 있습니다.

 **1: 레지스트리에서 노드로 계층 가져오기**   
계층 가져오기 최적화를 위해 SOCI는 계층당 여러 동시 HTTP 연결을 생성하여 단일 연결 제한을 초과하는 다운로드 처리량을 곱합니다. 큰 계층을 청크로 분할하고 여러 연결에서 동시에 다운로드합니다. 이 접근 방식은 사용 가능한 네트워크 대역폭을 포화시키고 다운로드 시간을 크게 줄이는 데 도움이 됩니다. 이는 단일 계층이 몇 기가바이트일 수 있는 AI/ML 워크로드에 특히 유용합니다.

 **2. 컨테이너를 생성하기 위해 해당 계층의 압축을 풀고 준비**   
계층 언패킹 최적화를 위해 SOCI는 여러 계층을 동시에 처리합니다. 다음 단계를 시작하기 전에 각 계층의 압축이 완전히 풀릴 때까지 기다리는 대신 사용 가능한 CPU 코어를 사용하여 여러 계층의 압축을 풀고 동시에 추출합니다. 이 병렬 처리는 기존의 I/O 바운드 언패킹 단계를 사용 가능한 코어에 따라 확장되는 CPU 최적화 작업으로 변환합니다. 시스템은이 병렬화를 신중하게 오케스트레이션하여 파일 시스템 일관성을 유지하면서 처리량을 극대화합니다.

SOCI 병렬 풀 모드는 다운로드 동시성 및 언패킹 병렬 처리 모두에 대해 구성 가능한 파라미터가 있는 이중 임계값 제어 시스템을 사용합니다. 이러한 세분화된 제어를 통해 특정 성능 요구 사항 및 환경 조건을 충족하도록 SOCI의 동작을 미세 조정할 수 있습니다. 이러한 파라미터를 이해하면 최상의 풀 성능을 위해 런타임을 최적화하는 데 도움이 됩니다.

 **참조** 
+ 솔루션 및 튜닝 장단점에 대한 자세한 내용은 GitHub의 [SOCI 프로젝트 리포지토리](https://github.com/awslabs/soci-snapshotter)에 있는 [기능 설명서를](https://github.com/awslabs/soci-snapshotter/blob/main/docs/parallel-mode.md) 참조하세요.
+ Amazon EKS에서 Karpenter를 사용하는 실습 예제는 [SOCI 스냅샷 생성기 병렬 풀/언팩 모드를 사용하는 Karpenter 블루프린](https://github.com/aws-samples/karpenter-blueprints/tree/main/blueprints/soci-snapshotter)트를 참조하세요.
+ 병렬 풀을 위한 Bottlerocket 구성에 대한 자세한 내용은 Bottlerocket 설명서의 [soci-snapshotter 병렬 풀 언팩 모드를](https://bottlerocket.dev/en/os/1.44.x/api/settings/container-runtime-plugins/#tag-soci-parallel-pull-configuration) 참조하세요.o

### EBS 스냅샷을 사용하여 이미지 미리 가져오기
<a name="_using_ebs_snapshots_to_pre_pull_images"></a>

캐시된 컨테이너 이미지의 Amazon Elastic Block Store(EBS) 스냅샷을 만들고이 스냅샷을 EKS 작업자 노드에 재사용할 수 있습니다. 이렇게 하면 노드 시작 시 로컬에서 이미지를 미리 가져와 포드 초기화 시간을 줄일 수 있습니다. 관리형 노드 그룹에 대해 Karpenter 및 [EKS Terraform 블루프린트를 사용하여 자세한 내용은 Bottlerocket 데이터 볼륨을 사용하여 Amazon EKS에서 컨테이너 시작 시간 단축](https://aws.amazon.com/blogs/containers/reduce-container-startup-time-on-amazon-eks-with-bottlerocket-data-volume/)을 참조하세요. [https://aws-ia.github.io/terraform-aws-eks-blueprints/patterns/machine-learning/ml-container-cache/](https://aws-ia.github.io/terraform-aws-eks-blueprints/patterns/machine-learning/ml-container-cache/) 

자세한 내용은 AI on EKS 워크숍의 [컨테이너 스냅샷 생성기 사용](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](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 또는 배포)를 사용하여 노드에 컨테이너 이미지를 미리 끌어와 노드의 컨테이너 런타임 캐시를 채울 수 있습니다. 컨테이너 런타임 캐시는 컨테이너 런타임에서 관리하는 로컬 스토리지입니다(예: 레지스트리에서 가져온 후 이미지가 저장되는 [컨테이너형](https://containerd.io/) 스토리지입니다. 사전 풀링을 통해 로컬에서 이미지를 사용할 수 있으므로 포드 시작 중에 다운로드 지연이 발생하지 않습니다. 이 접근 방식은 이미지가 자주 변경되거나(예: 자주 업데이트), EBS 스냅샷이 미리 구성되지 않거나, EBS 볼륨을 빌드하는 데 컨테이너 레지스트리에서 직접 가져오는 것보다 시간이 많이 걸리거나, 노드가 이미 클러스터에 있고 여러 가능한 이미지 중 하나를 사용하여 온디맨드로 포드를 가동해야 하는 경우에 특히 유용합니다.

모든 변형을 미리 풀링하면 필요한 이미지에 관계없이 빠르게 시작할 수 있습니다. 예를 들어 10가지 기술을 사용하여 구축된 100,000개의 소형 모델이 필요한 대규모 병렬 ML 워크로드에서 대규모 클러스터(예: 수천 개의 노드)에서 DaemonSet를 통해 10개의 이미지를 미리 풀링하면 포드 시작 시간이 최소화되어 온디맨드 풀을 방지하여 10초 이내에 완료할 수 있습니다. 컨테이너 런타임 캐시 접근 방식을 사용하면 EBS 스냅샷을 관리할 필요가 없으며, 항상 DaemonSets를 사용하여 최신 컨테이너 이미지 버전을 얻을 수 있지만 노드가 스케일 인/아웃되는 실시간 추론 워크로드의 경우 Cluster Autoscaler와 같은 도구가 추가한 새 노드는 미리 풀링된 DaemonSet가 이미지 풀링을 완료하기 전에 워크로드 포드를 예약할 수 있습니다. 이로 인해 새 노드의 초기 포드가 풀을 트리거하여 시작이 지연되고 지연 시간이 짧은 요구 사항에 영향을 미칠 수 있습니다. 또한 kubelet 이미지 가비지 수집은 디스크 사용량이 특정 임계값을 초과하거나 구성된 최대 미사용 기간을 초과할 때 미사용 이미지를 제거하여 미리 풀링된 이미지에 영향을 미칠 수 있습니다. 스케일 인/아웃 패턴에서는 유휴 노드에서 이미지를 제거할 수 있으므로 후속 스케일 업 중에 다시 풀링하고 버스트 워크로드에 대한 캐시의 신뢰성을 줄여야 합니다.

컨테이너 런타임 캐시로 이미지를 미리 풀링하는 예제는 [AWS GitHub 리포지토리](https://github.com/aws-samples/aws-do-eks/tree/main/Container-Root/eks/deployment/prepull)를 참조하세요.

## kubelet 및 컨테이너형 스토리지용 NVMe 고려
<a name="_consider_nvme_for_kubelet_and_containerd_storage"></a>

디스크 성능을 높이기 `containerd` 위해 임시 NVMe 인스턴스 스토리지 디스크를 사용하도록 `kubelet` 및를 구성하는 것이 좋습니다. 컨테이너 풀 프로세스에는 레지스트리에서 컨테이너 이미지를 다운로드하고 해당 계층을 사용 가능한 형식으로 압축 해제하는 작업이 포함됩니다. 압축 해제 중에 I/O 작업을 최적화하려면 컨테이너 호스트의 인스턴스 유형에 더 높은 수준의 I/O 성능과 처리량을 제공하는 요소, 즉 로컬 스토리지[가 있는 NVMe 지원 인스턴스](https://docs.aws.amazon.com/en_us/documentdb/latest/developerguide/db-instance-nvme.html)와 EBS 볼륨 IOPS/처리량을 비교하여 평가해야 합니다. NVMe 로컬 스토리지가 있는 EC2 인스턴스의 경우 더 높은 수준의 I/O 성능 및 처리량을 위해 임시 NVMe 인스턴스 스토리지 디스크를 사용하도록 kubelet(`/var/lib/kubelet`), containerd(`/var/lib/containerd`) 및 Pod 로그(`/var/log/pods`)에 대한 노드의 기본 파일 시스템을 구성하는 것이 좋습니다.

노드에 다운로드되는 임시 스토리지 및 컨테이너 이미지를 요청하는 포드 간에 노드의 임시 스토리지를 공유할 수 있습니다. Bottlerocket 또는 AL2023 EKS 최적화 AMIs와 함께 Karpenter를 사용하는 경우 instanceStorePolicy를 [RAID0](https://docs.aws.amazon.com/ebs/latest/userguide/raid-config.html)으로 설정하거나 관리형 노드 그룹을 사용하는 경우 NodeConfig의 localStoragePolicy를 사용자 데이터의 일부로 설정하여 [EC2NodeClass](https://karpenter.sh/docs/concepts/nodeclasses/#specinstancestorepolicy)에서 구성할 수 있습니다. [NodeConfig](https://eksctl.io/usage/node-bootstrapping/#configuring-the-bootstrapping-process) 