View a markdown version of this page

使用 CLIs 為 AI/ML 工作負載設定 Amazon EKS 叢集 - Amazon EKS

協助改進此頁面

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

若要為本使用者指南貢獻內容,請點選每個頁面右側面板中的在 GitHub 上編輯此頁面連結。

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

使用 CLIs 為 AI/ML 工作負載設定 Amazon EKS 叢集

提示

註冊即將舉行的 Amazon EKS AI/ML 研討會。

本節將逐步引導您建立透過 CLI 命令在 Amazon EKS 上執行訓練或推論工作負載所需的基礎設施。這些步驟包括建立 EKS 叢集、使用 EKS Auto Mode 或 Karpenter 啟用 GPU 的節點、使用 Prometheus 和 Grafana 的監控堆疊,以及用於模型權重的 Amazon S3 儲存。

如需這些功能如何在 EKS 叢集中佈建和自動擴展 EC2 執行個體的詳細資訊,請參閱 EKS Auto ModeKarpenter 的文件。 EC2

高階架構和工作流程

高階架構顯示具有 Karpenter NodeClass 和 NodePool 的 EKS 叢集、寫入 Amazon Managed Service for Prometheus 的 Grafana 和 Prometheus 監控堆疊、用於模型權重的 Amazon S3 儲存貯體,以及編號工作流程步驟

圖表顯示本節設定的 AWS 高階架構。右側的編號步驟指出您在以下步驟中完成組態的順序。

先決條件

  • kubectl >= 1.35。如需設定說明,請參閱 設定 kubectl 和 eksctl

  • AWS CLI >= 2.27。如需設定說明,請參閱安裝

  • Helm >= 3.14。如需設定說明,請參閱設定 Helm

  • jq。 如需設定說明,請參閱下載 jq

  • eksctl >= 0.227.0。如需設定說明,請參閱 eksctl 文件中的安裝

驗證您的eksctl版本:

eksctl version

如果您使用的版本早於 0.227.0,請遵循 eksctl 安裝指南升級至最新版本。

設定環境變數

在這些步驟中保持以下叢集名稱和 AWS 區域一致。變更它可能會導致後續命令以錯誤的 EKS 叢集為目標。

export CLUSTER_NAME=ai-eks-docs export AWS_REGION=us-east-2

使用所有可用的可用 AZs 可改善容錯能力,並增加取得 GPU 容量的機會:

export AZS=$(aws ec2 describe-availability-zones \ --region ${AWS_REGION} \ --query "AvailabilityZones[?ZoneId!='use1-az3' && ZoneId!='usw1-az2' && ZoneId!='cac1-az3'].ZoneName" \ --output text | tr '\t' ',') echo $AZS
重要

cac1-az3 排除可用區域 use1-az3、 和 usw1-az2,因為 Amazon EKS 不支援在這些區域中放置控制平面。在任何這些區域中建立具有子網路的叢集會導致 UnsupportedAvailabilityZoneException

預期的輸出結果:

us-east-2a,us-east-2b,us-east-2c

輸出中的 AZs 會因區域而異。此範例顯示 us-east-2區域的可用 AZs。

建立叢集和 GPU NodePool

本節提供兩種建立 EKS 叢集和 GPU 節點的路徑,如下圖所示。在整個指南中僅選擇一個選項。

  • EKS Auto Mode — 除了核心聯網、儲存和負載平衡附加元件之外,EKS Auto Mode 還包含和管理訓練和推論工作負載的下列功能:EKS 節點監控代理程式、自動節點修復、快速容器提取的 SOCI 快照器,以及預設 NodeClass 的 GPU 準備程度。NVIDIA 裝置外掛程式包含在 Bottlerocket 加速 AMI 中,EKS Auto Mode 用於已啟用 GPU 的節點。

  • 自我管理 Karpenter:在沒有 EKS Auto Mode 的 EKS 叢集上,您必須負責安裝和設定訓練和推論工作負載所需的元件。這包括聯網附加元件 (VPC CNI、CoreDNS、kube-proxy)、Karpenter、EKS 節點監控代理程式、NVIDIA 裝置外掛程式,以及用於快速容器提取的 SOCI 快照器。

EKS 叢集選項:EKS Auto Mode 和自我管理 Karpenter

兩個叢集選項的Side-by-side比較:具有 NodePool 的 EKS Auto Mode 叢集,以及具有自我管理 Karpenter、CoreDNS、VPC CNI、NVIDIA 裝置外掛程式、EKS Pod Identity Agent、Node Monitoring Agent、kube-proxy 和 NodeClass 和 NodePool 的 EKS 標準叢集

在下列每個步驟中,選擇路徑 (EKS Auto Mode、Karpenter) 並完全遵循。完成所選路徑的步驟後,您將擁有具有 GPU NodePool 的 EKS 叢集,準備好排程 GPU 工作負載。

步驟 1:建立叢集

首先建立 EKS 叢集,並安裝 GPU 工作負載所需的叢集元件。

使用 EKS Auto Mode 時,單一eksctl create cluster --enable-auto-mode命令會佈建適用於 GPU 工作負載的 EKS 叢集。

使用自我管理的 Karpenter,eksctl create cluster命令會佈建核心聯網附加元件,然後需要額外的步驟,才能透過 Karpenter 功能閘道啟用自動節點修復、安裝 EKS 節點監控代理程式,以及安裝 NVIDIA 裝置外掛程式。

EKS Auto Mode

建立 EKS Auto Mode 叢集

eksctl create cluster \ --name=$CLUSTER_NAME \ --region=$AWS_REGION \ --enable-auto-mode \ --version=1.35 \ --zones=$AZS

此命令需要幾分鐘的時間才能完成。完成後, eksctl會自動更新您的 kubeconfig 檔案,以使用新佈建的叢集。驗證叢集是否正常運作:

kubectl get pods --all-namespaces

預期的輸出結果:

NAMESPACE NAME READY STATUS RESTARTS AGE kube-system metrics-server-55cf976ddd-cz2mw 1/1 Running 0 3m kube-system metrics-server-55cf976ddd-wrjvv 1/1 Running 0 3m

在 EKS Auto 模式中,VPC CNI、kube-proxy 和 CoreDNS 會以受管元件的形式執行,而不會在 中顯示為 Podkube-system

Self-managed Karpenter

將 Helm 驗證為公有 ECR

eksctl 從 Amazon Public ECR 提取 Karpenter Helm Chart。在建立叢集之前進行驗證,以避免 Helm 安裝步驟發生 403 錯誤:

aws ecr-public get-login-password --region us-east-1 \ | helm registry login --username AWS --password-stdin public.ecr.aws

Public ECR 是在 中託管的全域服務us-east-1。無論您的 EKS 叢集位於哪個區域,都可以--region us-east-1在此處使用 。

預期的輸出: Login Succeeded

使用 Karpenter 建立 EKS 叢集

將您的 Karpenter 版本存放在 環境變數中,以供日後使用。如需最新的 Karpenter 版本,請參閱 GitHub 上的 Karpenter 版本

export KARPENTER_VERSION=1.12.0
cat << EOF > /tmp/cluster-karpenter.yaml apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: ${CLUSTER_NAME} region: ${AWS_REGION} version: "1.35" tags: karpenter.sh/discovery: ${CLUSTER_NAME} availabilityZones: [$(echo $AZS | sed 's/,/, /g')] autoModeConfig: enabled: false iam: withOIDC: true karpenter: version: "${KARPENTER_VERSION}" withSpotInterruptionQueue: true managedNodeGroups: - name: system instanceType: m6i.2xlarge desiredCapacity: 2 minSize: 2 maxSize: 3 labels: node-role: system tags: karpenter.sh/discovery: ${CLUSTER_NAME} addons: - name: eks-pod-identity-agent - name: eks-node-monitoring-agent EOF eksctl create cluster -f /tmp/cluster-karpenter.yaml

此命令大約需要 15 分鐘。它使用專用於託管附加元件和 Karpenter 控制器的受管節點群組來建立 EKS 叢集。Karpenter 安裝時已啟用 Spot 中斷佇列,因此可以處理 Spot 中斷和重新平衡建議。autoModeConfig.enabled: false 設定會明確表示此叢集不使用 EKS Auto 模式,因此在此路徑中安裝的 Karpenter 元件負責節點管理。

叢集也會取得安裝為 EKS 附加元件的 EKS Pod Identity Agent 和 EKS 節點監控代理程式。本指南稍後會使用 EKS Pod Identity。EKS 節點監控代理程式會在每個節點上執行KernelReady,並讀取核心日誌以設定節點條件,例如 AcceleratedHardwareReady、 和 NetworkingReady,Karpenter 自動節點修復會使用這些條件來決定何時取代運作狀態不佳的節點。

驗證叢集是否正常運作:

kubectl get pods --all-namespaces

預期的輸出包括 Karpenter、CoreDNS、kube-proxy、aws-node (VPC CNI)、EKS Pod Identity Agent 和 EKS 節點監控代理程式。

NAMESPACE NAME READY STATUS RESTARTS AGE karpenter karpenter-567547464c-s6vkx 1/1 Running 0 3m40s karpenter karpenter-567547464c-x7gmw 1/1 Running 0 3m40s kube-system aws-node-b6gf2 2/2 Running 0 12m kube-system aws-node-lcphh 2/2 Running 0 12m kube-system coredns-7d4dcbf4fb-ccvrr 1/1 Running 0 16m kube-system coredns-7d4dcbf4fb-qbhk2 1/1 Running 0 16m kube-system eks-node-monitoring-agent-h79vm 1/1 Running 0 9m45s kube-system eks-node-monitoring-agent-tf4dw 1/1 Running 0 9m45s kube-system eks-pod-identity-agent-5jbtc 1/1 Running 0 12m kube-system eks-pod-identity-agent-rwcrc 1/1 Running 0 12m kube-system kube-proxy-p4bmq 1/1 Running 0 12m kube-system kube-proxy-v5nwr 1/1 Running 0 12m kube-system metrics-server-5b966ff79c-hr58p 1/1 Running 0 9m22s kube-system metrics-server-5b966ff79c-szs2d 1/1 Running 0 9m22s

啟用自動節點修復

EKS Auto Mode 預設會啟用自動節點修復。在自我管理的 Karpenter 上,自動節點修復會鎖定在NodeRepair=true特徵閘道後方,且必須明確啟用。下列命令會修補 Karpenter 部署以新增NodeRepair=true功能閘道。更新部署環境會觸發 Karpenter Pod 的推展:

kubectl set env deployment/karpenter -n karpenter \ FEATURE_GATES=NodeRepair=true

預期的輸出結果:

deployment.apps/karpenter env updated

等待 Karpenter Pod 推出:

kubectl rollout status deployment/karpenter -n karpenter

安裝 NVIDIA 裝置外掛程式

EKS 最佳化 AL2023 AMI 不包含 NVIDIA 裝置外掛程式 (不同於 EKS Auto Mode 使用的 Bottlerocket AMI)。透過 Helm 安裝它,讓 GPU 資源可與叢集上的 Pod 搭配使用。

helm repo add nvdp https://nvidia.github.io/k8s-device-plugin helm repo update
cat << 'EOF' > /tmp/nvdp-values.yaml mofedEnabled: false nodeSelector: amiFamily: al2023 gfd: enabled: true nfd: worker: tolerations: - operator: "Exists" EOF
helm install nvidia-device-plugin nvdp/nvidia-device-plugin \ --namespace kube-system \ -f /tmp/nvdp-values.yaml
  • mofedEnabled: false:停用不使用的 Mellanox OFED (InfiniBand) 檢查 AWS

  • nodeSelector.amiFamily: al2023:僅將 DaemonSet 範圍限定為 AL2023 節點 (Bottlerocket 已內建外掛程式)

  • gfd.enabled: true:啟用 GPU 功能探索標籤 (nvidia.com/gpu.productnvidia.com/gpu.memory等)

確認已安裝 NVIDIA 裝置外掛程式。預期在佈建具有相符標籤的 GPU NodePool 之前,沒有任何裝置外掛程式 Pod。

kubectl get daemonset nvidia-device-plugin -n kube-system

預期的輸出結果:

NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE nvidia-device-plugin 0 0 0 0 0 amiFamily=al2023 2m5s
警告

對於 EKS Auto Mode 和自我管理的 Karpenter 路徑,自動節點修復的行為與 NodePools 佈建的節點相同。EKS Auto Mode 和 Karpenter 中的自動節點修復是一種強勢中斷方法,可略過 PodDisruptionBudgets、karpenter.sh/do-not-disrupt註釋和 terminationGracePeriod。自動節點修復會等待 10 分鐘,再將AcceleratedHardwareReady條件設為 的節點取代為 False,將其他修復條件取代為 30 分鐘。

步驟 2:建立動態 GPU NodePool

使用 Spot 容量搭配隨需做為備用,定義可動態佈建產生大於 4 的 G 系列 GPU 執行個體的 NodePool。EKS Auto Mode 和 Karpenter 路徑都使用相同的 NodePool API,唯一的區別是其指向的 NodeClass。在 EKS Auto 模式中,綁定的 default NodeClass 已選取正確的 AMI 並設定 SOCI 平行提取,因此 NodePool 是您建立的唯一物件。在自我管理的 Karpenter 中,您也需要可EC2NodeClass固定 AMI 並調校 SOCI 的自訂。

EKS Auto Mode

在 EKS Auto 模式中,綁定的 default NodeClass 會自動選取 GPU 執行個體的 Bottlerocket AMI,其中包括預先安裝的 NVIDIA 驅動程式、NVIDIA 裝置外掛程式和 SOCI 平行提取。您只需要套用參考 NodeClass 的 default NodePool: NodeClass

cat << 'EOF' | kubectl apply -f - apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: gpu-inf spec: template: metadata: labels: guide: ai-eks-docs spec: nodeClassRef: group: eks.amazonaws.com kind: NodeClass name: default taints: - key: nvidia.com/gpu effect: NoSchedule requirements: - key: karpenter.sh/capacity-type operator: In values: ["spot", "on-demand"] - key: eks.amazonaws.com/instance-category operator: In values: ["g"] - key: eks.amazonaws.com/instance-generation operator: Gt values: ["4"] - key: kubernetes.io/arch operator: In values: ["amd64"] limits: cpu: 1000 memory: 5000Gi EOF

此 NodePool 會佈建產生大於 4 的 G 系列 GPU 執行個體 (G5G6eG7e 等)。nvidia.com/gpu:NoSchedule 污點可確保只會在這些節點上排程符合 GPU 資格的 Pod。

Self-managed Karpenter

自我管理的 Karpenter 不包含預設 NodeClass。您首先會建立 EC2NodeClass 來鎖定 EKS 最佳化 NVIDIA AL2023 AMI 別名、透過FastImagePull功能閘道啟用 SOCI,並設定 instanceStorePolicy: RAID0將容器化映像快取移至本機 NVMe。然後,您可以建立參考它的 NodePool。

建立 EC2NodeClass

cat << EOF | kubectl apply -f - apiVersion: karpenter.k8s.aws/v1 kind: EC2NodeClass metadata: name: gpu-inf labels: guide: ai-eks-docs spec: role: "eksctl-KarpenterNodeRole-${CLUSTER_NAME}" amiSelectorTerms: - alias: al2023@latest subnetSelectorTerms: - tags: karpenter.sh/discovery: ${CLUSTER_NAME} securityGroupSelectorTerms: - tags: karpenter.sh/discovery: ${CLUSTER_NAME} tags: karpenter.sh/discovery: ${CLUSTER_NAME} instanceStorePolicy: RAID0 userData: | MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="BOUNDARY" --BOUNDARY Content-Type: application/node.eks.aws --- apiVersion: node.eks.aws/v1alpha1 kind: NodeConfig spec: featureGates: FastImagePull: true containerd: config: | [plugins."io.containerd.snapshotter.v1.soci"] [plugins."io.containerd.snapshotter.v1.soci".blob] max_concurrent_downloads_per_image = 20 concurrent_download_chunk_size = "16mb" max_concurrent_unpacks_per_image = 12 discard_unpacked_layers = true --BOUNDARY-- EOF

instanceStorePolicy: RAID0 將本機 NVMe 磁碟組合成 RAID-0 陣列。al2023@latest AMI 別名解析為 EKS 最佳化 AL2023 AMI。當 Karpenter 啟動 GPU 執行個體類型時,會自動選取 AL2023_x86_64_NVIDIA 加速變體,其中包含預先安裝的 NVIDIA 驅動程式。

FastImagePull 功能閘道啟用 SOCI 快照器平行提取模式,可同時下載和解壓縮映像層。這符合 G、P 和 Trn 執行個體系列中的 EKS 自動模式行為。containerd.config 區塊會調校 ECR 託管映像的 SOCI 快照器:

  • max_concurrent_downloads_per_image: 20 每個映像最多允許平行下載 20 層。Bottlerocket 預設為 3,AL2023 為 20。ECR 的建議值。

  • concurrent_download_chunk_size: "16mb" 會將每個圖層分割為透過 HTTP 範圍請求平行下載的 16 MB 區塊。建議用於支援範圍 GETs登錄檔 (ECR 會這麼做)。

  • max_concurrent_unpacks_per_image: 12 一次解壓縮最多 12 個層。Bottlerocket 預設為 1,AL2023 為 12。

  • discard_unpacked_layers: true 會在解壓縮後刪除壓縮層 Blob,以節省磁碟空間。

如需更多 SOCI 調校選項 (每個映像的並行下載、區塊大小等),請參閱 Karpenter SOCI 藍圖

驗證 EC2NodeClass:

kubectl get ec2nodeclass gpu-inf

預期的輸出:READY True。如果為 False,請執行kubectl describe ec2nodeclass gpu-inf並檢查遺失子網路或安全群組標籤的條件。

建立 GPU NodePool

cat << EOF | kubectl apply -f - apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: gpu-inf spec: template: metadata: labels: guide: ai-eks-docs amiFamily: al2023 spec: nodeClassRef: group: karpenter.k8s.aws kind: EC2NodeClass name: gpu-inf taints: - key: nvidia.com/gpu effect: NoSchedule requirements: - key: karpenter.sh/capacity-type operator: In values: ["spot", "on-demand"] - key: karpenter.k8s.aws/instance-category operator: In values: ["g"] - key: karpenter.k8s.aws/instance-generation operator: Gt values: ["4"] - key: kubernetes.io/arch operator: In values: ["amd64"] limits: cpu: 1000 memory: 5000Gi EOF

節點範本上的amiFamily: al2023標籤是 NVIDIA 裝置外掛程式 DaemonSet 用來選取這些節點的標籤。

驗證已建立 NodePool:

kubectl get nodepool gpu-inf

預期的輸出結果:

NAME NODECLASS NODES READY AGE gpu-inf default 0 True 8s

在自我管理 Karpenter 路徑上,NODECLASS 欄會顯示 gpu-inf而非 default

步驟 3:使用範例 Pod 進行測試

使用 Pod 測試 GPU NodePool nvidia-smi 設定。

cat << EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: nvidia-smi labels: guide: ai-eks-docs spec: tolerations: - key: "nvidia.com/gpu" operator: "Exists" effect: "NoSchedule" containers: - name: nvidia-smi image: public.ecr.aws/amazonlinux/amazonlinux:2023-minimal command: ["nvidia-smi"] resources: limits: nvidia.com/gpu: 1 restartPolicy: OnFailure EOF

確認 Pod 已排程並成功完成。

kubectl get pods

預期的輸出結果:

NAME READY STATUS RESTARTS AGE nvidia-smi 0/1 Completed 0 67s

STATUS: 已完成表示 nvidia-smi 命令已執行並結束。檢查 Pod 日誌以查看節點偵測到的 GPU。

kubectl logs nvidia-smi

預期的輸出結果:

+-----------------------------------------------------------------------------------------+ | NVIDIA-SMI 580.126.09 Driver Version: 580.126.09 CUDA Version: 13.0 | +-----------------------------------------+------------------------+----------------------+ | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |=========================================+========================+======================| | 0 NVIDIA RTX PRO 6000 Blac... On | 00000000:2B:00.0 Off | 0 | | N/A 30C P0 81W / 600W | 0MiB / 97887MiB | 0% Default | | | | Disabled | +-----------------------------------------+------------------------+----------------------+

輸出會顯示 GPU 模型、驅動程式版本、CUDA 版本和可用的記憶體。在此範例中,Karpenter 佈建了具有 NVIDIA RTX PRO 6000 Blackwell GPU 和 96 GB 記憶體的 G7e 執行個體。30C 是目前的 GPU 溫度,P0 表示 GPU 處於最高效能狀態 (閒置但就緒)。81W / 600W 顯示目前的耗電量與最大耗電量,而 0MiB / 97887MiB 顯示目前使用的 GPU 記憶體與可用的總容量。由於 Pod 剛執行 nvidia-smi 並結束,因此沒有工作負載使用 GPU,因此記憶體為 0,且電源處於閒置狀態。NVIDIA GPU 驅動程式版本 (580.126.09) 來自 Bottlerocket AMI,而 CUDA 版本 (13.0) 來自容器映像。GPU 模型和記憶體會根據 Karpenter 選取的執行個體類型而有所不同。G5 執行個體具有 NVIDIA A10G GPUs (24 GB)、G6e 執行個體具有 NVIDIA L40S GPUs (48 GB),而 G7e 執行個體具有 NVIDIA RTX PRO 6000 GPUs (96 GB)。

若要了解 Karpenter 和 Kubernetes 排程器如何協調以佈建節點並放置 Pod,請檢查 Pod 的生命週期事件:

kubectl describe po nvidia-smi

預期的輸出結果:

Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 60s default-scheduler 0/2 nodes are available: 2 node(s) had untolerated taint(s). no new claims to deallocate, preemption: 0/2 nodes are available: 2 Preemption is not helpful for scheduling. Normal Nominated 59s eks-auto-mode/compute Pod should schedule on: nodeclaim/gpu-inf-vxcnj Normal Scheduled 24s default-scheduler Successfully assigned default/nvidia-smi to i-0fb17a09bc4203164 Warning FailedCreatePodSandBox 21s kubelet Failed to create pod sandbox: rpc error: code = Unknown desc = failed to setup network for sandbox "7f85e25b220c8fb245187758dbbbc8efb3d40f3e49e13054404880daf4c3b2f0": plugin type="aws-cni" name="aws-cni" failed (add): add cmd: failed to setup network policy Normal Pulling 7s kubelet spec.containers{nvidia-smi}: Pulling image "public.ecr.aws/amazonlinux/amazonlinux:2023-minimal" Normal Pulled 5s kubelet spec.containers{nvidia-smi}: Successfully pulled image "public.ecr.aws/amazonlinux/amazonlinux:2023-minimal" in 1.237s (1.237s including waiting). Image size: 37442701 bytes. Normal Created 5s kubelet spec.containers{nvidia-smi}: Container created Normal Started 5s kubelet spec.containers{nvidia-smi}: Container started

這些事件會顯示 Pod 排程序列:Pod 一開始無法排程,因為沒有 GPU 節點 (FailedScheduling)、Karpenter 會指定新的 NodeClaim (Nominated)、排程器會在節點就緒時指派 Pod (排程),然後提取並啟動容器映像。EKS Auto Mode 在 G、P 和 Trn 執行個體上安裝並設定 SOCI (可擴展的 OCI) 平行提取。請注意,由於 SOCI 平行提取,容器映像是在 2 秒 (1.237 秒) 內從 ECR 提取。

NodeClaim 是 Karpenter 建立來佈建特定節點的請求。它會顯示執行個體類型、容量類型、AZ,以及節點是否已就緒。

kubectl get nodeclaims

預期的 NodeClaim 輸出:

NAME            TYPE          CAPACITY    ZONE         NODE                  READY   AGE
gpu-inf-xxxxx   g7e.2xlarge   spot        us-east-2a   i-0xxxxxxxxxxxx       True    2m

執行個體類型和 AZ 會有所不同。產生 > 4 的任何 G 系列執行個體都符合資格。

中的FailedCreatePodSandBox警告kubectl describe pod nvidia-smi是暫時性且預期的。VPC CNI 會在節點聯結後以非同步方式初始化,而 kubelet 會自動重試。如果 Pod 保留在 中ContainerCreating,請使用 檢查節點事件kubectl describe node <node-name>

提示

如果沒有出現節點,請檢查容量不足錯誤:

kubectl get events | grep InsufficientCapacityError

Karpenter 快取無法使用的方案 3 分鐘。擴大 NodePool 中允許的執行個體類型和可用AZs會增加登陸容量的機會。

注意

Karpenter 啟動的 Spot 執行個體不會出現在 EC2 Spot 請求主控台中。Karpenter 搭配 使用 EC2 CreateFleet APItype: instant。執行個體會以spot生命週期顯示在 EC2 執行個體主控台中。

步驟 4:將預留容量新增至 NodePool (選用)

若要先搭配 Spot/隨需備用使用預留容量,請建立 ODCR 並將其連接至 NodeClass,然後從步驟 2 更新動態 NodePool,以允許reserved容量。兩個路徑的保留 API 呼叫相同;NodeClass 連接不同,因為 EKS Auto Mode 和自我管理 Karpenter 使用不同的 NodeClass 類型。

警告

下列命令會產生預留執行個體類型的費用,直到您使用 將其取消為止aws ec2 cancel-capacity-reservation --capacity-reservation-id <id>

建立容量保留:

CR_AZ="us-east-2a" INSTANCE_TYPE="g6e.4xlarge" aws ec2 create-capacity-reservation \ --instance-type $INSTANCE_TYPE \ --instance-platform Linux/UNIX \ --availability-zone "$CR_AZ" \ --instance-count 1 \ --instance-match-criteria open \ --end-date-type unlimited

如果您收到InsufficientInstanceCapacity錯誤,CR_AZ請變更為不同的可用區域並重試。

查詢容量保留 ID,並將其存放在 shell 變數中,以進行下列步驟:

CAPACITY_RESERVATION_ID=$(aws ec2 describe-capacity-reservations \ --filters "Name=state,Values=active" "Name=instance-type,Values=${INSTANCE_TYPE}" \ --query 'CapacityReservations[0].CapacityReservationId' \ --output text \ --region ${AWS_REGION}) echo "Capacity reservation ID: ${CAPACITY_RESERVATION_ID}"

然後將 NodeClass 和 NodePool 變更套用至您的路徑:

EKS Auto Mode

在 EKS Auto 模式中,綁定的 default NodeClass 是唯讀的,因此請建立參考保留的自訂 NodeClass,然後更新 NodePool 以指向 NodeClass,並將reserved容量新增至capacity-type清單。

NODE_ROLE=$(kubectl get nodeclass default -o jsonpath='{.spec.role}') cat << EOF | kubectl apply -f - apiVersion: eks.amazonaws.com/v1 kind: NodeClass metadata: name: gpu-inf labels: guide: ai-eks-docs spec: role: "$NODE_ROLE" subnetSelectorTerms: - tags: alpha.eksctl.io/cluster-name: "$CLUSTER_NAME" kubernetes.io/role/internal-elb: "1" securityGroupSelectorTerms: - tags: aws:eks:cluster-name: "$CLUSTER_NAME" capacityReservationSelectorTerms: - id: "$CAPACITY_RESERVATION_ID" EOF

kubernetes.io/role/internal-elb: "1"標籤可確保節點僅在私有子網路中啟動。

更新 NodePool 以使用 ODCR 支援的 NodeClass,並包含 reserved做為容量類型:

cat << EOF | kubectl apply -f - apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: gpu-inf spec: template: metadata: labels: guide: ai-eks-docs spec: nodeClassRef: group: eks.amazonaws.com kind: NodeClass name: gpu-inf taints: - key: nvidia.com/gpu effect: NoSchedule requirements: - key: karpenter.sh/capacity-type operator: In values: ["spot", "on-demand", "reserved"] - key: eks.amazonaws.com/instance-category operator: In values: ["g"] - key: eks.amazonaws.com/instance-generation operator: Gt values: ["4"] - key: kubernetes.io/arch operator: In values: ["amd64"] limits: cpu: 1000 memory: 5000Gi EOF
Self-managed Karpenter

對於自我管理的 Karpenter,重新套用EC2NodeClass您在步驟 2 中建立並capacityReservationSelectorTerms新增的 。欄位名稱和形狀符合其他索引標籤中NodeClass顯示的 EKS Auto 模式。

cat << EOF | kubectl apply -f - apiVersion: karpenter.k8s.aws/v1 kind: EC2NodeClass metadata: name: gpu-inf labels: guide: ai-eks-docs spec: role: "eksctl-KarpenterNodeRole-${CLUSTER_NAME}" amiSelectorTerms: - alias: al2023@latest subnetSelectorTerms: - tags: karpenter.sh/discovery: ${CLUSTER_NAME} securityGroupSelectorTerms: - tags: karpenter.sh/discovery: ${CLUSTER_NAME} tags: karpenter.sh/discovery: ${CLUSTER_NAME} instanceStorePolicy: RAID0 capacityReservationSelectorTerms: - id: "$CAPACITY_RESERVATION_ID" userData: | MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="BOUNDARY" --BOUNDARY Content-Type: application/node.eks.aws --- apiVersion: node.eks.aws/v1alpha1 kind: NodeConfig spec: featureGates: FastImagePull: true containerd: config: | [plugins."io.containerd.snapshotter.v1.soci"] [plugins."io.containerd.snapshotter.v1.soci".blob] max_concurrent_downloads_per_image = 20 concurrent_download_chunk_size = "16mb" max_concurrent_unpacks_per_image = 12 discard_unpacked_layers = true --BOUNDARY-- EOF

從步驟 2 的唯一變更是新capacityReservationSelectorTerms欄位。所有其他欄位保持不變。

更新 NodePool 以包含 reserved做為容量類型:

cat << EOF | kubectl apply -f - apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: gpu-inf spec: template: metadata: labels: guide: ai-eks-docs amiFamily: al2023 spec: nodeClassRef: group: karpenter.k8s.aws kind: EC2NodeClass name: gpu-inf taints: - key: nvidia.com/gpu effect: NoSchedule requirements: - key: karpenter.sh/capacity-type operator: In values: ["spot", "on-demand", "reserved"] - key: karpenter.k8s.aws/instance-category operator: In values: ["g"] - key: karpenter.k8s.aws/instance-generation operator: Gt values: ["4"] - key: kubernetes.io/arch operator: In values: ["amd64"] limits: cpu: 1000 memory: 5000Gi EOF

Karpenter reserved將 視為最具成本效益的選項,並優先啟動。一旦保留已滿,就會回到 Spot 或隨需。

套用變更後,請驗證 Karpenter 是否排定保留容量的優先順序,並回到 Spot 或隨需。部署 2 個複本部署,每個 Pod 請求 1 個 GPU。ODCR 適用於 1 個執行個體,因此第一個 Pod 會觸發 Karpenter 啟動預留節點。第二個 Pod 無法容納在預留節點上,並觸發 Karpenter 從 Spot 或隨需容量啟動另一個節點。

cat << 'EOF' | kubectl apply -f - apiVersion: apps/v1 kind: Deployment metadata: name: gpu-overflow-test labels: guide: ai-eks-docs spec: replicas: 2 selector: matchLabels: app: gpu-overflow-test template: metadata: labels: app: gpu-overflow-test guide: ai-eks-docs spec: tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule containers: - name: nvidia-smi image: public.ecr.aws/amazonlinux/amazonlinux:2023-minimal command: ["sh", "-c", "nvidia-smi && sleep infinity"] resources: limits: nvidia.com/gpu: 1 EOF

與執行和結束步驟 3 nvidia-smi的測試 Pod 不同,此部署會保持 Pod 執行 (sleep infinity),以便它們保留 GPU 且不釋放節點。

驗證在不同節點上排程的 Pod:

kubectl get pods -l app=gpu-overflow-test -o wide

預期的輸出結果:

NAME                                 READY   STATUS    RESTARTS   AGE     IP                NODE                  NOMINATED NODE   READINESS GATES
gpu-overflow-test-59b97944fb-lq56c   1/1     Running   0          2m42s   192.168.186.240   i-057692590480155da   <none>           <none>
gpu-overflow-test-59b97944fb-z4zcx   1/1     Running   0          2m42s   192.168.130.64    i-0521ecd1849fa0578   <none>           <none>

兩個 Pod 正在執行中,每個在不同的節點上。

檢查 NodeClaims 以查看容量類型:

kubectl get nodeclaims

預期的輸出結果:

NAME            TYPE          CAPACITY    ZONE         NODE                  READY   AGE
gpu-inf-shg5w   g6e.xlarge    reserved    us-east-2a   i-0ea91fdeef65b8cb6   True    2m2s
gpu-inf-ssnqf   g7e.2xlarge   spot        us-east-2b   i-00ccf7ce65cf3f6ca   True    112s

預留節點會先啟動,然後在保留已滿時啟動 Spot 或隨需節點。

清除測試部署:

kubectl delete deployment gpu-overflow-test

監控

將收集叢集、節點和 GPU 指標的監控堆疊安裝到 Amazon Managed Service for Prometheus (AMP),並使用 Grafana 將其視覺化。kube-prometheus-stack Helm Chart 會將 Prometheus 部署到 AMP 的湊集和遠端寫入指標,以及儀表板的自我管理 Grafana。NVIDIA DCGM Exporter 新增 GPU 特定的指標 (使用率、記憶體、溫度、功率、NVLink、張量活動)。

Prometheus、Grafana 和運算子預設會落在非 GPU 節點上,因為 GPU nvidia.com/gpu:NoSchedule 節點帶有污點。Node-exporter 和 DCGM Exporter 都會在 GPU 節點上執行,因此我們可以在整個機群中抓取主機和 GPU 指標。

如果您開啟新的終端機,請設定叢集名稱和區域:

export CLUSTER_NAME=ai-eks-docs export AWS_REGION=us-east-2

建立 AMP 工作區

建立 AMP 工作區以存放指標:

aws amp create-workspace \ --alias "amp-ws-${CLUSTER_NAME}" \ --region ${AWS_REGION}

取得工作區 ID:

AMP_WORKSPACE_ID=$(aws amp list-workspaces \ --alias "amp-ws-${CLUSTER_NAME}" \ --query 'workspaces[0].workspaceId' \ --output text \ --region ${AWS_REGION}) echo "AMP Workspace ID: ${AMP_WORKSPACE_ID}"

取得遠端寫入端點:

AMP_ENDPOINT=$(aws amp describe-workspace \ --workspace-id ${AMP_WORKSPACE_ID} \ --query 'workspace.prometheusEndpoint' \ --output text \ --region ${AWS_REGION}) echo "AMP Endpoint: ${AMP_ENDPOINT}"

建立 IAM 政策和 EKS Pod 身分關聯

建立允許 Prometheus 遠端寫入指標和 Grafana 查詢它們的 IAM 政策:

ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) AMP_POLICY_ARN=$(aws iam create-policy \ --policy-name "${CLUSTER_NAME}-amp-grafana-policy" \ --policy-document "{\"Version\": \"2012-10-17\", \"Statement\": [{\"Sid\": \"AllowAMPReadWrite\", \"Effect\": \"Allow\", \"Action\": [\"aps:ListWorkspaces\", \"aps:DescribeWorkspace\", \"aps:GetMetricMetadata\", \"aps:GetSeries\", \"aps:QueryMetrics\", \"aps:RemoteWrite\", \"aps:GetLabels\"], \"Resource\": \"arn:aws:aps:${AWS_REGION}:${ACCOUNT_ID}:workspace/*\"}, {\"Sid\": \"AllowCloudWatchMetrics\", \"Effect\": \"Allow\", \"Action\": [\"cloudwatch:DescribeAlarmsForMetric\", \"cloudwatch:ListMetrics\", \"cloudwatch:GetMetricData\", \"cloudwatch:GetMetricStatistics\"], \"Resource\": \"*\"}]}" \ --query 'Policy.Arn' \ --output text) echo "AMP Policy ARN: ${AMP_POLICY_ARN}"

建立 Prometheus 和 Grafana 的監控命名空間和服務帳戶:

kubectl create namespace monitoring kubectl create serviceaccount amp-iamproxy-ingest-service-account -n monitoring kubectl create serviceaccount grafana-sa -n monitoring

建立 EKS Pod 身分關聯,將服務帳戶連結至 IAM 政策:

eksctl create podidentityassociation \ --cluster ${CLUSTER_NAME} \ --namespace monitoring \ --service-account-name amp-iamproxy-ingest-service-account \ --role-name "${CLUSTER_NAME}-amp-ingest-role" \ --permission-policy-arns ${AMP_POLICY_ARN} \ --region ${AWS_REGION} eksctl create podidentityassociation \ --cluster ${CLUSTER_NAME} \ --namespace monitoring \ --service-account-name grafana-sa \ --role-name "${CLUSTER_NAME}-grafana-role" \ --permission-policy-arns ${AMP_POLICY_ARN} \ --region ${AWS_REGION}

確認已建立兩個 EKS Pod 身分關聯:

eksctl get podidentityassociation --cluster ${CLUSTER_NAME} --region ${AWS_REGION}

預期的輸出應在monitoring命名空間grafana-sa中同時包含 amp-iamproxy-ingest-service-account和 。

安裝 kube-prometheus-stack

新增 Helm 儲存庫:

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm repo update

此值檔案會省略 Prometheus、Grafana 和 運算子的 nodeSelector:GPU nvidia.com/gpu:NoSchedule 節點的污點會使其遠離 GPU 節點,因此預設會落在系統或一般用途集區上。Node-exporter 使用萬用字元公差,因此它在每個節點上執行,包括 GPU 節點,以在整個機群中收集指標。

建立值檔案:

cat << EOF > /tmp/kube-prometheus-values.yaml prometheus: serviceAccount: create: false name: amp-iamproxy-ingest-service-account prometheusSpec: serviceAccountName: amp-iamproxy-ingest-service-account remoteWrite: - url: "${AMP_ENDPOINT}api/v1/remote_write" sigv4: region: "${AWS_REGION}" queueConfig: maxSamplesPerSend: 1000 maxShards: 200 capacity: 2500 retention: 5h scrapeInterval: 30s evaluationInterval: 30s podMonitorSelectorNilUsesHelmValues: false serviceMonitorSelectorNilUsesHelmValues: false alertmanager: enabled: false grafana: enabled: true serviceAccount: create: false name: grafana-sa grafana.ini: auth.sigv4: enabled: true sidecar: datasources: defaultDatasourceEnabled: false plugins: - grafana-amazonprometheus-datasource additionalDataSources: - name: Amazon-Managed-Prometheus type: grafana-amazonprometheus-datasource access: proxy url: "${AMP_ENDPOINT}" isDefault: true jsonData: sigV4Auth: true defaultRegion: "${AWS_REGION}" sigV4Region: "${AWS_REGION}" editable: true dashboardProviders: dashboardproviders.yaml: apiVersion: 1 providers: - name: default orgId: 1 folder: 'GPU Monitoring' type: file disableDeletion: false editable: true options: path: /var/lib/grafana/dashboards/default dashboards: default: nvidia-dcgm: gnetId: 25261 revision: 1 datasource: - name: DS_PROMETHEUS value: Amazon-Managed-Prometheus vllm: gnetId: 25263 revision: 1 datasource: - name: DS_PROMETHEUS value: Amazon-Managed-Prometheus prometheus-node-exporter: tolerations: - operator: Exists EOF

驗證變數是否正確填入:

grep -E "url:|region:|tolerations:" /tmp/kube-prometheus-values.yaml

您應該會看到完整的 AMP 端點 URL (以 開頭https://aps-workspaces…​)、您的區域,以及 node-exporter tolerations:行。如果有任何空白項目,請重新匯出變數並重新建立檔案。

安裝圖表:

helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack \ --namespace monitoring \ -f /tmp/kube-prometheus-values.yaml

驗證 Pod 正在執行:

kubectl get pods -n monitoring

預期的輸出結果:

NAME                                                       READY   STATUS    RESTARTS   AGE
kube-prometheus-stack-grafana-7c58f54f77-rftrj             3/3     Running   0          4m
kube-prometheus-stack-kube-state-metrics-d68dcbc84-5smxq   1/1     Running   0          4m
kube-prometheus-stack-operator-5895df479f-ttm47            1/1     Running   0          4m
kube-prometheus-stack-prometheus-node-exporter-t9q7s       1/1     Running   0          4m
kube-prometheus-stack-prometheus-node-exporter-x6vfb       1/1     Running   0          4m
prometheus-kube-prometheus-stack-prometheus-0              2/2     Running   0          4m

堆疊會部署下列元件:

  • Prometheus (StatefulSet):抓取指標並將其遠端寫入 AMP

  • Grafana:儀表板和視覺化,使用 AMP 資料來源預先設定

  • kube-state-metrics:產生有關 Kubernetes 物件狀態的指標 (Pod 狀態、資源請求/限制、NodeClaim 狀態)

  • node-exporter (DaemonSet,每個節點一個):收集主機層級指標 (CPU、記憶體、磁碟、網路)

  • 運算子:管理 Prometheus 和 Alertmanager 自訂資源

警示管理員在此設定中已停用。

存取 Grafana

開啟單獨的終端機並向前移植以存取 Grafana:

kubectl port-forward svc/kube-prometheus-stack-grafana 3000:80 -n monitoring

在瀏覽器http://localhost:3000中開啟 。從admin下列命令使用使用者名稱和密碼登入:

kubectl --namespace monitoring get secrets kube-prometheus-stack-grafana -o jsonpath="{.data.admin-password}" | base64 -d ; echo

若要驗證指標管道是否端對端運作:

  1. 導覽至連線 > 資料來源,並確認 Amazon-Managed-Prometheus 列為預設資料來源。

    驗證 Grafana 中的 AMP 資料來源

    顯示 Amazon-Managed-Prometheus 列為預設資料來源的 Grafana Connections 頁面
  2. 導覽至向下切入 > 指標並搜尋指標。 up您應該會看到叢集湊集目標的結果。

    驗證 up Grafana 中的指標

    Grafana 向下切入指標頁面顯示綠色狀態列的向上指標,指出作用中的抓取目標

如果 up顯示結果,表示管道 (叢集 → Prometheus → AMP → Grafana) 正在運作。

部署適用於 GPU 指標的 DCGM Exporter

kube-prometheus-stack 會收集節點層級的 CPU 和記憶體指標,但不會收集 GPU 指標。NVIDIA DCGM Exporter 新增 GPU 使用率、記憶體用量、溫度、耗電量、NVLink 頻寬和張量活動。

helm repo add gpu-helm-charts https://nvidia.github.io/dcgm-exporter/helm-charts helm repo update

為您的路徑設定 GPU 節點選擇器金鑰。EKS Auto Mode 和自我管理 Karpenter 使用 GPU 製造商的不同標籤金鑰。

EKS Auto Mode
GPU_NODE_SELECTOR_KEY="eks.amazonaws.com/instance-gpu-manufacturer"
Self-managed Karpenter
GPU_NODE_SELECTOR_KEY="karpenter.k8s.aws/instance-gpu-manufacturer"

建立 DCGM 匯出工具值檔案:

cat << EOF > /tmp/dcgm-exporter-values.yaml resources: requests: memory: "512Mi" cpu: "100m" limits: memory: "1Gi" cpu: "500m" serviceMonitor: enabled: true additionalLabels: release: kube-prometheus-stack nodeSelector: ${GPU_NODE_SELECTOR_KEY}: nvidia tolerations: - key: "nvidia.com/gpu" operator: "Exists" effect: "NoSchedule" customMetrics: | # Clocks DCGM_FI_DEV_SM_CLOCK, gauge, SM clock frequency (in MHz). DCGM_FI_DEV_MEM_CLOCK, gauge, Memory clock frequency (in MHz). # Temperature DCGM_FI_DEV_MEMORY_TEMP, gauge, Memory temperature (in C). DCGM_FI_DEV_GPU_TEMP, gauge, GPU temperature (in C). # Power DCGM_FI_DEV_POWER_USAGE, gauge, Power draw (in W). DCGM_FI_DEV_TOTAL_ENERGY_CONSUMPTION, counter, Total energy consumption since boot (in mJ). # PCIe DCGM_FI_PROF_PCIE_TX_BYTES, counter, Number of bytes transmitted through PCIe TX (in KB) via NVML. DCGM_FI_PROF_PCIE_RX_BYTES, counter, Number of bytes received through PCIe RX (in KB) via NVML. DCGM_FI_DEV_PCIE_REPLAY_COUNTER, counter, Total number of PCIe retries. # Utilization (the sample period varies depending on the product) DCGM_FI_DEV_GPU_UTIL, gauge, GPU utilization (in %). DCGM_FI_DEV_MEM_COPY_UTIL, gauge, Memory utilization (in %). DCGM_FI_DEV_ENC_UTIL, gauge, Encoder utilization (in %). DCGM_FI_DEV_DEC_UTIL, gauge, Decoder utilization (in %). # Errors and violations DCGM_FI_DEV_XID_ERRORS, gauge, Value of the last XID error encountered. DCGM_EXP_XID_ERRORS_COUNT, gauge, Value of count of XID errors encountered. DCGM_FI_DEV_POWER_VIOLATION, counter, Throttling duration due to power constraints (in us). DCGM_FI_DEV_THERMAL_VIOLATION, counter, Throttling duration due to thermal constraints (in us). DCGM_FI_DEV_SYNC_BOOST_VIOLATION, counter, Throttling duration due to sync-boost constraints (in us). DCGM_FI_DEV_BOARD_LIMIT_VIOLATION, counter, Throttling duration due to board limit constraints (in us). DCGM_FI_DEV_LOW_UTIL_VIOLATION, counter, Throttling duration due to low utilization (in us). DCGM_FI_DEV_RELIABILITY_VIOLATION, counter, Throttling duration due to reliability constraints (in us). # Memory usage DCGM_FI_DEV_FB_FREE, gauge, Framebuffer memory free (in MiB). DCGM_FI_DEV_FB_USED, gauge, Framebuffer memory used (in MiB). # Retired pages DCGM_FI_DEV_RETIRED_SBE, counter, Total number of retired pages due to single-bit errors. DCGM_FI_DEV_RETIRED_DBE, counter, Total number of retired pages due to double-bit errors. DCGM_FI_DEV_RETIRED_PENDING, counter, Total number of pages pending retirement. # NVLink DCGM_FI_DEV_NVLINK_BANDWIDTH_TOTAL, counter, Total number of NVLink bandwidth counters for all lanes. DCGM_FI_PROF_NVLINK_TX_BYTES, counter, The rate of data transmitted over NVLink not including protocol headers in bytes per second. DCGM_FI_PROF_NVLINK_RX_BYTES, counter, The rate of data received over NVLink not including protocol headers in bytes per second. # DCP metrics DCGM_FI_PROF_GR_ENGINE_ACTIVE, gauge, Ratio of time the graphics engine is active (in %). DCGM_FI_PROF_SM_ACTIVE, gauge, The ratio of cycles an SM has at least 1 warp assigned (in %). DCGM_FI_PROF_SM_OCCUPANCY, gauge, The ratio of number of warps resident on an SM (in %). DCGM_FI_PROF_PIPE_TENSOR_ACTIVE, gauge, Ratio of cycles the tensor (HMMA) pipe is active (in %). DCGM_FI_PROF_DRAM_ACTIVE, gauge, Ratio of cycles the device memory interface is active sending or receiving data (in %). DCGM_FI_DEV_CLOCK_THROTTLE_REASONS, gauge, Current clock throttle reasons (bitmask of DCGM_CLOCKS_THROTTLE_REASON_*). DCGM_FI_DEV_GPU_NVLINK_ERRORS, gauge, Identifies a GPU NVLink error type returned by DCGM_FI_DEV_GPU_NVLINK_ERRORS. ## NVLink DCGM_FI_DEV_NVLINK_BANDWIDTH_L0, counter, The number of bytes of active NVLink rx or tx data including both header and payload. ## Remapped rows DCGM_FI_DEV_UNCORRECTABLE_REMAPPED_ROWS, counter, Number of remapped rows for uncorrectable errors. DCGM_FI_DEV_CORRECTABLE_REMAPPED_ROWS, counter, Number of remapped rows for correctable errors. DCGM_FI_DEV_ROW_REMAP_FAILURE, gauge, whether remapping of rows has failed. ## Profiling metrics DCGM_FI_PROF_PIPE_FP64_ACTIVE, gauge, Ratio of cycles the fp64 pipes are active (in %). DCGM_FI_PROF_PIPE_FP32_ACTIVE, gauge, Ratio of cycles the fp32 pipes are active (in %). DCGM_FI_PROF_PIPE_FP16_ACTIVE, gauge, Ratio of cycles the fp16 pipes are active (in %). # ECC DCGM_FI_DEV_ECC_SBE_VOL_TOTAL, counter, Total number of single-bit volatile ECC errors. DCGM_FI_DEV_ECC_DBE_VOL_TOTAL, counter, Total number of double-bit volatile ECC errors. EOF

customMetrics 欄位會使用延伸指標集覆寫 DCGM 匯出者的預設指標集,其中包含 NVLink 頻寬、張量活動、PCIe 輸送量、ECC 錯誤和熱調節。對於推論工作負載,這可協助您了解 GPU 運算單位是否充分利用、GPU 是否因為批次大小低而在請求之間閒置、CPU 和 GPU 之間的資料傳輸是否是瓶頸、熱調節是否造成延遲峰值,以及大型批次的 GPU 記憶體空間剩餘多少。

安裝 DCGM 匯出工具:

helm install dcgm-exporter gpu-helm-charts/dcgm-exporter \ --namespace monitoring \ -f /tmp/dcgm-exporter-values.yaml

允許匯出程式tolerations在您於步驟 2 佈建的 GPU 污點節點上執行。serviceMonitor 具有 release: kube-prometheus-stack標籤的 可確保 Prometheus 自動探索和抓取它。

驗證 DCGM 匯出工具 DaemonSet:

kubectl get daemonset dcgm-exporter -n monitoring

GPU 節點執行後,您應該會看到一個就緒的 Pod。若要驗證 DCGM 指標,請導覽至 Grafana 中的向下切入 > 指標並搜尋 DCGM_

在 Grafana 中驗證 DCGM 指標

由 DCGM_ 篩選的 Grafana 向下切入指標頁面顯示 GPU 指標,包括 DCGM_FI_DEV_ECC_SBE_VOL_TOTAL、DCGM_FI_DEV_ENC_UTIL、DCGM_FI_DEV_FB_FREE 和 DCGM_FI_DEV_FB_USED

若要檢視儀表板,請導覽至儀表板 > GPU 監控 > NVIDIA DCGM 匯出工具儀表板

Grafana 中的 NVIDIA DCGM 匯出工具儀表板

Grafana NVIDIA DCGM Exporter Dashboard 顯示 GPU 使用率、GPU 平均溫度、使用的 GPU Framebuffer Mem 和 GPU Power Total 面板

模型權重 S3 儲存貯體

建立 Amazon S3 儲存貯體來存放模型權重,並設定 EKS Pod Identity Association,以便工作負載 Pod 可以讀取和寫入模型權重。

如果您開啟新的終端機,請設定叢集名稱和區域:

export CLUSTER_NAME=ai-eks-docs export AWS_REGION=us-east-2

建立 S3 儲存貯體

使用隨機尾碼建立儲存貯體,以避免名稱衝突:

BUCKET_SUFFIX=$(head -c 4 /dev/urandom | od -An -tx1 | tr -d ' \n') MODEL_BUCKET="${CLUSTER_NAME}-models-${BUCKET_SUFFIX}" aws s3 mb s3://${MODEL_BUCKET} --region ${AWS_REGION}

在 2023 年 1 月之後建立的 S3 儲存貯體預設會啟用伺服器端加密 (AES256) 和公有存取封鎖。

設定 S3 存取的 EKS Pod 身分

default 命名空間中建立 model-storage-sa ServiceAccount、範圍限定於模型儲存貯體的 IAM 政策,以及連結它們的 EKS Pod 身分關聯。設定的工作負載 Pod serviceAccountName: model-storage-sa將能夠讀取和寫入儲存貯體。

kubectl create serviceaccount model-storage-sa

建立 IAM 政策:

POLICY_ARN=$(aws iam create-policy \ --policy-name "${CLUSTER_NAME}-model-storage-policy" \ --policy-document "{\"Version\": \"2012-10-17\", \"Statement\": [{\"Effect\": \"Allow\", \"Action\": [\"s3:GetObject\", \"s3:PutObject\", \"s3:ListBucket\", \"s3:DeleteObject\"], \"Resource\": [\"arn:aws:s3:::${MODEL_BUCKET}\", \"arn:aws:s3:::${MODEL_BUCKET}/*\"]}]}" \ --query 'Policy.Arn' \ --output text) echo "Policy ARN: ${POLICY_ARN}"
注意

此政策s3:PutObject會針對驗證步驟授予 s3:DeleteObject和 。對於只讀取模型權重的生產推論 Pod,請移除 s3:PutObjects3:DeleteObject遵循最低權限。

建立 EKS Pod Identity Association。 會eksctl建立具有正確信任政策的 IAM 角色,並將其連結至 ServiceAccount:

eksctl create podidentityassociation \ --cluster ${CLUSTER_NAME} \ --namespace default \ --service-account-name model-storage-sa \ --role-name "${CLUSTER_NAME}-model-storage-role" \ --permission-policy-arns ${POLICY_ARN} \ --region ${AWS_REGION}

驗證關聯:

eksctl get podidentityassociation --cluster ${CLUSTER_NAME} --region ${AWS_REGION}

輸出應該包含 default 命名空間中的model-storage-sa關聯。

使用 model-storage-sa ServiceAccount 使用 AWS CLI 映像執行一次性 Pod,以確認已連接 EKS Pod 身分且 S3 存取正常運作:

cat << EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: s3-test labels: guide: ai-eks-docs spec: serviceAccountName: model-storage-sa containers: - name: aws-cli image: public.ecr.aws/aws-cli/aws-cli:2.27.0 command: - sh - -c - | echo "=== Caller Identity ===" aws sts get-caller-identity echo "" echo "=== S3 Write Test ===" echo "pod identity works" | aws s3 cp - s3://${MODEL_BUCKET}/test.txt echo "" echo "=== S3 List Test ===" aws s3 ls s3://${MODEL_BUCKET}/ echo "" echo "=== S3 Delete Test ===" aws s3 rm s3://${MODEL_BUCKET}/test.txt restartPolicy: Never EOF

等待 Pod 完成並檢查日誌:

kubectl wait --for=jsonpath='{.status.phase}'=Succeeded pod/s3-test --timeout=300s kubectl logs s3-test

預期的輸出結果:

=== Caller Identity ===
{
    "UserId": "AROA...:eks-ai-eks-docs-model-s-...",
    "Account": "123456789012",
    "Arn": "arn:aws:sts::123456789012:assumed-role/ai-eks-docs-model-storage-role/eks-ai-eks-docs-model-s-..."
}

=== S3 Write Test ===
upload: - to s3://ai-eks-docs-models-01234567/test.txt

=== S3 List Test ===
2026-05-04 12:00:00         19 test.txt

=== S3 Delete Test ===
delete: s3://ai-eks-docs-models-01234567/test.txt

發起人身分會確認 Pod 透過 EKS Pod 身分擔任該${CLUSTER_NAME}-model-storage-role角色。S3 命令會確認讀取和寫入存取。

清除測試 Pod:

kubectl delete pod s3-test

後續步驟

叢集準備就緒後,您可以繼續載入並提供模型,以部署大型語言模型並與推論端點互動。

清除

提示

如果您打算繼續本指南的下一節,請略過完整清除。只有在完成時才會執行它。

export CLUSTER_NAME=ai-eks-docs export AWS_REGION=us-east-2
kubectl delete pod nvidia-smi --ignore-not-found kubectl delete deployment gpu-overflow-test --ignore-not-found

如果您建立了 ODCR,請先取消它:

INSTANCE_TYPE="g6e.4xlarge" CAPACITY_RESERVATION_ID=$(aws ec2 describe-capacity-reservations \ --filters "Name=state,Values=active" "Name=instance-type,Values=${INSTANCE_TYPE}" \ --query 'CapacityReservations[0].CapacityReservationId' \ --output text \ --region ${AWS_REGION}) aws ec2 cancel-capacity-reservation --capacity-reservation-id ${CAPACITY_RESERVATION_ID}
重要

取消保留不會終止執行中的執行個體。它們會以標準隨需費率繼續,直到終止為止。取消之前,請先刪除部署以耗盡預留節點。

查詢 IAM 政策 ARN:

AMP_POLICY_ARN=$(aws iam list-policies \ --scope Local \ --query "Policies[?PolicyName=='${CLUSTER_NAME}-amp-grafana-policy'].Arn" \ --output text) echo "AMP Policy ARN: ${AMP_POLICY_ARN}"

查詢 AMP 工作區 ID:

AMP_WORKSPACE_ID=$(aws amp list-workspaces \ --alias "amp-ws-${CLUSTER_NAME}" \ --query 'workspaces[0].workspaceId' \ --output text \ --region ${AWS_REGION}) echo "AMP Workspace ID: ${AMP_WORKSPACE_ID}"

解除安裝 DCGM 匯出工具 Helm 版本:

helm uninstall dcgm-exporter -n monitoring

解除安裝 kube-prometheus-stack Helm 版本:

helm uninstall kube-prometheus-stack -n monitoring

刪除 Prometheus 擷取服務帳戶的 EKS Pod 身分關聯:

eksctl delete podidentityassociation \ --cluster ${CLUSTER_NAME} \ --namespace monitoring \ --service-account-name amp-iamproxy-ingest-service-account \ --region ${AWS_REGION}

刪除 Grafana 服務帳戶的 EKS Pod 身分關聯:

eksctl delete podidentityassociation \ --cluster ${CLUSTER_NAME} \ --namespace monitoring \ --service-account-name grafana-sa \ --region ${AWS_REGION}

刪除 Prometheus 和 Grafana 使用的 IAM 政策:

aws iam delete-policy --policy-arn ${AMP_POLICY_ARN}

刪除 AMP 工作區:

aws amp delete-workspace --workspace-id ${AMP_WORKSPACE_ID} --region ${AWS_REGION}

刪除監控命名空間:

kubectl delete namespace monitoring

查詢模型儲存貯體名稱:

MODEL_BUCKET=$(aws s3api list-buckets \ --query "Buckets[?starts_with(Name, '${CLUSTER_NAME}-models-')].Name | [0]" \ --output text) echo "Model bucket: ${MODEL_BUCKET}"

查詢 IAM 政策 ARN:

POLICY_ARN=$(aws iam list-policies \ --scope Local \ --query "Policies[?PolicyName=='${CLUSTER_NAME}-model-storage-policy'].Arn" \ --output text) echo "Policy ARN: ${POLICY_ARN}"

刪除 S3 模型儲存貯體及其所有物件:

aws s3 rb s3://${MODEL_BUCKET} --force

刪除 EKS Pod 身分關聯:

eksctl delete podidentityassociation \ --cluster ${CLUSTER_NAME} \ --namespace default \ --service-account-name model-storage-sa \ --region ${AWS_REGION}

刪除 IAM 政策:

aws iam delete-policy --policy-arn ${POLICY_ARN}

刪除 Kubernetes ServiceAccount:

kubectl delete serviceaccount model-storage-sa
kubectl delete nodepool gpu-inf --ignore-not-found kubectl delete nodeclass gpu-inf --ignore-not-found kubectl delete ec2nodeclass gpu-inf --ignore-not-found eksctl delete cluster --name=$CLUSTER_NAME --region=$AWS_REGION