View a markdown version of this page

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

協助改進此頁面

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

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

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

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

提示

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

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

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

高階架構和工作流程

顯示 <shared id= 的高階架構

圖表顯示本節設定的 AWS 高階架構。

先決條件

重要

您在本教學課程中建立的資源,包括 EKS 叢集、GPU 執行個體、Application Load Balancer 和 Amazon Managed Service for Prometheus,都會產生費用。當您完成時刪除資源,以避免持續收費。

驗證您的工具版本:

terraform --version aws --version kubectl version --client jq --version

步驟 1:下載並部署 Terraform 程式碼

本演練使用 sample-eks-docs AWS Samples GitHub 儲存庫中的 Terraform 程式碼。將儲存庫複製到工作目錄中:

git clone git@github.com:aws-samples/sample-eks-docs.git cd sample-eks-docs/ai-ml/set-up-cluster

儲存庫在您剛變更為的ai-ml/set-up-cluster/目錄下具有下列結構:

set-up-cluster/
├── scripts/
│   └── cleanup.sh
└── terraform/
    ├── auto-mode/
    └── karpenter/

儲存庫提供兩個部署路徑。請只選擇一個,並在整個指南中使用它。

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

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

重要

選擇 EKS Auto Mode 或自我管理 Karpenter,並在整個指南中使用它。切換中串流需要銷毀叢集並重新開始。

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 標準叢集
Grafana 可透過 HTTP 使用預設登入資料公開存取

Grafana ALB Ingress預設為 var.my_cidr 0.0.0.0/0,這會透過使用預設管理員憑證的純 HTTP 向公有網際網路公開 Grafana。自動化掃描器會在幾分鐘內探索公有負載平衡器。您必須var.my_cidr使用自己的 IP 地址覆寫來限制存取:

export MY_CIDR="$(curl -s https://checkip.amazonaws.com)/32" terraform apply -var "my_cidr=${MY_CIDR}"

將 source-IP 允許清單視為最低防護,而非完整防護。也請在第一次登入後變更預設的 Grafana 管理員密碼。如需更強的姿勢,請將 alb.ingress.kubernetes.io/scheme 變更為 internal(只能從您的 VPC 或連線的 VPN 內存取),然後新增 TLS 憑證。

部署叢集

將 變更為所選路徑的 目錄,初始化 Terraform,然後套用:

這兩個變體預設為 us-east-2區域。若要在不同區域中部署,請在下列步驟中將 -var "region=region-code"新增至 terraform apply命令,其中 region-code 是 AWS 您要部署的區域。

Terraform 程式碼使用目標區域中所有可用的可用區域,但 use1-az3、 和 除外usw1-az2cac1-az3因為 Amazon EKS 不支援在這些區域中放置控制平面

EKS Auto Mode
cd terraform/auto-mode terraform init terraform apply

此命令需要幾分鐘的時間才能完成。

Self-managed Karpenter
cd terraform/karpenter terraform init terraform apply

此命令大約需要 15 分鐘。它使用專用於託管附加元件和 Karpenter 控制器的受管節點群組來建立 EKS 叢集。Terraform 會在啟用 Spot 中斷佇列的情況下安裝 Karpenter,並開啟 NodeRepairStaticCapacity功能閘道。它也會安裝 NVIDIA 裝置外掛程式、 AWS Load Balancer控制器和監控堆疊。

檢閱 Terraform 輸出

當套用完成時,Terraform 會列印下列輸出 (值根據您的組態而有所不同):

Apply complete! Resources: 74 added, 0 changed, 0 destroyed.

Outputs:

cluster_name         = "ai-eks-docs"
configure_kubectl    = "aws eks update-kubeconfig --region us-east-2 --name ai-eks-docs --alias ai-eks-docs"
configure_model_bucket = "export MODEL_BUCKET=ai-eks-docs-models-20250612abc1"
model_bucket         = "ai-eks-docs-models-20250612abc1"
node_iam_role_name   = "ai-eks-docs-eks-auto-20250612..."
region               = "us-east-2"

configure_kubectl 輸出是kubectl指向叢集的ready-to-run命令。model_bucket 輸出包含模型權重的 S3 儲存貯體名稱。node_iam_role_name 輸出會顯示節點使用的 IAM 角色。

設定 kubectl

kubectl 指向新的叢集。configure_kubectl 輸出是ready-to-run命令:

eval "$(terraform output -raw configure_kubectl)"

驗證叢集

EKS Auto Mode
kubectl get pods --all-namespaces

預期的輸出結果:

NAMESPACE NAME READY STATUS RESTARTS AGE kube-system metrics-server-5db89f9ffd-h4mlr 1/1 Running 0 3m kube-system metrics-server-5db89f9ffd-nd748 1/1 Running 0 3m monitoring kube-prometheus-stack-grafana-ff9b5fd57-dh562 3/3 Running 0 3m monitoring kube-prometheus-stack-kube-state-metrics-5dcbfdf69b-wd6qn 1/1 Running 0 3m monitoring kube-prometheus-stack-operator-548c4f4485-m5wh2 1/1 Running 0 3m monitoring kube-prometheus-stack-prometheus-node-exporter-p2z7l 1/1 Running 0 3m monitoring prometheus-kube-prometheus-stack-prometheus-0 2/2 Running 0 3m

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

Self-managed Karpenter
kubectl get pods --all-namespaces

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

NAMESPACE NAME READY STATUS RESTARTS AGE kube-system aws-node-bzdcz 2/2 Running 0 5m kube-system aws-node-vkbhb 2/2 Running 0 5m kube-system coredns-7dbb8998cf-9b9wk 1/1 Running 0 5m kube-system coredns-7dbb8998cf-pwtjd 1/1 Running 0 5m kube-system ebs-csi-controller-748f54b69-8h7jv 6/6 Running 0 5m kube-system ebs-csi-controller-748f54b69-v2mv8 6/6 Running 0 5m kube-system eks-node-monitoring-agent-5qw4l 1/1 Running 0 5m kube-system eks-node-monitoring-agent-7lrtm 1/1 Running 0 5m kube-system eks-pod-identity-agent-ddvlv 1/1 Running 0 5m kube-system eks-pod-identity-agent-q4g29 1/1 Running 0 5m kube-system karpenter-898ff78-cndbd 1/1 Running 0 5m kube-system karpenter-898ff78-hfbhn 1/1 Running 0 5m kube-system kube-proxy-gcfnh 1/1 Running 0 5m kube-system kube-proxy-tktcf 1/1 Running 0 5m kube-system metrics-server-5b789db597-cm9qd 1/1 Running 0 5m kube-system metrics-server-5b789db597-w57b6 1/1 Running 0 5m kube-system nvidia-device-plugin-node-feature-discovery-gc-66cb7f5dc-xvftc 1/1 Running 0 5m kube-system nvidia-device-plugin-node-feature-discovery-master-854d6b5hnqtp 1/1 Running 0 5m monitoring kube-prometheus-stack-grafana-6797bcb59f-2zlwg 3/3 Running 0 5m monitoring kube-prometheus-stack-kube-state-metrics-8446bd549c-q6gjc 1/1 Running 0 5m monitoring kube-prometheus-stack-operator-5f499b784-vf5xb 1/1 Running 0 5m monitoring kube-prometheus-stack-prometheus-node-exporter-4c6wq 1/1 Running 0 5m monitoring kube-prometheus-stack-prometheus-node-exporter-l5t25 1/1 Running 0 5m monitoring prometheus-kube-prometheus-stack-prometheus-0 2/2 Running 0 5m

確認已安裝 NVIDIA 裝置外掛程式。在佈建具有相符amiFamily=al2023標籤的 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 5m

步驟 2:建立動態 GPU NodePool

GPU NodePools 為選擇加入。根據預設, 會terraform apply建立沒有 GPU 容量且沒有 GPU 計費的叢集和監控堆疊。若要佈建 GPU 節點,請使用策略名稱傳遞 nodepools變數。

啟用 spot-ondemand策略,該策略使用 Spot 容量搭配隨需做為備用,以佈建產生大於 4 的 G 系列 GPU 執行個體:

terraform apply -var 'nodepools={"spot-ondemand"={}}'

此命令會從 nodepools/spot-ondemand/目錄套用 NodePool 和 NodeClass 範本。兩個路徑都使用相同的 NodePool API,但它們在 NodeClass 中的 NodePool 參考不同。

EKS Auto Mode

NodePool 參考受管 default NodeClass,其已選取 Bottlerocket 加速 AMI、NVIDIA 驅動程式、NVIDIA 裝置外掛程式和 SOCI 平行提取。spot-ondemand 策略在此路徑上沒有自己的 NodeClass。

驗證 NodePool:

kubectl get nodepools,nodeclasses

預期的輸出結果。gpu-inf NodePool 會加入內建 general-purposesystem NodePools,而這三個都參考受管 default NodeClass:

NAME NODECLASS NODES READY AGE nodepool.karpenter.sh/general-purpose default 0 True 12m nodepool.karpenter.sh/gpu-inf default 0 True 20s nodepool.karpenter.sh/system default 1 True 12m NAME ROLE READY AGE nodeclass.eks.amazonaws.com/default ai-eks-docs-eks-auto-... True 12m
Self-managed Karpenter

Terraform 會gpu-infEC2NodeClass搭配 NodePool 套用自訂。將 EKS 最佳化 AL2023 AMI 別名EC2NodeClass接腳,透過FastImagePull功能閘道啟用 SOCI,並設定 instanceStorePolicy: RAID0將容器化映像快取移至本機 NVMe。

驗證 NodePool 和 EC2NodeClass:

kubectl get nodepools,ec2nodeclasses

預期的輸出結果。gpu-inf 配對會加入 Terraform 為非 GPU 工作負載建立的 general-purpose NodePool 和 EC2NodeClass:

NAME NODECLASS NODES READY AGE nodepool.karpenter.sh/general-purpose general-purpose 1 True 14m nodepool.karpenter.sh/gpu-inf gpu-inf 0 True 25s NAME READY AGE ec2nodeclass.karpenter.k8s.aws/general-purpose True 14m ec2nodeclass.karpenter.k8s.aws/gpu-inf True 25s

兩個路徑都會顯示 的0節點,gpu-inf直到排定 GPU 工作負載為止。EKS Auto Mode 和 Karpenter 只會在待定 Pod 需要時啟動節點。

步驟 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: restartPolicy: OnFailure 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 EOF

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

kubectl get pods nvidia-smi

預期的輸出結果:

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

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

kubectl logs nvidia-smi

預期的輸出結果:

+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 580.159.03             Driver Version: 580.159.03     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 L4                      On  |   00000000:31:00.0 Off |                    0 |
| N/A   41C    P8             13W /   72W |       0MiB /  23034MiB |      0%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+

輸出會顯示 GPU 模型、驅動程式版本、CUDA 版本和可用的記憶體。在此範例中,Karpenter 佈建了具有 NVIDIA L4 GPU 和 24 GB 記憶體的 G6 執行個體。GPU 模型和記憶體會根據 Karpenter 選取的執行個體類型而有所不同。G5 執行個體具有 NVIDIA A10G GPUs (24 GB)、G6 執行個體具有 NVIDIA L4 GPUs (24 GB),而 G6e 執行個體具有 NVIDIA L40S GPUs (48 GB)。

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

kubectl describe pod nvidia-smi

預期的輸出結果:

Events:
  Type     Reason            Age   From                   Message
  ----     ------            ----  ----                   -------
  Warning  FailedScheduling  75s   default-scheduler      0/2 nodes are available: 2 node(s) had untolerated taint(s).
  Normal   Nominated         74s   eks-auto-mode/compute  Pod should schedule on: nodeclaim/gpu-inf-z6q75
  Normal   Scheduled         35s   default-scheduler      Successfully assigned default/nvidia-smi to i-0eb897a8302551589
  Normal   Pulling           27s   kubelet                spec.containers{nvidia-smi}: Pulling image "public.ecr.aws/amazonlinux/amazonlinux:2023-minimal"
  Normal   Pulled            22s   kubelet                spec.containers{nvidia-smi}: Successfully pulled image "public.ecr.aws/amazonlinux/amazonlinux:2023-minimal" in 5.625s (5.626s including waiting). Image size: 37440620 bytes.
  Normal   Created           22s   kubelet                spec.containers{nvidia-smi}: Container created
  Normal   Started           21s   kubelet                spec.containers{nvidia-smi}: Container started

這些事件會顯示 Pod 排程序列:Pod 一開始無法排程,因為 GPU 節點不存在 (FailedScheduling),Karpenter 會指定新的 NodeClaim (Nominated),排程器會在節點就緒時指派 Pod (Scheduled),然後提取並啟動容器映像。EKS Auto Mode 預設會在 G、P 和 Trn 執行個體上安裝和設定 SOCI (可尋求 OCI) 平行提取,而自我管理 Karpenter 路徑會透過FastImagePull功能閘道明確設定。

注意

在自我管理的 Karpenter 叢集上,Nominated事件會顯示 karpenter/compute而非 eks-auto-mode/compute

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

kubectl get nodeclaims

預期的輸出結果:

NAME            TYPE        CAPACITY   ZONE         NODE                  READY   AGE
gpu-inf-z6q75   g6.xlarge   spot       us-east-2a   i-0eb897a8302551589   True    5m

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

提示

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

kubectl get events | grep InsufficientCapacityError

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

注意

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

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

雖然步驟 2 的 GPU NodePool 動態佈建 Spot 或隨需執行個體,但某些使用案例需要保證容量。您可以建立隨需容量保留 (ODCR),以確保 GPU 容量在需要時可用。

使用 Terraform 時,單一命令會建立 ODCR,這是依標籤參考保留的自訂 NodeClass,並更新 NodePool 以包含 reserved做為容量類型。Terraform 使用 標記 ODCR,nodepool=reserved-spot-ondemandNodeClass 會依該標籤選取它。

警告

下列命令會建立 ODCR,該 會立即計費並繼續計費,直到您使用 terraform destroy或清除指令碼將其銷毀,無論節點是否在其上執行。

使用預設值 (g6e.4xlarge、1 個執行個體、第一個叢集 AZ):

terraform apply -var 'nodepools={"reserved-spot-ondemand"={reservation={}}}'

選擇執行個體類型、計數和可用區域:

terraform apply -var 'nodepools={"reserved-spot-ondemand"={reservation={instance_type="g6e.2xlarge",instance_count=1,az="us-east-2a"}}}'

reservation 物件支援下列欄位:

  • instance_type — 要保留的 GPU 執行個體類型。預設:g6e.4xlarge

  • instance_count — 要保留的執行個體數量。預設:1

  • az — 保留的可用區域。預設: "" (使用第一個叢集 AZ)。

重要

spot-ondemandreserved-spot-ondemand策略是互斥的。您最多可以在 nodepools變數中啟用一個 。如果您之前在步驟 2 spot-ondemand中使用過 ,reserved-spot-ondemand命令會取代它,因為兩者都會管理相同的 gpu-inf NodePool。

如果您收到InsufficientInstanceCapacity錯誤,則無法在指定的 AZ 中完成保留。取消 Terraform 操作 (Ctrl+C),然後使用不同的az值重新執行:

terraform apply -var 'nodepools={"reserved-spot-ondemand"={reservation={instance_type="g6e.4xlarge",az="us-east-2b"}}}'

套用後,Terraform 會將 NodePool 更新為在容量類型需求on-demand中包含 spotreserved和 。Karpenter reserved將 視為最具成本效益的選項,並優先啟動。一旦保留已滿,就會回到 Spot 或隨需。

在 EKS Auto Mode 路徑上,Terraform 會建立自訂 gpu-inf NodeClass (因為 Bundled default NodeClass 為唯讀),透過 標籤參考 ODCRcapacityReservationSelectorTerms。在自我管理的 Karpenter 路徑上,Terraform 會重新套用 gpu-inf EC2NodeClass,並capacityReservationSelectorTerms新增和更新 NodePool 以包含 reserved

驗證是否已建立 ODCR:

aws ec2 describe-capacity-reservations \ --filters "Name=state,Values=active" "Name=tag:nodepool,Values=reserved-spot-ondemand" \ --query 'CapacityReservations[0].{Id:CapacityReservationId,State:State,InstanceType:InstanceType,AvailableCount:AvailableInstanceCount}' \ --output table \ --region $(terraform output -raw region)

驗證 NodeClass 參考 ODCR:

EKS Auto Mode
kubectl get nodeclasses gpu-inf -o yaml | grep 'id: cr-.*'

預期的輸出結果:

id: cr-xxxxxxxxxxxxxxxxx
Self-managed Karpenter
kubectl get ec2nodeclasses gpu-inf -o yaml | grep 'id: cr-.*'

預期的輸出結果:

id: cr-xxxxxxxxxxxxxxxxx

驗證 NodePool 已就緒:

kubectl get nodepools gpu-inf

預期的輸出結果:

NAME      NODECLASS   NODES   READY   AGE
gpu-inf   gpu-inf     0       True    30s

套用變更後,請驗證 Karpenter 是否排定保留容量的優先順序,並回到 Spot 或隨需。部署 2 個複本部署,每個 Pod 請求 1 個 GPU。ODCR 適用於 1 個執行個體 (1 個 GPU),因此第一個 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-55d55ff5b9-dvg52   1/1     Running   0          4m42s   10.0.75.210   i-08741a36089ff2088   <none>           <none>
gpu-overflow-test-55d55ff5b9-hw4m9   1/1     Running   0          4m43s   10.0.82.49    i-0f50cdbacb2017202   <none>           <none>

檢查 NodeClaims 以查看容量類型:

kubectl get nodeclaims

預期的輸出結果:

NAME            TYPE          CAPACITY   ZONE         NODE                  READY   AGE
gpu-inf-vw99m   g6e.4xlarge   reserved   us-east-2c   i-0f50cdbacb2017202   True    6m
gpu-inf-s65s6   g6.xlarge     spot       us-east-2b   i-08741a36089ff2088   True    5m59s

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

清除測試部署:

kubectl delete deployment gpu-overflow-test

監控

在步驟 1 terraform apply中,Terraform 已在 期間佈建完整的監控堆疊。堆疊包含 Amazon Managed Service for Prometheus (AMP) 工作區、IAM 政策和 EKS Pod Identity Associations for Prometheus remote-write and Grafana 查詢存取、kube-prometheus-stack Helm Chart (Prometheus、Grafana、kube-state-metrics、 node-exporter),以及適用於 GPU 指標的 NVIDIA DCGM Exporter。

本節涵蓋已部署監控元件的驗證。

驗證監控 Pod

等待所有監控 Pod 就緒:

kubectl wait --for=condition=Ready pod --all -n monitoring --timeout=300s kubectl get pods -n monitoring

預期的輸出結果:

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

存取 Grafana

Grafana 透過 Internet-facing AWS Application Load Balancer (ALB) 公開,僅限於您在 中設定的 CIDRvar.my_cidr。列印負載平衡器 URL (允許 ALB 佈建一兩分鐘):

echo "http://$(kubectl get ingress kube-prometheus-stack-grafana -n monitoring -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')"

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

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

驗證指標管道

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

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

    驗證 Grafana 中的 AMP 資料來源

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

    驗證 up Grafana 中的指標

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

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

驗證 DCGM GPU 指標

DCGM Exporter DaemonSet 會在 GPU 節點上執行,並報告 GPU 使用率、記憶體、溫度、耗電量、NVLink 頻寬和張量活動指標。

驗證 DCGM 匯出工具 DaemonSet:

kubectl get daemonset dcgm-exporter -n monitoring

一旦 GPU 節點執行 (從步驟 2 或步驟 4),您應該會看到一或多個就緒的 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 儲存貯體

Terraform 已建立用於存放模型權重的 Amazon S3 儲存貯體、default命名空間中的 model-storage-sa ServiceAccount、範圍為儲存貯體的 IAM 政策,以及連結它們的 EKS Pod Identity Association。設定的工作負載 Pod serviceAccountName: model-storage-sa可以讀取和寫入儲存貯體。

驗證儲存貯體

從 Terraform 輸出擷取儲存貯體名稱:

MODEL_BUCKET=$(terraform output -raw model_bucket) echo ${MODEL_BUCKET}

驗證儲存貯體是否存在:

aws s3api head-bucket --bucket ${MODEL_BUCKET}

預期的輸出結果:

{
    "BucketArn": "arn:aws:s3:::ai-eks-docs-models-20250612abc1",
    "BucketRegion": "us-east-2",
    "AccessPointAlias": false
}

使用 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-models-.../eks-ai-eks-docs-..."
}

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

=== S3 List Test ===
2026-07-15 12:00:00         19 test.txt

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

發起人身分確認 Pod 透過 EKS Pod 身分擔任模型儲存角色。S3 命令會確認讀取和寫入存取。

清除測試 Pod:

kubectl delete pod s3-test

後續步驟

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

清除

提示

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

刪除測試工作負載,讓 Pod 不會保留 GPU 節點:

kubectl delete pod nvidia-smi --ignore-not-found kubectl delete deployment gpu-overflow-test --ignore-not-found

如果您只想釋放 ODCR 並返回 Spot 和隨需容量,請將nodepools變數切換回spot-ondemand策略:

terraform apply -var 'nodepools={"spot-ondemand"={}}'

reserved會從 NodePool 容量類型需求中刪除,並銷毀 ODCR,並將叢集、監控堆疊和 S3 儲存貯體留在原處。

重要

取消保留不會終止已在其中執行的執行個體。這些執行個體會持續以標準隨需費率執行,直到終止為止。首先刪除 GPU 工作負載,如上所示,因此保留的節點會在釋出保留之前耗盡。

在銷毀之前耗盡 Karpenter 受管節點,因此沒有任何傳輸中節點生命週期會封鎖銷毀。刪除任何會阻止耗盡的 PodDisruptionBudgets,然後刪除 NodeClaims:

kubectl delete pdb -A --all --ignore-not-found kubectl delete nodeclaim --all --wait=true --timeout=900s

然後銷毀建立的所有 Terraform,包括 EKS 叢集、VPC、監控堆疊、NodePools 和 NodeClasses、S3 模型儲存貯體,以及任何 ODCR:

terraform destroy
警告

模型權重 S3 儲存貯體是使用 建立force_destroy = true的,因此 會terraform destroy刪除儲存貯體以及您上傳到儲存貯體的任何模型權重。先將您想要保留的任何內容複製到另一個位置。

注意

儲存庫也會提供執行上述耗盡和銷毀步驟的scripts/cleanup.sh協助程式,然後掃描任何以叢集名稱標記的孤立 EBS 磁碟區。從您套用的terraform/<mode>/目錄中執行它,然後傳遞 --auto-approve以略過 Terraform 確認提示。

確認叢集沒有剩餘的作用中容量保留:

aws ec2 describe-capacity-reservations \ --filters "Name=state,Values=active" "Name=tag:nodepool,Values=reserved-spot-ondemand" \ --query 'CapacityReservations[].CapacityReservationId' \ --output text

空白結果表示沒有作用中的保留,也不會產生其他費用。