運算和自動擴展 - Amazon EKS

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

運算和自動擴展

GPU 資源最佳化和成本管理

使用 Well-Known 標籤以 GPU 需求排程工作負載

對於對不同 GPU 特性 (例如 GPU、GPU 記憶體) 敏感的 AI/ML 工作負載,建議使用與 Karpenter受管節點群組搭配使用的節點類型支援的已知排程標籤來指定 GPU 需求。未定義這些項目可能會導致在 GPU 資源不足的執行個體上排程 Pod,進而導致故障或效能降低。我們建議使用 nodeSelectorNode 親和性來指定 Pod 應在哪個節點上執行,並在 Pod 的資源區段中設定運算資源 (CPU、記憶體、GPUs 等)。

範例

例如,使用 Karpenter 時使用 GPU 名稱節點選擇器:

apiVersion: v1 kind: Pod metadata: name: gpu-pod-example spec: containers: - name: ml-workload image: <image> resources: limits: nvidia.com/gpu: 1 # Request one NVIDIA GPU nodeSelector: karpenter.k8s.aws/instance-gpu-name: "l40s" # Run on nodes with NVIDIA L40S GPUs

使用 Kubernetes 裝置外掛程式公開 GPUs

若要在節點上公開 GPUs,NVIDIA GPU 驅動程式必須安裝在節點的作業系統和容器執行時間上,設定成允許 Kubernetes 排程器將 Pod 指派給具有可用 GPUs 的節點。NVIDIA Kubernetes 裝置外掛程式的設定程序取決於您使用的 EKS 加速 AMI:

  • Bottlerocket Accelerated AMI此 AMI 包含 NVIDIA GPU 驅動程式,且已預先安裝 NVIDIA Kubernetes 裝置外掛程式並可供使用,可立即支援 GPU。向 Kubernetes 排程器公開 GPUs 不需要額外的組態。

  • AL2023 加速 AMI此 AMI 包含 NVIDIA GPU 驅動程式,但未預先安裝 NVIDIA Kubernetes 裝置外掛程式。您必須分別安裝和設定裝置外掛程式,通常是透過 DaemonSet。請注意,如果您使用 eksctl 建立叢集,並在 ClusterConfig 中指定 GPU 執行個體類型 (例如 g5.xlarge), eksctl 會自動選取加速 AMI,並在節點群組中的每個執行個體上安裝 NVIDIA Kubernetes 裝置外掛程式。若要進一步了解,請參閱 eksctl 文件中的 GPU 支援

若要驗證 NVIDIA 裝置外掛程式是否作用中且 GPUs 已正確公開,請執行:

kubectl describe node | grep nvidia.com/gpu

此命令會檢查nvidia.com/gpu資源是否在節點的容量和可配置的資源中。例如,具有一個 GPU 的節點應該會顯示 nvidia.com/gpu: 1。如需詳細資訊,請參閱 Kubernetes GPU 排程指南

使用 ML 容量區塊來確保 P 和 Trainium 執行個體的容量

ML 的容量區塊可讓您保留熱門的 GPU 執行個體,特別是 P 執行個體 (例如 p6-b200、p5、p5e、p5en、p4d、p4de) 和 Trainium 執行個體 (例如 trn1、trn2),以幾乎立即開始或在未來日期開始,以支援您的短期機器學習 (ML) 工作負載。這些保留非常適合確保運算密集型任務的容量,例如模型訓練和微調。EC2 容量區塊定價包含保留費和作業系統費用。若要進一步了解定價,請參閱適用於 ML 定價的 EC2 容量區塊

若要為 Amazon EKS 上的 AI/ML 工作負載保留 GPUs,以保證可預測的容量,我們建議將 ML 容量區塊用於短期或隨需容量保留 ODCRs),以保證一般用途的容量。

  • ODCRs 可讓您在特定可用區域中保留 EC2 執行個體容量 (例如 g5 或 p5 等 GPU 執行個體),即使在高需求期間也能確保可用性。ODCRs沒有長期承諾,但您要支付預留容量的隨需費率,無論是已使用或閒置。在 EKS 中,Karpenter受管節點群組等節點類型支援 ODCRs。若要排定 Karpenter 中的 ODCRs優先順序,請將 NodeClass 設定為使用 capacityReservationSelectorTerms 欄位。請參閱 Karpenter NodePools 文件

  • 容量區塊是 GPU (例如 p5、p4d) 或 Trainium (trn1、trn2) 執行個體的特殊保留機制,專為模型訓練、微調或實驗等短期 ML 工作負載而設計。您從未來日期開始,在定義的期間內 (通常為 24 小時至 182 天) 保留容量,僅支付預留時間的費用。它們是預付的,需要預先規劃容量需求,且不支援自動擴展,但會共置在 EC2 UltraClusters 中以進行低延遲聯網。它們只會收取預留期間的費用。若要進一步了解,請參閱尋找和購買容量區塊,或使用建立具有 ML 容量區塊的受管節點群組中的指示來設定具有容量區塊的受管節點群組

透過 AWS 管理主控台預留容量,並將節點設定為使用 ML 容量區塊。根據工作負載排程規劃保留,並在預備叢集中進行測試。如需詳細資訊,請參閱容量區塊文件

考慮 G Amazon EC2 執行個體的隨需、Amazon EC2 Spot 或隨需容量保留 (ODCRs)

對於 G Amazon EC2 執行個體,請考慮與隨需、Amazon EC2 Spot 執行個體和隨需容量保留不同的購買選項。ODCRs 可讓您在特定的可用區域中保留 EC2 執行個體容量一段時間,即使在高需求期間也能確保可用性。與僅適用於 P 和 Trainium 執行個體的 ML 容量區塊不同,ODCRs 可用於更廣泛的執行個體類型,包括 G 執行個體,使其適用於需要不同 GPU 功能的工作負載,例如推論或圖形。使用 Amazon EC2 Spot 執行個體時,能夠跨不同的執行個體類型、大小和可用區域進行多樣化,是讓 Spot 停留更久的關鍵。

ODCRs沒有長期承諾,但您要支付預留容量的隨需費率,無論是已使用或閒置。您可以建立 ODCRs以供立即使用,或排定未來日期,提供容量規劃的彈性。在 Amazon EKS 中,Karpenter受管節點群組等節點類型支援 ODCRs。若要排定 Karpenter 中的 ODCRs優先順序,請將 NodeClass 設定為使用 capacityReservationSelectorTerms 欄位。請參閱 Karpenter NodePools 文件。如需建立 ODCRs 的詳細資訊,包括 CLI 命令,請參閱隨需容量保留入門

考慮其他加速執行個體類型和大小

選取適當的加速執行個體和大小對於在 Amazon EKS 上最佳化 ML 工作負載的效能和成本至關重要。例如,不同的 GPU 執行個體系列具有不同的效能和功能,例如 GPU 記憶體。為了協助您選擇價格效能最佳的選項,請檢閱加速運算EC2 執行個體類型頁面中可用的 GPU 執行個體。評估多個執行個體類型和大小,以找出最適合您特定工作負載需求的執行個體類型和大小。考慮 GPUs 數量、記憶體和網路效能等因素。透過仔細選擇正確的 GPU 執行個體類型和大小,您可以在 EKS 叢集中實現更好的資源使用率和成本效益。

如果您在 EKS 節點中使用 GPU 執行個體,則預設在kube-system命名空間中會有 nvidia-device-plugin-daemonset Pod。若要快速了解您是否充分利用執行個體中的 GPU,您可以使用 nvidia-smi (如下所示):

kubectl exec nvidia-device-plugin-daemonset-xxxxx \ -n kube-system -- nvidia-smi \ --query-gpu=index,power.draw,power.limit,temperature.gpu,utilization.gpu,utilization.memory,memory.free,memory.used \ --format=csv -l 5
  • 如果 utilization.memory (接近 100%),則您的程式碼可能已繫結記憶體。這表示 GPU (記憶體) 已充分利用,但可能表示應調查進一步的效能最佳化。

  • 如果 utilization.gpu 接近 100%,這不一定表示 GPU 已充分利用。要查看的較佳指標是 power.draw與 的比率power.limit。如果此比率為 100% 或以上,則您的程式碼會充分利用 GPU 的運算容量 (運算容量)。

  • -l 5 旗標指出 每 5 秒輸出一次指標。如果是單一 GPU 執行個體類型,則不需要索引查詢旗標。

若要進一步了解,請參閱 AWS 文件中的 GPU 執行個體

使用時間分割、MIG 和分量 GPU 配置來最佳化 GPU 資源配置

Kubernetes 中的靜態資源限制 (例如 CPU、記憶體、GPU 計數) 可能會導致過度佈建或利用率不足,尤其是推論等動態 AI/ML 工作負載。選取正確的 GPU 非常重要。對於低容量或尖峰工作負載,時間分割允許多個工作負載透過共用其運算資源來共用單一 GPU,進而提高效率並減少浪費。GPU 共用可以透過不同的選項達成:

  • 利用節點選擇器/節點親和性來影響排程:確保佈建的節點和 Pod 已排程在工作負載的適當 GPUs 上 (例如 karpenter.k8s.aws/instance-gpu-name: "a100")

  • 時間分割:排程工作負載以隨時間共用 GPU 的運算資源,允許並行執行,無需實體分割。這非常適合具有可變運算需求的工作負載,但可能缺乏記憶體隔離。

  • 多執行個體 GPU (MIG):MIG 允許單一 NVIDIA GPU 分割成多個隔離的執行個體,並支援 NVIDIA Ampere (例如 A100 GPU)、NVIDIA Hopper (例如 H100 GPU) 和 NVIDIA Blackwell (例如 Blackwell GPUs) GPUs。每個 MIG 執行個體都會接收專用運算和記憶體資源,在需要資源保證的多租用戶環境或工作負載中啟用資源共用,這可讓您最佳化 GPU 資源使用率,包括透過時間分割提供不同批次大小的多個模型。

  • 分數 GPU 分配:使用軟體型排程,將部分 GPU 運算或記憶體分配給工作負載,為動態工作負載提供彈性。NVIDIA KAI 排程器是 Run:ai 平台的一部分,透過允許 Pod 請求部分 GPU 資源來啟用此功能。

若要在 EKS 中啟用這些功能,您可以部署 NVIDIA 裝置外掛程式,將 GPUs 公開為可排程的資源,並支援時間分割和 MIG。若要進一步了解,請參閱 Kubernetes 中的時間分割 GPUs 使用 NVIDIA 時間分割和加速 EC2 執行個體的 Amazon EKS 上的 GPU 共用

範例

例如,若要使用 NVIDIA 裝置外掛程式啟用時間分割:

apiVersion: v1 kind: ConfigMap metadata: name: nvidia-device-plugin-config namespace: kube-system data: config.yaml: | version: v1 sharing: timeSlicing: resources: - name: nvidia.com/gpu replicas: 4 # Allow 4 pods to share each GPU

範例

例如,若要使用 KAI 排程器配置分數 GPU,請將其與 NVIDIA GPU Operator 一起部署,並在 Pod 規格中指定分數 GPU 資源:

apiVersion: v1 kind: Pod metadata: name: fractional-gpu-pod-example annotations: gpu-fraction: "0.5" # Annotation for 50% GPU labels: runai/queue: "default" # Required queue assignment spec: containers: - name: ml-workload image: nvcr.io/nvidia/pytorch:25.04-py3 resources: limits: nvidia.com/gpu: 1 nodeSelector: nvidia.com/gpu: "true" schedulerName: kai-scheduler

節點彈性和訓練任務管理

使用自動復原實作節點運作狀態檢查

對於需要頻繁節點間通訊的 Amazon EKS 分散式訓練任務,例如跨多個節點的多 GPU 模型訓練,GPU 或 EFA 失敗等硬體問題可能會導致訓練任務中斷。這些中斷可能會導致訓練進度的損失和成本增加,尤其是依賴穩定硬體的長期執行 AI/ML 工作負載。

為了協助增加硬體故障的彈性,例如執行 GPU 工作負載的 EKS 叢集中的 GPU 失敗,我們建議您利用 EKS 節點監控代理程式搭配自動修復或 Amazon SageMaker HyperPod。雖然具有自動修復功能的 EKS 節點監控代理程式提供節點運作狀態監控和使用標準 Kubernetes 機制的自動修復等功能,但 SageMaker HyperPod 提供目標彈性和其他專為大規模 ML 訓練而設計的功能,例如深度運作狀態檢查和自動恢復任務。

  • EKS Node Monitoring Agent with Node Auto Repair 透過讀取日誌和套用 NodeConditions 來持續監控節點運作狀態,包括加速硬體的特定標準條件,例如 Ready和 條件,以識別 GPU 或網路故障等問題。當節點視為運作狀態不佳時,Node Auto Repair 會將其封鎖,並將其取代為新的節點。重新排程 Pod 和重新啟動任務取決於標準 Kubernetes 機制和任務的重新啟動政策。

  • SageMaker HyperPod 深度運作狀態檢查和運作狀態監控代理程式會持續監控 GPU 和 Trainium 型執行個體的運作狀態。它專為 AI/ML 工作負載量身打造,使用標籤 (例如 node-health-status) 來管理節點運作狀態。當節點視為運作狀態不佳時,HyperPod 會觸發自動取代故障的硬體,例如 GPUs。它預設透過 EFA 的基本運作狀態檢查來偵測網路相關的故障,並支援自動恢復中斷的訓練任務,允許任務從最後一個檢查點繼續進行,將大規模 ML 任務的中斷降至最低。

對於具有自動修復的 EKS 節點監控代理程式和使用 EFA 的 SageMaker HyperPod 叢集,若要監控 EFA 特定指標,例如遠端直接記憶體存取 (RDMA) 錯誤和封包捨棄,請確定已安裝 AWS EFA 驅動程式。此外,我們建議部署 CloudWatch 可觀測性附加元件或使用 DCGM Exporter 和 Prometheus 和 Grafana 等工具來監控 EFA、GPU,以及針對 SageMaker HyperPod,與其功能相關的特定指標。

針對中斷敏感工作負載停用 Karpenter 合併

對於對處理、大規模 AI/ML 預測任務或訓練等中斷敏感的工作負載,我們建議調校 Karpenter 整合政策,以防止任務執行期間中斷。Karpenter 的合併功能會自動最佳化叢集成本,方法是終止未充分利用的節點,或以價格較低的替代節點取代它們。不過,即使工作負載完全利用 GPU,如果 Karpenter 識別出符合 Pod 需求的價格較低的適當執行個體類型,則可能會合併節點,導致任務中斷。

WhenEmptyOrUnderutilized 合併政策可能會提早終止節點,導致執行時間延長。例如,由於 Pod 重新排程、資料重新載入,中斷可能會延遲任務恢復,這對於長時間執行的批次推論任務可能非常昂貴。若要緩解這種情況,您可以將 consolidationPolicy 設定為 ,WhenEmpty並設定consolidateAfter持續時間,例如 1 小時,以在工作負載尖峰期間保留節點。例如:

disruption: consolidationPolicy: WhenEmpty consolidateAfter: 60m

此方法可改善尖峰批次推論工作負載和其他干擾敏感任務的 Pod 啟動延遲,例如即時線上推論資料處理或模型訓練,其中中斷成本高於運算成本節省。Karpenter NodePool 中斷預算是管理 Karpenter 中斷的另一項功能。透過預算,您可以確保在所選的 NodePool 中,不超過特定數量的節點節點會在某個時間點中斷。您也可以使用中斷預算來防止在特定時間 (例如尖峰時間) 中斷所有節點。若要進一步了解,請參閱 Karpenter 合併文件。

使用 ttlSecondsAfterFinished 自動清除 Kubernetes 任務

我們建議ttlSecondsAfterFinished在 Amazon EKS 中設定 Kubernetes 任務,以自動刪除已完成的任務物件。內嵌任務物件會耗用叢集資源,例如 API 伺服器記憶體,並透過雜亂儀表板 (例如 Grafana、Amazon CloudWatch) 來複雜化監控。例如,將 TTL 設定為 1 小時可確保任務會在完成後不久移除,讓您的叢集保持整齊。如需詳細資訊,請參閱完成任務的自動清除

設定較高優先順序任務/工作負載的低優先順序任務先佔

對於 Amazon EKS 上的混合優先順序 AI/ML 工作負載,您可以設定低優先順序任務先佔,以確保較高優先順序的任務 (例如即時推論) 可快速接收資源。如果沒有先佔,低優先順序工作負載,例如批次程序 (例如批次推論、資料處理)、非批次服務 (例如背景任務、cron 任務) 或 CPU/記憶體密集型任務 (例如 Web 服務),可以透過佔用節點來延遲關鍵 Pod。先佔允許 Kubernetes 在高優先順序 Pod 需要資源時移出低優先順序 Pod,確保在具有 GPUs、CPUs 或記憶體的節點上進行有效率的資源配置。建議使用 Kubernetes PriorityClass來指派優先順序PodDisruptionBudget並控制移出行為。

apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: low-priority value: 100 --- spec: priorityClassName: low-priority

如需詳細資訊,請參閱 Kubernetes 優先順序和先佔文件

應用程式擴展和效能

使用 Karpenter 或靜態節點的 ML 工作負載量身訂做運算容量

為了確保 Amazon EKS 上機器學習 (ML) 工作流程的成本效益和回應性運算容量,我們建議您根據工作負載的特性和成本承諾量身打造節點佈建策略。以下是兩個要考慮的方法:使用 Karpenter 和靜態節點群組即時 just-in-time 擴展預留容量。

  • Just-in-time資料平面縮放器,例如 Karpenter:對於具有可變運算需求的動態 ML 工作流程 (例如,GPU 型推論,後面接著 CPU 型繪圖),我們建議使用just-in-time資料平面縮放器,例如 Karpenter。

  • 將靜態節點群組用於可預測的工作負載:對於可預測、穩定狀態的 ML 工作負載或使用預留執行個體時,EKS 受管節點群組可協助確保預留容量已完全佈建和使用,從而最大限度地節省成本。此方法非常適合透過 RIs 或 ODCRs 遞交的特定執行個體類型。

範例

這是各種 Karpenter NodePool 的範例,可啟動執行個體產生大於三個的 g Amazon EC2 執行個體。

apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: gpu-inference spec: template: spec: nodeClassRef: group: karpenter.k8s.aws kind: EC2NodeClass name: default requirements: - key: karpenter.sh/capacity-type operator: In values: ["on-demand"] - key: karpenter.k8s.aws/instance-category operator: In values: ["g"] - key: karpenter.k8s.aws/instance-generation operator: Gt values: ["3"] - key: kubernetes.io/arch operator: In values: ["amd64"] taints: - key: nvidia.com/gpu effect: NoSchedule limits: cpu: "1000" memory: "4000Gi" nvidia.com/gpu: "10" *# Limit the total number of GPUs to 10 for the NodePool* disruption: consolidationPolicy: WhenEmpty consolidateAfter: 60m expireAfter: 720h

範例

使用靜態節點群組訓練工作負載的範例:

apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: ml-cluster region: us-west-2 managedNodeGroups: - name: gpu-node-group instanceType: p4d.24xlarge minSize: 2 maxSize: 2 desiredCapacity: 2 taints: - key: nvidia.com/gpu effect: NoSchedule

使用污點和容錯,防止在加速執行個體上排程非加速工作負載

在 GPU 資源上排程非加速工作負載不具運算效率,建議您使用污點和容錯,以確保非加速工作負載 Pod 不會排程在不適當的節點上。如需詳細資訊,請參閱 Kubernetes 文件

根據模型效能擴展

對於推論工作負載,建議使用 Kubernetes Event-Driven Autoscaling (KEDA) 根據模型效能指標進行擴展,例如推論請求或字符輸送量,並具有適當的冷卻時間。靜態擴展政策可能會過度佈建或佈建不足的資源,影響成本和延遲。如需進一步了解,請參閱 KEDA 文件

進階 GPU 管理的動態資源配置

動態資源配置 (DRA) 代表 Kubernetes GPU 資源管理的基本進展。DRA 超越了傳統的裝置外掛程式限制,以啟用複雜的 GPU 共用、拓撲感知和跨節點資源協調。適用於 Amazon EKS 1.33 版的 DRA 透過提供下列項目來解決 AI/ML 工作負載中的重大挑戰:

  • 精細的 GPU 配置

  • 進階共用機制,例如多程序服務 (MPS) 和多執行個體 GPU (MIG)

  • 支援新一代硬體架構,包括 NVIDIA GB200 UltraClusters

傳統 GPU 配置會將 GPUs 視為不透明的整數資源,造成顯著的使用不足 (通常在生產叢集中為 30-40%)。這是因為即使只需要部分資源,工作負載也會取得整個 GPUs 的專屬存取權。DRA 透過引入結構化的宣告式配置來轉換此模型,讓 Kubernetes 排程器完全了解硬體特性和工作負載需求。這可實現智慧型配置決策和有效率的資源共用。

使用 DRA 而非 NVIDIA 裝置外掛程式的優點

NVIDIA 裝置外掛程式 (從版本 開始0.12.0) 支援 GPU 共用機制,包括時間分割、MPS 和 MIG。不過,該 DRA 地址存在架構限制。

NVIDIA 裝置外掛程式限制

  • 靜態組態:GPU 共用組態 (時間分割複本和 MPS 設定) 需要透過 進行整個叢集的預先組態ConfigMaps。這使得為不同的工作負載提供不同的共用策略變得困難。

  • 有限精細選擇:雖然裝置外掛程式透過節點標籤公開 GPU 特性,但工作負載無法在排程決策中動態請求特定 GPU 組態 (記憶體大小和運算功能)。

  • 無跨節點資源協調:無法管理跨多個節點的分散式 GPU 資源,或表達複雜的拓撲需求,例如 NVIDIA GB200 等系統的 NVLink 網域。

  • 排程器限制:Kubernetes 排程器會將 GPU 資源視為不透明整數,限制其做出拓撲感知決策或處理複雜資源相依性的能力。

  • 組態複雜性:設定不同的共用策略需要多個仔細ConfigMaps的節點標記,從而產生操作複雜性。

搭配 DRA 的解決方案

  • 動態資源選擇:DRA 允許工作負載在透過 的請求時間指定詳細需求 (GPU 記憶體、驅動程式版本和特定屬性)resourceclaims。這可讓資源比對更具彈性。

  • 拓撲感知:透過結構化參數和裝置選擇器,DRA 可處理複雜的需求,例如跨節點 GPU 通訊和記憶體一致性互連。

  • 跨節點資源管理:computeDomains啟用跨多個節點的分散式 GPU 資源協調,對於具有 IMEX 通道的 GB200 等系統至關重要。

  • 工作負載特定的組態:每個 ResourceClaim 指定不同的共用策略和組態,允許每個工作負載的精細控制,而不是整個叢集的設定。

  • 增強型排程器整合:DRA 提供排程器詳細的裝置資訊,並根據硬體拓撲和資源特性進行更明智的置放決策。

重要:DRA 不會完全取代 NVIDIA 裝置外掛程式。NVIDIA DRA 驅動程式可與裝置外掛程式搭配使用,以提供增強功能。裝置外掛程式會繼續處理基本的 GPU 探索和管理,而 DRA 新增進階配置和排程功能。

DRA 支援的執行個體及其功能

DRA 支援因 Amazon EC2 執行個體系列和 GPU 架構而異,如下表所示。

執行個體系列 GPU 類型 時間分割 MIG 支援 MPS 支援 IMEX 支援 使用案例

G5

NVIDIA A10G

推論和圖形工作負載

G6

NVIDIA L4

AI 推論和影片處理

G6e

NVIDIA L40S

訓練、推論和圖形

P4d/P4de

NVIDIA A100

大規模訓練和 HPC

P5

NVIDIA H100

基礎模型訓練

P6

NVIDIA B200

十億或兆參數模型、分散式訓練和推論

P6e

NVIDIA GB200

十億或兆參數模型、分散式訓練和推論

以下是 資料表中每個功能的描述:

  • 時間分割:允許多個工作負載隨時間共用 GPU 運算資源。

  • 多執行個體 GPU (MIG):建立隔離 GPU 執行個體的硬體層級分割。

  • 多程序服務 (MPS):在單一 GPU 上同時執行多個 CUDA 程序。

  • 節點間記憶體交換 (IMEX):GB200 UltraClusters 跨節點的記憶體一致性通訊。

其他資源

如需 Kubernetes DRA 和 NVIDIA DRA 驅動程式的詳細資訊,請參閱 GitHub 上的下列資源:

設定動態資源配置以進行進階 GPU 管理

下列主題說明如何設定動態資源配置 (DRA) 以進行進階 GPU 管理。

先決條件

在 Amazon EKS 上實作 DRA 之前,請確定您的環境符合下列要求。

叢集組態
必要元件
  • NVIDIA 裝置外掛程式版本 0.17.1 或更新版本

  • NVIDIA DRA 驅動程式版本 25.3.0 或更新版本

步驟 1:使用 eksctl 使用已啟用 DRA 的節點群組建立叢集

  1. 建立名為 的叢集組態檔案dra-eks-cluster.yaml

    --- apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: dra-eks-cluster region: us-west-2 version: '1.33' managedNodeGroups: - name: gpu-dra-nodes amiFamily: AmazonLinux2023 instanceType: g6.12xlarge desiredCapacity: 2 minSize: 1 maxSize: 3 labels: node-type: "gpu-dra" nvidia.com/gpu.present: "true" taints: - key: nvidia.com/gpu value: "true" effect: NoSchedule
  2. 建立叢集:

    eksctl create cluster -f dra-eks-cluster.yaml

步驟 2:部署 NVIDIA 裝置外掛程式

部署 NVIDIA 裝置外掛程式以啟用基本 GPU 探索:

  1. 新增 NVIDIA 裝置外掛程式 Helm 儲存庫:

    helm repo add nvidia https://nvidia.github.io/k8s-device-plugin helm repo update
  2. 為裝置外掛程式建立自訂值:

    cat <<EOF > nvidia-device-plugin-values.yaml gfd: enabled: true nfd: enabled: true tolerations: - key: [nvidia.com/gpu](http://nvidia.com/gpu) operator: Exists effect: NoSchedule EOF
  3. 安裝 NVIDIA 裝置外掛程式:

    helm install nvidia-device-plugin nvidia/nvidia-device-plugin \ --namespace nvidia-device-plugin \ --create-namespace \ --version v0.17.1 \ --values nvidia-device-plugin-values.yaml

步驟 3:部署 NVIDIA DRA 驅動程式 Helm Chart

  1. 建立 DRA 驅動程式dra-driver-values.yaml的值檔案:

    --- nvidiaDriverRoot: / gpuResourcesEnabledOverride: true resources: gpus: enabled: true computeDomains: enabled: true # Enable for GB200 IMEX support controller: tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule kubeletPlugin: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: "nvidia.com/gpu.present" operator: In values: ["true"] tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule
  2. 新增 NVIDIA NGC Helm 儲存庫:

    helm repo add nvidia https://helm.ngc.nvidia.com/nvidia helm repo update
  3. 安裝 NVIDIA DRA 驅動程式:

    helm install nvidia-dra-driver nvidia/nvidia-dra-driver-gpu \ --version="25.3.0-rc.2" \ --namespace nvidia-dra-driver \ --create-namespace \ --values dra-driver-values.yaml

步驟 4:驗證 DRA 安裝

  1. 驗證 DRA API 資源是否可用:

    kubectl api-resources | grep [resource.k8s.io/v1beta1](http://resource.k8s.io/v1beta1)

    以下是預期的輸出:

    deviceclasses [resource.k8s.io/v1beta1](http://resource.k8s.io/v1beta1) false DeviceClass resourceclaims [resource.k8s.io/v1beta1](http://resource.k8s.io/v1beta1) true ResourceClaim resourceclaimtemplates [resource.k8s.io/v1beta1](http://resource.k8s.io/v1beta1) true ResourceClaimTemplate resourceslices [resource.k8s.io/v1beta1](http://resource.k8s.io/v1beta1) false ResourceSlice
  2. 檢查可用的裝置類別:

    kubectl get deviceclasses

    以下是預期輸出的範例:

    NAME AGE compute-domain-daemon.nvidia.com 4h39m compute-domain-default-channel.nvidia.com 4h39m gpu.nvidia.com 4h39m mig.nvidia.com 4h39m

    當新建立的 G6 GPU 執行個體加入已啟用 DRA 的 Amazon EKS 叢集時,會發生下列動作:

    • NVIDIA DRA 驅動程式會自動探索 A10G GPU,並在該節點resourceslices上建立兩個 GPU。

    • gpu.nvidia.com 配量會將實體 A10G GPU 裝置與其規格 (記憶體、運算功能等) 註冊。

    • 由於 A10G 不支援 MIG 分割,compute-domain.nvidia.com配量會建立代表 GPU 整個運算內容的單一運算網域。

    • 這些resourceslices接著會發佈至 Kubernetes API 伺服器,讓 GPU 資源可透過 進行排程resourceclaims

      DRA 排程器現在可以智慧地將此 GPU 配置給透過 請求 GPU 資源的 Podresourceclaimtemplates,提供比傳統裝置外掛程式方法更靈活的資源管理。這會自動發生,無需手動介入。一旦 DRA 驅動程式完成資源探索和註冊程序,節點即可直接用於 GPU 工作負載。

      當您執行下列命令時:

      kubectl get resourceslices

      以下是預期輸出的範例:

      NAME NODE DRIVER POOL AGE ip-100-64-129-47.ec2.internal-compute-domain.nvidia.com-rwsts ip-100-64-129-47.ec2.internal compute-domain.nvidia.com ip-100-64-129-47.ec2.internal 35m ip-100-64-129-47.ec2.internal-gpu.nvidia.com-6kndg ip-100-64-129-47.ec2.internal gpu.nvidia.com ip-100-64-129-47.ec2.internal 35m

繼續進行使用動態資源配置排程簡單的 GPU 工作負載

使用動態資源配置排程簡單的 GPU 工作負載

若要使用動態資源配置 (DRA) 排程簡單的 GPU 工作負載,請執行下列步驟。在繼續之前,請確定您已遵循 設定動態資源配置以進行進階 GPU 管理

  1. 使用名為 ResourceClaimTemplate 的檔案建立 GPU 配置的基本basic-gpu-claim-template.yaml

    --- apiVersion: v1 kind: Namespace metadata: name: gpu-test1 --- apiVersion: resource.k8s.io/v1beta1 kind: ResourceClaimTemplate metadata: namespace: gpu-test1 name: single-gpu spec: spec: devices: requests: - name: gpu deviceClassName: gpu.nvidia.com
  2. 套用範本:

    kubectl apply -f basic-gpu-claim-template.yaml
  3. 驗證狀態:

    kubectl get resourceclaimtemplates -n gpu-test1

    下列為範例輸出:

    NAME AGE single-gpu 9m16s
  4. 建立使用 ResourceClaimTemplate 檔案名為 的 Podbasic-gpu-pod.yaml

    --- apiVersion: v1 kind: Pod metadata: namespace: gpu-test1 name: gpu-pod labels: app: pod spec: containers: - name: ctr0 image: ubuntu:22.04 command: ["bash", "-c"] args: ["nvidia-smi -L; trap 'exit 0' TERM; sleep 9999 & wait"] resources: claims: - name: gpu0 resourceClaims: - name: gpu0 resourceClaimTemplateName: single-gpu nodeSelector: NodeGroupType: gpu-dra nvidia.com/gpu.present: "true" tolerations: - key: "nvidia.com/gpu" operator: "Exists" effect: "NoSchedule"
  5. 套用和監控 Pod:

    kubectl apply -f basic-gpu-pod.yaml
  6. 檢查 Pod 狀態:

    kubectl get pod -n gpu-test1

    以下是預期的輸出範例:

    NAME READY STATUS RESTARTS AGE gpu-pod 1/1 Running 0 13m
  7. 檢查ResourceClaim狀態:

    kubectl get resourceclaims -n gpu-test1

    以下是預期的輸出範例:

    NAME STATE AGE gpu-pod-gpu0-l76cg allocated,reserved 9m6s
  8. 檢視 Pod 日誌以查看 GPU 資訊:

    kubectl logs gpu-pod -n gpu-test1

    以下是預期的輸出範例:

    GPU 0: NVIDIA L4 (UUID: GPU-da7c24d7-c7e3-ed3b-418c-bcecc32af7c5)

如需使用 DRA 具有動態資源配置的 GPU 最佳化技術 的更進階 GPU 最佳化技術,請繼續前往 。

具有動態資源配置的 GPU 最佳化技術

現代 GPU 工作負載需要複雜的資源管理,才能達到最佳的使用率和成本效益。DRA 啟用多種進階最佳化技術,可解決不同的使用案例和硬體功能:

這些技術可以大幅改善資源使用率。Organizations 報告 GPU 使用率從傳統配置的 30-40% 增加到最佳化共用策略的 80-90%。技術選擇取決於工作負載特性、隔離要求和硬體功能。

使用時間分割最佳化 GPU 工作負載

時間分割可讓多個工作負載透過排程在相同的實體 GPU 上循序執行,來共用 GPU 運算資源。它非常適合使用零星 GPU 的推論工作負載。

執行下列步驟。

  1. 使用名為 的檔案定義時間分割ResourceClaimTemplatetimeslicing-claim-template.yaml

    --- apiVersion: v1 kind: Namespace metadata: name: timeslicing-gpu --- apiVersion: resource.k8s.io/v1beta1 kind: ResourceClaimTemplate metadata: name: timeslicing-gpu-template namespace: timeslicing-gpu spec: spec: devices: requests: - name: shared-gpu deviceClassName: gpu.nvidia.com config: - requests: ["shared-gpu"] opaque: driver: gpu.nvidia.com parameters: apiVersion: resource.nvidia.com/v1beta1 kind: GpuConfig sharing: strategy: TimeSlicing
  2. 使用具有名為 的檔案的時間分割來定義 Podtimeslicing-pod.yaml

    --- # Pod 1 - Inference workload apiVersion: v1 kind: Pod metadata: name: inference-pod-1 namespace: timeslicing-gpu labels: app: gpu-inference spec: restartPolicy: Never containers: - name: inference-container image: nvcr.io/nvidia/pytorch:25.04-py3 command: ["python", "-c"] args: - | import torch import time import os print(f"=== POD 1 STARTING ===") print(f"GPU available: {torch.cuda.is_available()}") print(f"GPU count: {torch.cuda.device_count()}") if torch.cuda.is_available(): device = torch.cuda.current_device() print(f"Current GPU: {torch.cuda.get_device_name(device)}") print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1024**3:.1f} GB") # Simulate inference workload for i in range(20): x = torch.randn(1000, 1000).cuda() y = torch.mm(x, x.t()) print(f"Pod 1 - Iteration {i+1} completed at {time.strftime('%H:%M:%S')}") time.sleep(60) else: print("No GPU available!") time.sleep(5) resources: claims: - name: shared-gpu-claim resourceClaims: - name: shared-gpu-claim resourceClaimTemplateName: timeslicing-gpu-template nodeSelector: NodeGroupType: "gpu-dra" nvidia.com/gpu.present: "true" tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule --- # Pod 2 - Training workload apiVersion: v1 kind: Pod metadata: name: training-pod-2 namespace: timeslicing-gpu labels: app: gpu-training spec: restartPolicy: Never containers: - name: training-container image: nvcr.io/nvidia/pytorch:25.04-py3 command: ["python", "-c"] args: - | import torch import time import os print(f"=== POD 2 STARTING ===") print(f"GPU available: {torch.cuda.is_available()}") print(f"GPU count: {torch.cuda.device_count()}") if torch.cuda.is_available(): device = torch.cuda.current_device() print(f"Current GPU: {torch.cuda.get_device_name(device)}") print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1024**3:.1f} GB") # Simulate training workload with heavier compute for i in range(15): x = torch.randn(2000, 2000).cuda() y = torch.mm(x, x.t()) loss = torch.sum(y) print(f"Pod 2 - Training step {i+1}, Loss: {loss.item():.2f} at {time.strftime('%H:%M:%S')}") time.sleep(5) else: print("No GPU available!") time.sleep(60) resources: claims: - name: shared-gpu-claim-2 resourceClaims: - name: shared-gpu-claim-2 resourceClaimTemplateName: timeslicing-gpu-template nodeSelector: NodeGroupType: "gpu-dra" nvidia.com/gpu.present: "true" tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule
  3. 套用範本和 Pod:

    kubectl apply -f timeslicing-claim-template.yaml kubectl apply -f timeslicing-pod.yaml
  4. 監控資源宣告:

    kubectl get resourceclaims -n timeslicing-gpu -w

    下列為範例輸出:

    NAME STATE AGE inference-pod-1-shared-gpu-claim-9p97x allocated,reserved 21s training-pod-2-shared-gpu-claim-2-qghnb pending 21s inference-pod-1-shared-gpu-claim-9p97x pending 105s training-pod-2-shared-gpu-claim-2-qghnb pending 105s inference-pod-1-shared-gpu-claim-9p97x pending 105s training-pod-2-shared-gpu-claim-2-qghnb allocated,reserved 105s inference-pod-1-shared-gpu-claim-9p97x pending 105s

第一個 Pod (inference-pod-1)

  • 狀態allocated,reserved

  • 意義:DRA 找到可用的 GPU,並預留給此 Pod

  • Pod 狀態:立即開始執行

第二個 Pod (training-pod-2)

  • 狀態pending

  • 意義:等待 DRA 在相同 GPU 上設定時間分割

  • Pod 狀態:等待排程

  • 狀態將從 移至 pending allocated,reservedrunning

使用 MPS 最佳化 GPU 工作負載

多程序服務 (MPS) 可在單一 GPU 上並行執行多個 CUDA 內容,比時間分割具有更好的隔離能力。

執行下列步驟。

  1. 使用名為 的檔案為 ResourceClaimTemplate MPS 定義 mps-claim-template.yaml

    --- apiVersion: v1 kind: Namespace metadata: name: mps-gpu --- apiVersion: resource.k8s.io/v1beta1 kind: ResourceClaimTemplate metadata: name: mps-gpu-template namespace: mps-gpu spec: spec: devices: requests: - name: shared-gpu deviceClassName: gpu.nvidia.com config: - requests: ["shared-gpu"] opaque: driver: gpu.nvidia.com parameters: apiVersion: resource.nvidia.com/v1beta1 kind: GpuConfig sharing: strategy: MPS
  2. 使用 MPS 搭配名為 的檔案來定義 Podmps-pod.yaml

    --- # Single Pod with Multiple Containers sharing GPU via MPS apiVersion: v1 kind: Pod metadata: name: mps-multi-container-pod namespace: mps-gpu labels: app: mps-demo spec: restartPolicy: Never containers: # Container 1 - Inference workload - name: inference-container image: nvcr.io/nvidia/pytorch:25.04-py3 command: ["python", "-c"] args: - | import torch import torch.nn as nn import time import os print(f"=== INFERENCE CONTAINER STARTING ===") print(f"Process ID: {os.getpid()}") print(f"GPU available: {torch.cuda.is_available()}") print(f"GPU count: {torch.cuda.device_count()}") if torch.cuda.is_available(): device = torch.cuda.current_device() print(f"Current GPU: {torch.cuda.get_device_name(device)}") print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1024**3:.1f} GB") # Create inference model model = nn.Sequential( nn.Linear(1000, 500), nn.ReLU(), nn.Linear(500, 100) ).cuda() # Run inference for i in range(1, 999999): with torch.no_grad(): x = torch.randn(128, 1000).cuda() output = model(x) result = torch.sum(output) print(f"Inference Container PID {os.getpid()}: Batch {i}, Result: {result.item():.2f} at {time.strftime('%H:%M:%S')}") time.sleep(2) else: print("No GPU available!") time.sleep(60) resources: claims: - name: shared-gpu-claim request: shared-gpu # Container 2 - Training workload - name: training-container image: nvcr.io/nvidia/pytorch:25.04-py3 command: ["python", "-c"] args: - | import torch import torch.nn as nn import time import os print(f"=== TRAINING CONTAINER STARTING ===") print(f"Process ID: {os.getpid()}") print(f"GPU available: {torch.cuda.is_available()}") print(f"GPU count: {torch.cuda.device_count()}") if torch.cuda.is_available(): device = torch.cuda.current_device() print(f"Current GPU: {torch.cuda.get_device_name(device)}") print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1024**3:.1f} GB") # Create training model model = nn.Sequential( nn.Linear(2000, 1000), nn.ReLU(), nn.Linear(1000, 500), nn.ReLU(), nn.Linear(500, 10) ).cuda() criterion = nn.MSELoss() optimizer = torch.optim.Adam(model.parameters(), lr=0.001) # Run training for epoch in range(1, 999999): x = torch.randn(64, 2000).cuda() target = torch.randn(64, 10).cuda() optimizer.zero_grad() output = model(x) loss = criterion(output, target) loss.backward() optimizer.step() print(f"Training Container PID {os.getpid()}: Epoch {epoch}, Loss: {loss.item():.4f} at {time.strftime('%H:%M:%S')}") time.sleep(3) else: print("No GPU available!") time.sleep(60) resources: claims: - name: shared-gpu-claim request: shared-gpu resourceClaims: - name: shared-gpu-claim resourceClaimTemplateName: mps-gpu-template nodeSelector: NodeGroupType: "gpu-dra" nvidia.com/gpu.present: "true" tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule
  3. 套用範本並建立多個 MPS Pod:

    kubectl apply -f mps-claim-template.yaml kubectl apply -f mps-pod.yaml
  4. 監控資源宣告:

    kubectl get resourceclaims -n mps-gpu -w

    下列為範例輸出:

    NAME STATE AGE mps-multi-container-pod-shared-gpu-claim-2p9kx allocated,reserved 86s

此組態透過動態資源分配 (DRA),使用 NVIDIA Multi-Process Service (MPS) 示範真正的 GPU 共用。與使用 GPU 依序輪換工作負載的時間分割不同,MPS 可讓兩個容器同時在相同的實體 GPU 上執行。關鍵洞見是 DRA MPS 共用需要單一 Pod 中的多個容器,而不是多個單獨的 Pod。部署時,DRA 驅動程式會將一個配置ResourceClaim給 Pod,並自動設定 MPS,以允許推論和訓練容器同時執行。

每個容器都有自己的隔離 GPU 記憶體空間和運算資源,搭配 MPS 協助程式來協調基礎硬體的存取。您可以執行下列動作來驗證是否正常運作:

  • 檢查 nvidia-smi,這會將兩個容器顯示為共用相同 GPU 裝置的 M+C (MPS + Compute) 程序。

  • 從兩個容器監控日誌,這會顯示可同時執行的交錯時間戳記。

這種方法允許互補工作負載有效率地共用昂貴的 GPU 硬體,而不是讓單一程序未充分利用 GPU 使用率,從而最大限度地提高 GPU 使用率。

Container1: inference-container
root@mps-multi-container-pod:/workspace# nvidia-smi Wed Jul 16 21:09:30 2025 +-----------------------------------------------------------------------------------------+ | NVIDIA-SMI 570.158.01 Driver Version: 570.158.01 CUDA Version: 12.9 | |-----------------------------------------+------------------------+----------------------+ | 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:35:00.0 Off | 0 | | N/A 48C P0 28W / 72W | 597MiB / 23034MiB | 0% E. Process | | | | N/A | +-----------------------------------------+------------------------+----------------------+ +-----------------------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=========================================================================================| | 0 N/A N/A 1 M+C python 246MiB | +-----------------------------------------------------------------------------------------+
Container2: training-container
root@mps-multi-container-pod:/workspace# nvidia-smi Wed Jul 16 21:16:00 2025 +-----------------------------------------------------------------------------------------+ | NVIDIA-SMI 570.158.01 Driver Version: 570.158.01 CUDA Version: 12.9 | |-----------------------------------------+------------------------+----------------------+ | 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:35:00.0 Off | 0 | | N/A 51C P0 28W / 72W | 597MiB / 23034MiB | 0% E. Process | | | | N/A | +-----------------------------------------+------------------------+----------------------+ +-----------------------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=========================================================================================| | 0 N/A N/A 1 M+C python 314MiB | +-----------------------------------------------------------------------------------------+

使用多執行個體 GPU 最佳化 GPU 工作負載

多執行個體 GPU (MIG) 提供硬體層級分割,以專用運算和記憶體資源建立隔離的 GPU 執行個體。

搭配各種設定檔使用動態 MIG 分割需要 NVIDIA GPU Operator。NVIDIA GPU Operator 使用 MIG Manager 建立 MIG 設定檔,並重新啟動 P4D, P4De, P5, P6 等 GPU 執行個體,以套用組態變更。GPU Operator 透過 MIG Manager 元件包含完整的 MIG 管理功能,可監控節點標籤變更並自動套用適當的 MIG 組態。請求 MIG 設定檔變更時,運算子會正常關閉所有 GPU 用戶端、套用新的分割區幾何,並重新啟動受影響的服務。此程序需要重新啟動 GPU 執行個體的節點,以確保 GPU 狀態的轉換乾淨。這就是為什麼在 MIG Manager 組態WITH–0—REBOOT=true中啟用 對成功的 MIG 部署至關重要。

您需要 NVIDIA DRA 驅動程式和 NVIDIA GPU Operator 才能在 Amazon EKS 中使用 MIG。除此之外,您不需要 NVIDIA 裝置外掛程式和 DCGM Exporter,因為這些是 NVIDIA GPU Operator 的一部分。由於 EKS NVIDIA AMIs 隨附預先安裝的 NVIDIA 驅動程式,因此我們停用 GPU Operator 部署驅動程式,以避免衝突並利用執行個體上已存在的最佳化驅動程式。NVIDIA DRA 驅動程式會處理 MIG 執行個體的動態資源配置,而 GPU Operator 會管理整個 GPU 生命週期。這包括 MIG 組態、裝置外掛程式功能、透過 DCGM 監控,以及節點功能探索。這種整合方法為企業 GPU 管理提供了完整的解決方案,具有硬體層級隔離和動態資源配置功能。

步驟 1:部署 NVIDIA GPU Operator
  1. 新增 NVIDIA GPU Operator 儲存庫:

    helm repo add nvidia https://nvidia.github.io/gpu-operator helm repo update
  2. 建立gpu-operator-values.yaml檔案:

    driver: enabled: false mig: strategy: mixed migManager: enabled: true env: - name: WITH_REBOOT value: "true" config: create: true name: custom-mig-parted-configs default: "all-disabled" data: config.yaml: |- version: v1 mig-configs: all-disabled: - devices: all mig-enabled: false # P4D profiles (A100 40GB) p4d-half-balanced: - devices: [0, 1, 2, 3] mig-enabled: true mig-devices: "1g.5gb": 2 "2g.10gb": 1 "3g.20gb": 1 - devices: [4, 5, 6, 7] mig-enabled: false # P4DE profiles (A100 80GB) p4de-half-balanced: - devices: [0, 1, 2, 3] mig-enabled: true mig-devices: "1g.10gb": 2 "2g.20gb": 1 "3g.40gb": 1 - devices: [4, 5, 6, 7] mig-enabled: false devicePlugin: enabled: true config: name: "" create: false default: "" toolkit: enabled: true nfd: enabled: true gfd: enabled: true dcgmExporter: enabled: true serviceMonitor: enabled: true interval: 15s honorLabels: false additionalLabels: release: kube-prometheus-stack nodeStatusExporter: enabled: false operator: defaultRuntime: containerd runtimeClass: nvidia resources: limits: cpu: 500m memory: 350Mi requests: cpu: 200m memory: 100Mi daemonsets: tolerations: - key: "nvidia.com/gpu" operator: "Exists" effect: "NoSchedule" nodeSelector: accelerator: nvidia priorityClassName: system-node-critical
  3. 使用 gpu-operator-values.yaml 檔案安裝 GPU Operator:

    helm install gpu-operator nvidia/gpu-operator \ --namespace gpu-operator \ --create-namespace \ --version v25.3.1 \ --values gpu-operator-values.yaml

    此 Helm Chart 部署下列元件和多個 MIG 設定檔:

    • 裝置外掛程式 (GPU 資源排程)

    • DCGM Exporter (GPU 指標和監控)

    • 節點功能探索 (NFD - 硬體標籤)

    • GPU 功能探索 (GFD - GPU 特定標籤)

    • MIG Manager (多執行個體 GPU 分割)

    • Container Toolkit (GPU 容器執行時間)

    • 運算子控制器 (生命週期管理)

  4. 驗證部署 Pod:

    kubectl get pods -n gpu-operator

    下列為範例輸出:

    NAME READY STATUS RESTARTS AGE gpu-feature-discovery-27rdq 1/1 Running 0 3h31m gpu-operator-555774698d-48brn 1/1 Running 0 4h8m nvidia-container-toolkit-daemonset-sxmh9 1/1 Running 1 (3h32m ago) 4h1m nvidia-cuda-validator-qb77g 0/1 Completed 0 3h31m nvidia-dcgm-exporter-cvzd7 1/1 Running 0 3h31m nvidia-device-plugin-daemonset-5ljm5 1/1 Running 0 3h31m nvidia-gpu-operator-node-feature-discovery-gc-67f66fc557-q5wkt 1/1 Running 0 4h8m nvidia-gpu-operator-node-feature-discovery-master-5d8ffddcsl6s6 1/1 Running 0 4h8m nvidia-gpu-operator-node-feature-discovery-worker-6t4w7 1/1 Running 1 (3h32m ago) 4h1m nvidia-gpu-operator-node-feature-discovery-worker-9w7g8 1/1 Running 0 4h8m nvidia-gpu-operator-node-feature-discovery-worker-k5fgs 1/1 Running 0 4h8m nvidia-mig-manager-zvf54 1/1 Running 1 (3h32m ago) 3h35m
  5. 使用 p4De 受管節點群組建立 Amazon EKS 叢集,以測試 MIG 範例:

    apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: dra-eks-cluster region: us-east-1 version: '1.33' managedNodeGroups: # P4DE MIG Node Group with Capacity Block Reservation - name: p4de-mig-nodes amiFamily: AmazonLinux2023 instanceType: p4de.24xlarge # Capacity settings desiredCapacity: 0 minSize: 0 maxSize: 1 # Use specific subnet in us-east-1b for capacity reservation subnets: - us-east-1b # AL2023 NodeConfig for RAID0 local storage only nodeadmConfig: apiVersion: node.eks.aws/v1alpha1 kind: NodeConfig spec: instance: localStorage: strategy: RAID0 # Node labels for MIG configuration labels: nvidia.com/gpu.present: "true" nvidia.com/gpu.product: "A100-SXM4-80GB" nvidia.com/mig.config: "p4de-half-balanced" node-type: "p4de" vpc.amazonaws.com/efa.present: "true" accelerator: "nvidia" # Node taints taints: - key: nvidia.com/gpu value: "true" effect: NoSchedule # EFA support efaEnabled: true # Placement group for high-performance networking placementGroup: groupName: p4de-placement-group strategy: cluster # Capacity Block Reservation (CBR) # Ensure CBR ID matches the subnet AZ with the Nodegroup subnet spot: false capacityReservation: capacityReservationTarget: capacityReservationId: "cr-abcdefghij" # Replace with your capacity reservation ID

    NVIDIA GPU Operator 使用新增至節點的標籤,nvidia.com/mig.config: "p4de-half-balanced"並以指定的設定檔分割 GPU。

  6. 登入p4de執行個體。

  7. 執行以下命令:

    nvidia-smi -L

    您應該會看到下列範例輸出:

    [root@ip-100-64-173-145 bin]# nvidia-smi -L GPU 0: NVIDIA A100-SXM4-80GB (UUID: GPU-ab52e33c-be48-38f2-119e-b62b9935925a) MIG 3g.40gb Device 0: (UUID: MIG-da972af8-a20a-5f51-849f-bc0439f7970e) MIG 2g.20gb Device 1: (UUID: MIG-7f9768b7-11a6-5de9-a8aa-e9c424400da4) MIG 1g.10gb Device 2: (UUID: MIG-498adad6-6cf7-53af-9d1a-10cfd1fa53b2) MIG 1g.10gb Device 3: (UUID: MIG-3f55ef65-1991-571a-ac50-0dbf50d80c5a) GPU 1: NVIDIA A100-SXM4-80GB (UUID: GPU-0eabeccc-7498-c282-0ac7-d3c09f6af0c8) MIG 3g.40gb Device 0: (UUID: MIG-80543849-ea3b-595b-b162-847568fe6e0e) MIG 2g.20gb Device 1: (UUID: MIG-3af1958f-fac4-59f1-8477-9f8d08c55029) MIG 1g.10gb Device 2: (UUID: MIG-401088d2-716f-527b-a970-b1fc7a4ac6b2) MIG 1g.10gb Device 3: (UUID: MIG-8c56c75e-5141-501c-8f43-8cf22f422569) GPU 2: NVIDIA A100-SXM4-80GB (UUID: GPU-1c7a1289-243f-7872-a35c-1d2d8af22dd0) MIG 3g.40gb Device 0: (UUID: MIG-e9b44486-09fc-591a-b904-0d378caf2276) MIG 2g.20gb Device 1: (UUID: MIG-ded93941-9f64-56a3-a9b1-a129c6edf6e4) MIG 1g.10gb Device 2: (UUID: MIG-6c317d83-a078-5c25-9fa3-c8308b379aa1) MIG 1g.10gb Device 3: (UUID: MIG-2b070d39-d4e9-5b11-bda6-e903372e3d08) GPU 3: NVIDIA A100-SXM4-80GB (UUID: GPU-9a6250e2-5c59-10b7-2da8-b61d8a937233) MIG 3g.40gb Device 0: (UUID: MIG-20e3cd87-7a57-5f1b-82e7-97b14ab1a5aa) MIG 2g.20gb Device 1: (UUID: MIG-04430354-1575-5b42-95f4-bda6901f1ace) MIG 1g.10gb Device 2: (UUID: MIG-d62ec8b6-e097-5e99-a60c-abf8eb906f91) MIG 1g.10gb Device 3: (UUID: MIG-fce20069-2baa-5dd4-988a-cead08348ada) GPU 4: NVIDIA A100-SXM4-80GB (UUID: GPU-5d09daf0-c2eb-75fd-3919-7ad8fafa5f86) GPU 5: NVIDIA A100-SXM4-80GB (UUID: GPU-99194e04-ab2a-b519-4793-81cb2e8e9179) GPU 6: NVIDIA A100-SXM4-80GB (UUID: GPU-c1a1910f-465a-e16f-5af1-c6aafe499cd6) GPU 7: NVIDIA A100-SXM4-80GB (UUID: GPU-c2cfafbc-fd6e-2679-e955-2a9e09377f78)

NVIDIA GPU Operator 已成功將 p4de-half-balanced MIG 設定檔套用至 P4DE 執行個體,並依設定建立硬體層級 GPU 分割區。以下是分割的運作方式:

GPU Operator 從您的內嵌 MIG 設定檔套用此組態:

p4de-half-balanced: - devices: [0, 1, 2, 3] # First 4 GPUs: MIG enabled mig-enabled: true mig-devices: "1g.10gb": 2 # 2x small instances (10GB each) "2g.20gb": 1 # 1x medium instance (20GB) "3g.40gb": 1 # 1x large instance (40GB) - devices: [4, 5, 6, 7] # Last 4 GPUs: Full GPUs mig-enabled: false

從您的nvidia-smi -L輸出中,GPU Operator 建立的內容如下:

  • 啟用 MIG 的 GPUs (0-3):硬體分割

    • GPU 0:NVIDIA A100-SXM4-80GB

      • MIG 3g.40gb 裝置 0 – 大型工作負載 (40GB 記憶體、42 個 SMs)

      • MIG 2g.20gb 裝置 1 – 中型工作負載 (20GB 記憶體、28 個 SMs)

      • MIG 1g.10gb 裝置 2 – 小型工作負載 (10GB 記憶體、14 個 SMs)

      • MIG 1g.10gb 裝置 3 – 小型工作負載 (10GB 記憶體、14 個 SMs)

    • GPU 1:NVIDIA A100-SXM4-80GB

      • MIG 3g.40gb 裝置 0 – 相同的分割區配置

      • MIG 2g.20gb 裝置 1

      • MIG 1g.10gb 裝置 2

      • MIG 1g.10gb 裝置 3

    • GPU 2 和 GPU 3 – 與 GPU 0 和 GPU 1 相同的模式

  • 完整 GPUs (4-7):無 MIG 分割

    • GPU 4:NVIDIA A100-SXM4-80GB – 完整 80GB GPU

    • GPU 5:NVIDIA A100-SXM4-80GB – 完整 80GB GPU

    • GPU 6:NVIDIA A100-SXM4-80GB – 完整 80GB GPU

    • GPU 7:NVIDIA A100-SXM4-80GB – 完整 80GB GPU

NVIDIA GPU Operator 建立 MIG 分割區後,NVIDIA DRA 驅動程式會自動偵測這些硬體隔離的執行個體,並將其用於 Kubernetes 中的動態資源配置。DRA 驅動程式會使用其特定設定檔 (1g.10gb、2g.20gb、3g.40gb) 探索每個 MIG 執行個體,並透過mig.nvidia.com裝置類別將其公開為可排程的資源。

DRA 驅動程式會持續監控 MIG 拓撲,並維護所有 GPUs 中可用執行個體的庫存。當 Pod 透過 請求特定 MIG 設定檔時ResourceClaimTemplate,DRA 驅動程式會智慧地從任何可用的 GPU 選取適當的 MIG 執行個體,從而實現真正的硬體層級多租用戶。此動態配置可讓多個隔離的工作負載同時在相同的實體 GPU 上執行,同時維持嚴格的資源界限和效能保證。

步驟 2:測試 MIG 資源配置

現在,讓我們執行一些範例,示範 DRA 如何將 MIG 執行個體動態分配給不同的工作負載。部署 resourceclaimtemplates和 測試 Pod,以查看 DRA 驅動程式如何在可用的 MIG 分割區之間放置工作負載,允許多個容器與硬體層級隔離共用 GPU 資源。

  1. 建立 mig-claim-template.yaml以包含 MIGresourceclaimtemplates

    apiVersion: v1 kind: Namespace metadata: name: mig-gpu --- # Template for 3g.40gb MIG instance (Large training) apiVersion: resource.k8s.io/v1beta1 kind: ResourceClaimTemplate metadata: name: mig-large-template namespace: mig-gpu spec: spec: devices: requests: - name: mig-large deviceClassName: mig.nvidia.com selectors: - cel: expression: | device.attributes['gpu.nvidia.com'].profile == '3g.40gb' --- # Template for 2g.20gb MIG instance (Medium training) apiVersion: resource.k8s.io/v1beta1 kind: ResourceClaimTemplate metadata: name: mig-medium-template namespace: mig-gpu spec: spec: devices: requests: - name: mig-medium deviceClassName: mig.nvidia.com selectors: - cel: expression: | device.attributes['gpu.nvidia.com'].profile == '2g.20gb' --- # Template for 1g.10gb MIG instance (Small inference) apiVersion: resource.k8s.io/v1beta1 kind: ResourceClaimTemplate metadata: name: mig-small-template namespace: mig-gpu spec: spec: devices: requests: - name: mig-small deviceClassName: mig.nvidia.com selectors: - cel: expression: | device.attributes['gpu.nvidia.com'].profile == '1g.10gb'
  2. 套用三個範本:

    kubectl apply -f mig-claim-template.yaml
  3. 執行以下命令:

    kubectl get resourceclaimtemplates -n mig-gpu

    下列為範例輸出:

    NAME AGE mig-large-template 71m mig-medium-template 71m mig-small-template 71m
  4. 建立 mig-pod.yaml 以排程多個任務,以利用此 resourceclaimtemplates

    --- # ConfigMap containing Python scripts for MIG pods apiVersion: v1 kind: ConfigMap metadata: name: mig-scripts-configmap namespace: mig-gpu data: large-training-script.py: | import torch import torch.nn as nn import torch.optim as optim import time import os print(f"=== LARGE TRAINING POD (3g.40gb) ===") print(f"Process ID: {os.getpid()}") print(f"GPU available: {torch.cuda.is_available()}") print(f"GPU count: {torch.cuda.device_count()}") if torch.cuda.is_available(): device = torch.cuda.current_device() print(f"Using GPU: {torch.cuda.get_device_name(device)}") print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1e9:.1f} GB") # Large model for 3g.40gb instance model = nn.Sequential( nn.Linear(2048, 1024), nn.ReLU(), nn.Linear(1024, 512), nn.ReLU(), nn.Linear(512, 256), nn.ReLU(), nn.Linear(256, 10) ).cuda() optimizer = optim.Adam(model.parameters()) criterion = nn.CrossEntropyLoss() print(f"Model parameters: {sum(p.numel() for p in model.parameters())}") # Training loop for epoch in range(100): # Large batch for 3g.40gb x = torch.randn(256, 2048).cuda() y = torch.randint(0, 10, (256,)).cuda() optimizer.zero_grad() output = model(x) loss = criterion(output, y) loss.backward() optimizer.step() if epoch % 10 == 0: print(f"Large Training - Epoch {epoch}, Loss: {loss.item():.4f}, GPU Memory: {torch.cuda.memory_allocated()/1e9:.2f}GB") time.sleep(3) print("Large training completed on 3g.40gb MIG instance") medium-training-script.py: | import torch import torch.nn as nn import torch.optim as optim import time import os print(f"=== MEDIUM TRAINING POD (2g.20gb) ===") print(f"Process ID: {os.getpid()}") print(f"GPU available: {torch.cuda.is_available()}") print(f"GPU count: {torch.cuda.device_count()}") if torch.cuda.is_available(): device = torch.cuda.current_device() print(f"Using GPU: {torch.cuda.get_device_name(device)}") print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1e9:.1f} GB") # Medium model for 2g.20gb instance model = nn.Sequential( nn.Linear(1024, 512), nn.ReLU(), nn.Linear(512, 256), nn.ReLU(), nn.Linear(256, 10) ).cuda() optimizer = optim.Adam(model.parameters()) criterion = nn.CrossEntropyLoss() print(f"Model parameters: {sum(p.numel() for p in model.parameters())}") # Training loop for epoch in range(100): # Medium batch for 2g.20gb x = torch.randn(128, 1024).cuda() y = torch.randint(0, 10, (128,)).cuda() optimizer.zero_grad() output = model(x) loss = criterion(output, y) loss.backward() optimizer.step() if epoch % 10 == 0: print(f"Medium Training - Epoch {epoch}, Loss: {loss.item():.4f}, GPU Memory: {torch.cuda.memory_allocated()/1e9:.2f}GB") time.sleep(4) print("Medium training completed on 2g.20gb MIG instance") small-inference-script.py: | import torch import torch.nn as nn import time import os print(f"=== SMALL INFERENCE POD (1g.10gb) ===") print(f"Process ID: {os.getpid()}") print(f"GPU available: {torch.cuda.is_available()}") print(f"GPU count: {torch.cuda.device_count()}") if torch.cuda.is_available(): device = torch.cuda.current_device() print(f"Using GPU: {torch.cuda.get_device_name(device)}") print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1e9:.1f} GB") # Small model for 1g.10gb instance model = nn.Sequential( nn.Linear(512, 256), nn.ReLU(), nn.Linear(256, 10) ).cuda() print(f"Model parameters: {sum(p.numel() for p in model.parameters())}") # Inference loop for i in range(200): with torch.no_grad(): # Small batch for 1g.10gb x = torch.randn(32, 512).cuda() output = model(x) prediction = torch.argmax(output, dim=1) if i % 20 == 0: print(f"Small Inference - Batch {i}, Predictions: {prediction[:5].tolist()}, GPU Memory: {torch.cuda.memory_allocated()/1e9:.2f}GB") time.sleep(2) print("Small inference completed on 1g.10gb MIG instance") --- # Pod 1: Large training workload (3g.40gb) apiVersion: v1 kind: Pod metadata: name: mig-large-training-pod namespace: mig-gpu labels: app: mig-large-training workload-type: training spec: restartPolicy: Never containers: - name: large-training-container image: nvcr.io/nvidia/pytorch:25.04-py3 command: ["python", "/scripts/large-training-script.py"] volumeMounts: - name: script-volume mountPath: /scripts readOnly: true resources: claims: - name: mig-large-claim resourceClaims: - name: mig-large-claim resourceClaimTemplateName: mig-large-template nodeSelector: node.kubernetes.io/instance-type: p4de.24xlarge nvidia.com/gpu.present: "true" tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule volumes: - name: script-volume configMap: name: mig-scripts-configmap defaultMode: 0755 --- # Pod 2: Medium training workload (2g.20gb) - can run on SAME GPU as Pod 1 apiVersion: v1 kind: Pod metadata: name: mig-medium-training-pod namespace: mig-gpu labels: app: mig-medium-training workload-type: training spec: restartPolicy: Never containers: - name: medium-training-container image: nvcr.io/nvidia/pytorch:25.04-py3 command: ["python", "/scripts/medium-training-script.py"] volumeMounts: - name: script-volume mountPath: /scripts readOnly: true resources: claims: - name: mig-medium-claim resourceClaims: - name: mig-medium-claim resourceClaimTemplateName: mig-medium-template nodeSelector: node.kubernetes.io/instance-type: p4de.24xlarge nvidia.com/gpu.present: "true" tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule volumes: - name: script-volume configMap: name: mig-scripts-configmap defaultMode: 0755 --- # Pod 3: Small inference workload (1g.10gb) - can run on SAME GPU as Pod 1 & 2 apiVersion: v1 kind: Pod metadata: name: mig-small-inference-pod namespace: mig-gpu labels: app: mig-small-inference workload-type: inference spec: restartPolicy: Never containers: - name: small-inference-container image: nvcr.io/nvidia/pytorch:25.04-py3 command: ["python", "/scripts/small-inference-script.py"] volumeMounts: - name: script-volume mountPath: /scripts readOnly: true resources: claims: - name: mig-small-claim resourceClaims: - name: mig-small-claim resourceClaimTemplateName: mig-small-template nodeSelector: node.kubernetes.io/instance-type: p4de.24xlarge nvidia.com/gpu.present: "true" tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule volumes: - name: script-volume configMap: name: mig-scripts-configmap defaultMode: 0755
  5. 套用此規格,應部署三個 Pod:

    kubctl apply -f mig-pod.yaml

    這些 Pod 應由 DRA 驅動程式排程。

  6. 檢查 DRA 驅動程式 Pod 日誌,您會看到類似以下的輸出:

    I0717 21:50:22.925811 1 driver.go:87] NodePrepareResource is called: number of claims: 1 I0717 21:50:22.932499 1 driver.go:129] Returning newly prepared devices for claim '933e9c72-6fd6-49c5-933c-a896407dc6d1': [&Device{RequestNames:[mig-large],PoolName:ip-100-64-173-145.ec2.internal,DeviceName:gpu-0-mig-9-4-4,CDIDeviceIDs:[k8s.gpu.nvidia.com/device=**gpu-0-mig-9-4-4**],}] I0717 21:50:23.186472 1 driver.go:87] NodePrepareResource is called: number of claims: 1 I0717 21:50:23.191226 1 driver.go:129] Returning newly prepared devices for claim '61e5ddd2-8c2e-4c19-93ae-d317fecb44a4': [&Device{RequestNames:[mig-medium],PoolName:ip-100-64-173-145.ec2.internal,DeviceName:gpu-2-mig-14-0-2,CDIDeviceIDs:[k8s.gpu.nvidia.com/device=**gpu-2-mig-14-0-2**],}] I0717 21:50:23.450024 1 driver.go:87] NodePrepareResource is called: number of claims: 1 I0717 21:50:23.455991 1 driver.go:129] Returning newly prepared devices for claim '1eda9b2c-2ea6-401e-96d0-90e9b3c111b5': [&Device{RequestNames:[mig-small],PoolName:ip-100-64-173-145.ec2.internal,DeviceName:gpu-1-mig-19-2-1,CDIDeviceIDs:[k8s.gpu.nvidia.com/device=**gpu-1-mig-19-2-1**],}]
  7. 驗證 resourceclaims 以查看 Pod 狀態:

    kubectl get resourceclaims -n mig-gpu -w

    下列為範例輸出:

    NAME STATE AGE mig-large-training-pod-mig-large-claim-6dpn8 pending 0s mig-large-training-pod-mig-large-claim-6dpn8 pending 0s mig-large-training-pod-mig-large-claim-6dpn8 allocated,reserved 0s mig-medium-training-pod-mig-medium-claim-bk596 pending 0s mig-medium-training-pod-mig-medium-claim-bk596 pending 0s mig-medium-training-pod-mig-medium-claim-bk596 allocated,reserved 0s mig-small-inference-pod-mig-small-claim-d2t58 pending 0s mig-small-inference-pod-mig-small-claim-d2t58 pending 0s mig-small-inference-pod-mig-small-claim-d2t58 allocated,reserved 0s

    如您所見,DRA 驅動程式會將所有 Pod 從待定移至 allocated,reserved

  8. nvidia-smi 從節點執行 。您會注意到有三個 Python 處理器正在執行:

    root@ip-100-64-173-145 bin]# nvidia-smi +-----------------------------------------------------------------------------------------+ | NVIDIA-SMI 570.158.01 Driver Version: 570.158.01 CUDA Version: 12.8 | |-----------------------------------------+------------------------+----------------------+ | 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 A100-SXM4-80GB On | 00000000:10:1C.0 Off | On | | N/A 63C P0 127W / 400W | 569MiB / 81920MiB | N/A Default | | | | Enabled | +-----------------------------------------+------------------------+----------------------+ | 1 NVIDIA A100-SXM4-80GB On | 00000000:10:1D.0 Off | On | | N/A 56C P0 121W / 400W | 374MiB / 81920MiB | N/A Default | | | | Enabled | +-----------------------------------------+------------------------+----------------------+ | 2 NVIDIA A100-SXM4-80GB On | 00000000:20:1C.0 Off | On | | N/A 63C P0 128W / 400W | 467MiB / 81920MiB | N/A Default | | | | Enabled | +-----------------------------------------+------------------------+----------------------+ | 3 NVIDIA A100-SXM4-80GB On | 00000000:20:1D.0 Off | On | | N/A 57C P0 118W / 400W | 249MiB / 81920MiB | N/A Default | | | | Enabled | +-----------------------------------------+------------------------+----------------------+ | 4 NVIDIA A100-SXM4-80GB On | 00000000:90:1C.0 Off | 0 | | N/A 51C P0 77W / 400W | 0MiB / 81920MiB | 0% Default | | | | Disabled | +-----------------------------------------+------------------------+----------------------+ | 5 NVIDIA A100-SXM4-80GB On | 00000000:90:1D.0 Off | 0 | | N/A 46C P0 69W / 400W | 0MiB / 81920MiB | 0% Default | | | | Disabled | +-----------------------------------------+------------------------+----------------------+ | 6 NVIDIA A100-SXM4-80GB On | 00000000:A0:1C.0 Off | 0 | | N/A 52C P0 74W / 400W | 0MiB / 81920MiB | 0% Default | | | | Disabled | +-----------------------------------------+------------------------+----------------------+ | 7 NVIDIA A100-SXM4-80GB On | 00000000:A0:1D.0 Off | 0 | | N/A 47C P0 72W / 400W | 0MiB / 81920MiB | 0% Default | | | | Disabled | +-----------------------------------------+------------------------+----------------------+ +-----------------------------------------------------------------------------------------+ | MIG devices: | +------------------+----------------------------------+-----------+-----------------------+ | GPU GI CI MIG | Memory-Usage | Vol| Shared | | ID ID Dev | BAR1-Usage | SM Unc| CE ENC DEC OFA JPG | | | | ECC| | |==================+==================================+===========+=======================| | 0 2 0 0 | 428MiB / 40192MiB | 42 0 | 3 0 2 0 0 | | | 2MiB / 32767MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 0 3 0 1 | 71MiB / 19968MiB | 28 0 | 2 0 1 0 0 | | | 0MiB / 16383MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 0 9 0 2 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 | | | 0MiB / 8191MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 0 10 0 3 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 | | | 0MiB / 8191MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 1 1 0 0 | 107MiB / 40192MiB | 42 0 | 3 0 2 0 0 | | | 0MiB / 32767MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 1 5 0 1 | 71MiB / 19968MiB | 28 0 | 2 0 1 0 0 | | | 0MiB / 16383MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 1 13 0 2 | 161MiB / 9728MiB | 14 0 | 1 0 0 0 0 | | | 2MiB / 8191MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 1 14 0 3 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 | | | 0MiB / 8191MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 2 1 0 0 | 107MiB / 40192MiB | 42 0 | 3 0 2 0 0 | | | 0MiB / 32767MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 2 5 0 1 | 289MiB / 19968MiB | 28 0 | 2 0 1 0 0 | | | 2MiB / 16383MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 2 13 0 2 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 | | | 0MiB / 8191MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 2 14 0 3 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 | | | 0MiB / 8191MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 3 1 0 0 | 107MiB / 40192MiB | 42 0 | 3 0 2 0 0 | | | 0MiB / 32767MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 3 5 0 1 | 71MiB / 19968MiB | 28 0 | 2 0 1 0 0 | | | 0MiB / 16383MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 3 13 0 2 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 | | | 0MiB / 8191MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 3 14 0 3 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 | | | 0MiB / 8191MiB | | | +------------------+----------------------------------+-----------+-----------------------+ +-----------------------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=========================================================================================| **| 0 2 0 64080 C python 312MiB | | 1 13 0 64085 C python 118MiB | | 2 5 0 64073 C python 210MiB |** +-----------------------------------------------------------------------------------------+

使用 GB200 P6e 執行個體透過 IMEX 最佳化 GPU 工作負載

IMEX (Internode Memory Exchange) 可讓跨節點的記憶體一致性通訊,以便在 NVIDIA GB200 UltraClusters 上進行分散式訓練。

執行下列步驟。

  1. 使用名為 的檔案為ComputeDomain多節點訓練定義 imex-compute-domain.yaml

    apiVersion: resource.nvidia.com/v1beta1 kind: ComputeDomain metadata: name: distributed-training-domain namespace: default spec: numNodes: 2 channel: resourceClaimTemplate: name: imex-channel-template
  2. 使用 IMEX 頻道搭配名為 的檔案來定義 Podimex-pod.yaml

    apiVersion: v1 kind: Pod metadata: name: imex-distributed-training namespace: default labels: app: imex-training spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: nvidia.com/gpu.clique operator: Exists containers: - name: distributed-training image: nvcr.io/nvidia/pytorch:25.04-py3 command: ["bash", "-c"] args: - | echo "=== IMEX Channel Verification ===" ls -la /dev/nvidia-caps-imex-channels/ echo "" echo "=== GPU Information ===" nvidia-smi echo "" echo "=== NCCL Test (if available) ===" python -c " import torch import torch.distributed as dist import os print(f'CUDA available: {torch.cuda.is_available()}') print(f'CUDA device count: {torch.cuda.device_count()}') if torch.cuda.is_available(): for i in range(torch.cuda.device_count()): print(f'GPU {i}: {torch.cuda.get_device_name(i)}') # Check for IMEX environment variables imex_vars = [k for k in os.environ.keys() if 'IMEX' in k or 'NVLINK' in k] if imex_vars: print('IMEX Environment Variables:') for var in imex_vars: print(f' {var}={os.environ[var]}') print('IMEX channel verification completed') " # Keep container running for inspection sleep 3600 resources: claims: - name: imex-channel-0 - name: imex-channel-1 resourceClaims: - name: imex-channel-0 resourceClaimTemplateName: imex-channel-template - name: imex-channel-1 resourceClaimTemplateName: imex-channel-template tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule
    注意

    這需要 P6e GB200 執行個體。

  3. 透過套用 ComputeDomain和 範本來部署 IMEX:

    kubectl apply -f imex-claim-template.yaml kubectl apply -f imex-compute-domain.yaml kubectl apply -f imex-pod.yaml
  4. 檢查ComputeDomain狀態。

    kubectl get computedomain distributed-training-domain
  5. 監控 IMEX 協助程式部署。

    kubectl get pods -n nvidia-dra-driver -l [resource.nvidia.com/computeDomain](http://resource.nvidia.com/computeDomain)
  6. 檢查 Pod 中的 IMEX 頻道:

    kubectl exec imex-distributed-training -- ls -la /dev/nvidia-caps-imex-channels/
  7. 檢視 Pod 日誌:

    kubectl logs imex-distributed-training

    以下是預期輸出的範例:

    === IMEX Channel Verification === total 0 drwxr-xr-x. 2 root root 80 Jul 8 10:45 . drwxr-xr-x. 6 root root 380 Jul 8 10:45 .. crw-rw-rw-. 1 root root 241, 0 Jul 8 10:45 channel0 crw-rw-rw-. 1 root root 241, 1 Jul 8 10:45 channel1

如需詳細資訊,請參閱 GitHub 上的 NVIDIA 範例