コンピューティングと自動スケーリング - Amazon EKS

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

コンピューティングと自動スケーリング

GPU リソースの最適化とコスト管理

Well-Known ラベルを使用して GPU 要件でワークロードをスケジュールする

さまざまな GPU 特性 (GPU、GPU メモリなど) に敏感な AI/ML ワークロードでは、Karpenter およびマネージド型ノードグループで使用されるノードタイプでサポートされている既知のスケジューリングラベルを使用して GPU 要件を指定することをお勧めします。これらを定義しないと、GPU リソースが不十分なインスタンスでポッドがスケジュールされ、障害やパフォーマンスの低下が発生する可能性があります。nodeSelector または Node アフィニティを使用して、ポッドを実行するノードを指定し、ポッドのリソースセクションでコンピューティングリソース (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 Device Plugin を使用して GPUs

GPUs をノードに公開するには、NVIDIA GPU ドライバーをノードのオペレーティングシステムとコンテナランタイムにインストールし、Kubernetes スケジューラが使用可能な GPUs を持つノードにポッドを割り当てることができるように設定する必要があります。NVIDIA Kubernetes Device Plugin のセットアッププロセスは、使用している EKS Accelerated AMI によって異なります。

  • Bottlerocket Accelerated AMI: この AMI には NVIDIA GPU ドライバーが含まれており、NVIDIA Kubernetes Device Plugin がプリインストールされ、すぐに使用できるため、GPU サポートがすぐに利用できます。GPUs を Kubernetes スケジューラに公開するために、追加の設定は必要ありません。

  • AL2023 Accelerated AMI: この AMI には NVIDIA GPU ドライバーが含まれていますが、NVIDIA Kubernetes Device Plugin はプリインストールされていません。デバイスプラグインは、通常は DaemonSet を介して個別にインストールおよび設定する必要があります。eksctl を使用してクラスターを作成し、ClusterConfig で GPU インスタンスタイプ ( などg5.xlarge) を指定すると、 eksctl は自動的に適切な AMI を選択し、NVIDIA Kubernetes Device Plugin をインストールします。詳細については、eksctl ドキュメントの「GPU サポート」を参照してください。

代わりに EKS Accelerated AMIs と NVIDIA GPU 演算子を使用して NVIDIA Kubernetes デバイスプラグインなどのコンポーネントを管理する場合は、NVIDIA GPU ドライバーと NVIDIA Container ツールキットの管理を、インストール済みの NVIDIA GPU ドライバーと NVIDIA Container Toolkit NVIDIA ドキュメントに従って無効にしてください。

NVIDIA Device Plugin がアクティブで GPUsが正しく公開されていることを確認するには、以下を実行します。

kubectl describe node | grep nvidia.com/gpu

このコマンドは、nvidia.com/gpuリソースがノードの容量と割り当て可能なリソースにあるかどうかを確認します。たとえば、1 つの GPU を持つノードには が表示されますnvidia.com/gpu: 1。詳細については、Kubernetes GPU スケジューリングガイドを参照してください。

さまざまな EC2 インスタンスタイプを使用する

Kubernetes データプレーン 「」セクションで説明されているように、Amazon EKS でのスケーラビリティに関する重要なベストプラクティスは、できるだけ多くの異なる EC2 インスタンスタイプを使用することです。この推奨事項は、高速ハードウェア (GPUs など) を使用するインスタンスにも適用されます。1 つのインスタンスタイプのみを使用するクラスターを作成し、リージョンの容量を超えてノード数をスケーリングしようとすると、使用可能なインスタンスがないことを示す容量不足エラー (ICE) が表示されることがあります。任意に分散する前に、AI/ML ワークロードの固有の特性を理解することが重要です。EC2 Instance Type Explorer ツールを使用して使用可能なインスタンスタイプを確認し、特定のコンピューティング要件に一致するインスタンスタイプのリストを生成し、クラスターで使用できるインスタンスのタイプを任意に制限しないようにします。

高速コンピューティングインスタンスは、短期、中期、定常状態のワークロードに合わせて、さまざまな購入モデルで提供されています。予約を避けたい短期的で柔軟で耐障害性のあるワークロードについては、スポットインスタンスをご覧ください。キャパシティブロック、オンデマンドインスタンス、Saving Plans を使用すると、中長期のワークロード期間にわたって高速コンピューティングインスタンスをプロビジョニングできます。任意の購入オプションで必要な容量に正常にアクセスする可能性を高めるために、インスタンスタイプとアベイラビリティーゾーンのさまざまなリストを使用することをお勧めします。または、特定の購入モデルの ICEs が発生した場合は、別のモデルを使用して再試行します。

次の例は、Karpenter NodePool が世代 3 より大きい G および P インスタンス (p3 など) をプロビジョニングできるようにする方法を示しています。詳細については、「EKS スケーラビリティのベストプラクティス」のセクションを参照してください。

- key: karpenter.k8s.aws/instance-category operator: In values: ["g", "p"] # Diversifies across G-series and P-series - key: karpenter.k8s.aws/instance-generation operator: Gt values: ["3"] # Selects instance generations greater than 3

GPUs、以下のAmazon EC2 スポットインスタンスを Karpenter で GPUs」を参照してください。

Karpenter で GPUs に Amazon EC2 スポットインスタンスを使用することを検討する

Amazon EC2 スポットインスタンスを使用すると、AWS クラウド内の未使用の EC2 容量を利用でき、オンデマンド料金と比較して最大 90% の割引で利用できます。Amazon EC2 スポットインスタンスは、EC2 が容量を戻す必要がある場合、2 分間の通知で中断できます。詳細については、Amazon EC2 ユーザーガイド」の「スポットインスタンス」を参照してください。Amazon EC2 スポットは、耐障害性、ステートレス、柔軟性 (時間およびインスタンスタイプ) の高いワークロードに最適です。スポットインスタンスを使用するタイミングの詳細については、EC2 スポットインスタンスのベストプラクティス」を参照してください。スポットフレンドリであれば、AI/ML ワークロードにスポットインスタンスを使用することもできます。

ユースケース

スポットフレンドリーなワークロードには、ビッグデータ、コンテナ化されたワークロード、CI/CD、ステートレスウェブサーバー、ハイパフォーマンスコンピューティング (HPC)、レンダリングワークロードなどがあります。スポットインスタンスは、柔軟性がない、ステートフル、耐障害性がある、またはインスタンスノード間で緊密に結合されているワークロードには適していません (例えば、計算のために相互に大きく依存する並列プロセスを持つワークロードで、計算流体力学や複雑な相互依存関係を持つ分散データベースなどの MPI ベースの高性能コンピューティングアプリケーションなど、一定のノード間通信が必要です)。推奨される特定のユースケースを以下に示します (特定の順序はありません)。

  • リアルタイムオンライン推論: スポットインスタンスを使用して、ワークロードがスポットフレンドリである限り、リアルタイム推論ワークロードのコスト最適化スケーリングを行います。つまり、推論時間は 2 分未満で、アプリケーションは中断に対して耐障害性があり、さまざまなインスタンスタイプで実行できます。潜在的なスポット中断を処理するアプリケーションレベルの耐障害性を実装しながら、インスタンスの多様性 (複数のインスタンスタイプやアベイラビリティーゾーンなど) や予約を通じて高可用性を確保します。

  • ハイパーパラメータ調整: スポットインスタンスを使用して、特に短時間の実験では、中断が大きな損失なしで許容されるため、探索的な調整ジョブを日和見的に実行します。

  • データ拡張: スポットインスタンスを使用して、中断された場合にチェックポイントから再起動できるデータ前処理および拡張タスクを実行するため、スポットの可変可用性に最適です。

  • ファインチューニングモデル: スポットインスタンスを使用して、堅牢なチェックポイントメカニズムでファインチューニングを行い、最後に保存された状態から再開して、インスタンスの中断の影響を最小限に抑えます。

  • バッチ推論: スポットインスタンスを使用して、オフライン推論リクエストの大量のバッチをnon-real-time方法で処理します。ジョブを一時停止および再開でき、スポットのコスト削減と最適な連携を提供し、再試行や分散による潜在的な中断を処理します。

  • オポチュニスティックトレーニングサブセット: わずかなトレーニングワークロードや実験的なトレーニングワークロード (1,000 万パラメータ未満の小規模なモデルなど) にはスポットインスタンスを使用します。この場合、中断は許容され、インスタンスタイプやリージョン間の分散などの効率の最適化を適用できますが、中断の可能性があるため、本番規模のトレーニングにはお勧めしません。

考慮事項

Amazon EKS の高速ワークロードにスポットインスタンスを使用するには、いくつかの重要な考慮事項があります (特定の順序はありません)。

  • Karpenter を使用して、高度な統合を有効にしたスポットインスタンスを管理します。Karpenter NodePool で karpenter.sh/capacity-type を「スポット」として指定することで、Karpenter は追加の設定なしでデフォルトでスポットインスタンスをプロビジョニングします。ただし、使用率の低いスポットノードを低価格のスポット代替に置き換える高度なSpot-to-Spot統合を有効にするには、Karpenter コントローラー引数で --feature-gates SpotToSpotConsolidation=true を設定するか、FEATURE_GATES 環境変数を使用して SpotToSpotConsolidation 機能ゲートを有効にする必要があります。Karpenter は、price-capacity-optimized配分戦略を使用して EC2 インスタンスをプロビジョニングします。NodePool の要件とポッドの制約に基づいて、Karpenter はスケジュール不可能なポッドをパッケージ化し、さまざまなインスタンスタイプのセットを Amazon EC2 フリート API に送信します。EC2 Instance Type Explorer ツールを使用して、特定のコンピューティング要件に一致するインスタンスタイプのリストを生成できます。

  • ワークロードがステートレスで耐障害性があり、柔軟性があることを確認します。ワークロードは、ステートレスで耐障害性があり、インスタンス/GPU サイズに関して柔軟である必要があります。これにより、スポットの中断後にシームレスに再開でき、インスタンスの柔軟性により、スポットに長時間とどまる可能性があります。Karpenter でスポット中断処理を有効にするには、AWS SQS キューの名前を使用して settings.interruptionQueue Helm 値を設定し、スポット中断イベントをキャッチします。例えば、Helm 経由でインストールする場合は、--set "settings.interruptionQueue=${CLUSTER_NAME}" を使用します。例については、「Karpenter 入門ガイド」を参照してください。Karpenter は、スポット中断イベントに気付くと、中断イベントの前にノードを自動的にコーディング、テイント、ドレイン、終了 (複数可) して、ポッドの終了猶予期間を最大化します。同時に、Karpenter はすぐに新しいノードを起動し、できるだけ早く準備できるようにします。

  • インスタンスタイプの選択を過度に制限しないようにします。インスタンスタイプをできるだけ制限しないでください。インスタンスタイプを制限しないと、スポットインスタンスの中断頻度が低く、低コストで大規模なスポット容量を取得する可能性が高くなります。例えば、特定のタイプ (g5.xlarge など) に制限することは避けてください。karpenter.k8s.aws/instance-category や karpenter.k8s.aws/instance-generation などのキーを使用して、さまざまなインスタンスカテゴリと世代のセットを指定することを検討してください。Karpenter を使用すると、複数のインスタンスタイプとアベイラビリティーゾーン (AZs) 間でオンデマンドインスタンス容量とスポットインスタンス容量を簡単に分散できます。さらに、AI/ML ワークロードが特定のアクセラレーターまたは限られたアクセラレーターを必要とするが、リージョン間で柔軟性がある場合は、スポットプレイスメントスコアを使用して、起動前にワークロードをデプロイする最適なリージョンを動的に特定できます。

  • NodePool の要件を拡張して、同様の EC2 インスタンスファミリーの数を増やします。すべてのスポットインスタンスプールは、特定のアベイラビリティーゾーン (AZ) 内の特定のインスタンスタイプの未使用の EC2 インスタンス容量で構成されます。Karpenter が新しいノードのプロビジョニングを試みると、NodePool の要件に一致するインスタンスタイプが選択されます。互換性のあるインスタンスタイプに AZ のスポット容量がない場合、プロビジョニングは失敗します。この問題を回避するには、GPU メモリやレイトレーシングなどのハードウェアのニーズを考慮しながら、サイズとアベイラビリティーゾーン (AZs) 間で NVIDIA のより広範な g シリーズインスタンス (世代 4 以降) を許可します。インスタンスのタイプは異なる可能性があるため、ワークロードが各タイプで実行でき、得られるパフォーマンスがニーズを満たすことを確認する必要があります。

  • リージョン内のすべてのアベイラビリティーゾーンを活用します。使用可能な容量はアベイラビリティーゾーン (AZ) によって異なります。特定のインスタンスタイプは、ある AZ では使用できないものの、別の AZ では豊富である可能性があります。インスタンスタイプとアベイラビリティーゾーンの一意の組み合わせはそれぞれ、個別のスポットキャパシティープールを構成します。Karpenter NodePool 要件内のリージョン内のすべての AZs で容量をリクエストすることで、より多くのプールを一度に効果的に検索できます。これにより、スポットキャパシティープールの数を最大化できるため、スポットキャパシティーを取得する可能性が高くなります。これを実現するには、NodePool 設定で、topology.kubernetes.io/zone キーを完全に省略して、Karpenter がリージョンで使用可能なすべての AZs から選択できるようにするか、 演算子を使用して AZs を明示的に一覧表示します。 で値を指定します (us-west-2a など)。

  • スポットプレイスメントスコア (SPS) を使用して、スポットインスタンスを使用して必要な容量に正常にアクセスする可能性を可視化することを検討してください。スポットプレイスメントスコア (SPS) は、スポットリクエストが成功する可能性を評価するのに役立つスコアを提供するツールです。SPS を使用する場合は、まずスポットインスタンスのコンピューティング要件を指定し、Amazon EC2 はスポットリクエストが成功する可能性が高い上位 10 のリージョンまたはアベイラビリティーゾーン (AZs) を返します。リージョンとアベイラビリティーゾーンは1 ~ 10 のスケールで採点されます。スコアが 10 の場合、スポットリクエストは成功する可能性は高くなりますが、成功が保証されるわけではありません。スコア 1 はスポットリクエストがまったく成功する可能性がないことを示します。異なるリージョンまたはアベイラビリティーゾーンで同じスコアが返される場合があります。詳細については、「AWS でスポットプレイスメントスコアトラッカーダッシュボードを構築するためのガイダンス」を参照してください。スポット容量は常に変動するため、SPS は、ワークロードの制約 (柔軟性、パフォーマンス、サイズなど) に最適なインスタンスタイプ、AZs、リージョンの組み合わせを特定するのに役立ちます。AI/ML ワークロードが特定のアクセラレーターまたは限られたアクセラレーターを必要とするが、リージョン間で柔軟性がある場合は、スポットプレイスメントスコアを使用して、起動前にワークロードをデプロイする最適なリージョンを動的に特定できます。スポット容量を取得する可能性を自動的に確認できるように、SPS トラッカーダッシュボードを構築するためのガイダンスを提供します。このソリューションは、さまざまなセットアップ (GPUs) の YAML 設定を使用して SPS スコアを経時的にモニタリングし、CloudWatch にメトリクスを保存し、設定を比較するためのダッシュボードを提供します。ワークロードごとにダッシュボードを定義して vCPU、メモリ、GPU のニーズを評価し、他の AWS リージョンの使用を検討するなど、EKS クラスターの最適なセットアップを確保します。詳細については、「スポットプレイスメントスコアの仕組み」を参照してください。

  • スポットの中断とテストを適切に処理します。終了期間が 2 分を超えるポッドの場合、古いノードはそれらのポッドが再スケジュールされる前に中断され、ワークロードの可用性に影響する可能性があります。アプリケーションを設計するときは、2 分間のスポット中断通知を検討してください。 長時間実行されるアプリケーション (例: Amazon S3) などの永続的ストレージに進行状況を保存して、中断後に再開します。 Pod 仕様で terminationGracePeriodSeconds (デフォルトは 30 秒) を拡張して、正常なシャットダウンにより多くの時間を確保します。 および preStop、クリーンアップ、 状態の保存、 および 接続クロージャ。スケーリング時間が重要で、アプリケーションのトラフィック処理に 2 分以上かかるリアルタイムワークロードの場合は、 と アプリケーションのスケーリングとパフォーマンスのベストプラクティスを確認して、コンテナの起動時間と ML モデルのロード時間を最適化することを検討[Storage (ストレージ)]してください。代替ノードをテストするには、AWS Fault Injection Service (FIS) を使用してスポットの中断をシミュレートします。

これらのコアスポットのベストプラクティスに加えて、Amazon EKS で GPU ワークロードを管理する際には、これらの要素を考慮してください。CPU ベースのワークロードとは異なり、GPU ワークロードは GPU 機能や使用可能な GPU メモリなどのハードウェアの詳細に特に敏感です。GPU ワークロードは、使用できるインスタンスタイプによって制約される場合があり、CPUs。最初のステップとして、ワークロードがインスタンスに柔軟性があるかどうかを評価します。ワークロードで使用できるインスタンスタイプがわからない場合は、個別にテストして互換性と機能を確認します。分散によってワークロードが動作し続け、パフォーマンスへの影響 (スループットや完了時間など) を把握しながら、可能な限り分散できる柔軟性を特定します。ワークロードの多様化の一環として、次の点を考慮してください。

  • CUDA とフレームワークの互換性を確認します。GPU ワークロードは、特定のハードウェア、GPU タイプ (p3 の V100 と p4 の A100 など)、または TensorFlow などのライブラリの特定の CUDA バージョン用に記述される場合があるため、ワークロードの互換性を確認してください。この互換性は、ランタイムエラー、クラッシュ、GPU アクセラレーションの障害 (PyTorch や TensorFlow などのフレームワークとの CUDA バージョンの不一致により実行が妨げられる可能性があるなど) や、FP16/INT8 精度などのハードウェア機能を活用する機能を防止するために不可欠です。

  • GPU メモリDCGM Exporter などのツールを使用して、モデルのメモリ要件を評価し、ランタイム中にモデルのメモリ使用量をプロファイリングし、インスタンスタイプに必要な最小 GPU メモリを karpenter.k8s.aws/instance-gpu-memory などの既知のラベルに設定します。GPU VRAM はインスタンスタイプ (NVIDIA T4 が 16GB, A10G が 24GB, V100 が 16-32GB など) によって異なり、ML モデル (大規模言語モデルなど) が使用可能なメモリを超え、out-of-memory (OOM) エラーやクラッシュが発生する可能性があります。EKS のスポットインスタンスでは、分散が制限される場合があります。例えば、モデルが適合しない場合、低 VRAM タイプを含めることはできません。これにより、キャパシティプールへのアクセスが制限され、中断リスクが増加する可能性があります。単一 GPU の場合、単一ノード推論 (GPU リソースを利用するために同じノードで複数のポッドがスケジュールされているなど) では、スポット設定に十分な VRAM を持つインスタンスタイプのみを含めることができるため、分散が制限される場合があります。

  • 浮動小数点の精度とパフォーマンス。すべての Nvidia GPU アーキテクチャが同じ浮動小数点精度 (FP16/INT8 など) を持つわけではありません。ワークロードに必要なコアタイプ (CUDA/Tensor/RT) のパフォーマンスと浮動小数点精度を評価します。低価格でパフォーマンスの低い GPU で実行しても、パフォーマンスは向上しないため、分散の影響を理解するために、特定の期間内に完了した作業の観点からパフォーマンスを評価することを検討してください。

シナリオ: リアルタイム推論ワークロードの分散

スポットインスタンスのリアルタイムのオンライン推論ワークロードの場合、互換性のある GPU インスタンスファミリーと世代を分散するように Karpenter NodePool を設定できます。このアプローチにより、GPU の機能、メモリ、アーキテクチャに対する制約を通じてパフォーマンスを維持しながら、複数のスポットプールから高可用性を確保できます。インスタンス容量が制限されている場合の代替手段の使用をサポートし、中断を最小限に抑え、推論レイテンシーを最適化します。この NodePool 状態の例では、GPU メモリが 20GB を超える 3 を超える g および p シリーズインスタンスを使用します。

apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: gpu-inference-spot spec: template: metadata: labels: role: gpu-spot-worker spec: requirements: - key: karpenter.sh/capacity-type operator: In values: ["spot"] # Use Spot Instances - key: karpenter.k8s.aws/instance-category operator: In values: ["g", "p"] # Diversifies across G-series and P-series - key: karpenter.k8s.aws/instance-generation operator: Gt values: ["3"] # Selects instance generations greater than 3 - key: kubernetes.io/arch operator: In values: ["amd64"] # Specifies AMD64 architecture, compatible with NVIDIA GPUs - key: karpenter.k8s.aws/instance-gpu-memory operator: Gt values: ["20480"] # Ensures more than 20GB (20480 MiB) total GPU memory taints: - key: nvidia.com/gpu effect: NoSchedule nodeClassRef: name: gpu-inference-ec2 group: karpenter.k8s.aws kind: EC2NodeClass expireAfter: 720h limits: cpu: 100 memory: 100Gi disruption: consolidationPolicy: WhenEmptyOrUnderutilized consolidateAfter: 5m # Enables consolidation of underutilized nodes after 5 minutes

長時間実行されるトレーニングジョブのチェックポイントを実装する

チェックポイントは、プロセスの状態を定期的に保存し、中断した場合に最後に保存したポイントから再開できるようにする耐障害性手法です。機械学習では、一般的にトレーニングに関連付けられており、長時間実行されるジョブによってモデルの重みとオプティマイザの状態が節約され、ハードウェアの問題やスポットインスタンスの中断などの障害後にトレーニングを再開できます。

チェックポイントを使用して、トレーニング中に機械学習 (ML) モデルの状態を保存します。チェックポイントはモデルのスナップショットであり、機械学習フレームワークのコールバック関数を使用して設定できます。保存されたチェックポイントを使用して、トレーニングジョブを最後に保存したチェックポイントから再開できます。チェックポイントを使用すると、トレーニングジョブまたはインスタンスの予期しない中断により、モデルスナップショットをトレーニング中に保存します。これにより、チェックポイントから将来モデルのトレーニングを再開できます。ノードレジリエンシーシステムの実装に加えて、チェックポイントを実装して、ハードウェア障害や Amazon EC2 スポットインスタンスの中断などによる中断の影響を軽減することをお勧めします。

チェックポイントがないと、中断により計算時間が無駄になり、進行状況が失われる可能性があり、長時間実行されるトレーニングジョブにはコストがかかります。チェックポイントを使用すると、ジョブは定期的に状態 (モデルの重みやオプティマイザの状態など) を保存し、中断後に最後のチェックポイント (最後に処理されたバッチ) から再開できます。チェックポイントを実装するには、大量のバッチでデータを処理し、トレーニングジョブの進行中に Mountpoint for Amazon S3 CSI ドライバーを介して Amazon S3 バケットなどの中間結果を永続的ストレージに保存するようにアプリケーションを設計します。 Amazon S3

ユースケース

チェックポイントは、耐障害性とパフォーマンスのオーバーヘッドのバランスをとるために、特定のシナリオで特に有益です。次の場合はチェックポイントの使用を検討してください。

  • ジョブ時間が数時間を超える: 長時間実行されるトレーニングジョブの場合 (小規模モデルの場合は >1~2 時間、数十億のパラメータを持つ大規模基盤モデルの場合は日/週など)、中断による進行状況の損失にはコストがかかります。ジョブを短くすると、I/O オーバーヘッドが正当化されない場合があります。

  • スポットインスタンスまたはハードウェア障害の場合: EC2 スポット (2 分前の通知) やハードウェア障害 (GPU メモリエラーなど) などの中断が発生しやすい環境では、チェックポイントにより迅速な再開が可能になり、耐障害性のあるワークロードでスポットを有効にしてコストを削減できます。

  • 大規模な分散トレーニング: 数百/数千のアクセラレーター (>100 GPUs) のセットアップの場合、障害間の平均時間はスケールに応じて直線的に減少します。モデル/データ並列処理に を使用してチェックポイントへの同時アクセスを処理し、完全な再起動を回避します。

  • リソース需要の高い大規模モデル: クラスターサイズが原因で障害が避けられないペタバイト規模の LLM トレーニングでは、階層型アプローチ (一時的な場合は 5~30 分ごとに高速ローカル、重大な障害の場合は 1 時間ごとに耐久性) により、復旧時間と効率が最適化されます。

P インスタンスと Trainium インスタンスの容量保証に ML キャパシティブロックを使用する

ML のキャパシティブロックを使用すると、需要の高い GPU インスタンス、特に P インスタンス (p6-b200、p5、p5e、p5en、p4d、p4de など) と Trainium インスタンス (trn1、trn2 など) を予約して、短期間の機械学習 (ML) ワークロードをサポートするためにほぼ即時または将来の日付に開始できます。これらの予約は、モデルトレーニングやファインチューニングなどの計算負荷の高いタスクの容量を確保するのに最適です。EC2 キャパシティブロックの料金は、予約料金とオペレーティングシステム料金で構成されます。料金の詳細については、「ML 料金の EC2 キャパシティブロック」を参照してください。

予測可能なキャパシティ保証のために Amazon EKS の AI/ML ワークロード用の GPUs を予約するには、短期またはオンデマンドキャパシティ予約 (ODCR) に ML キャパシティブロックを活用して汎用キャパシティ保証を行うことをお勧めします。 ODCRs

  • ODCRsを使用すると、特定のアベイラビリティーゾーンの EC2 インスタンス容量 (g5 や p5 などの GPU インスタンスなど) を一定期間予約できるため、需要が高い場合でも可用性を確保できます。ODCRsには長期的なコミットメントはありませんが、使用の有無にかかわらず、リザーブドキャパシティのオンデマンド料金を支払います。EKS では、ODCRs は Karpenterマネージド型ノードグループなどのノードタイプでサポートされています。Karpenter で ODCRs に優先順位を付けるには、 capacityReservationSelectorTermsフィールドを使用するように NodeClass を設定します。Karpenter NodePools ドキュメントを参照してください。

  • キャパシティブロックは、GPU (p5、p4d など) または Trainium (trn1、trn2) インスタンス専用の予約メカニズムであり、モデルトレーニング、ファインチューニング、実験などの短期 ML ワークロード向けに設計されています。将来の日付から始まる定義された期間 (通常は 24 時間~182 日) のキャパシティーを予約し、予約時間に対してのみ支払います。これらは前払いであり、容量のニーズに応じて事前に計画する必要があり、自動スケーリングをサポートしていませんが、低レイテンシーのネットワーキングのために EC2 UltraClusters にコロケーションされています。予約期間に対してのみ課金されます。詳細については、「キャパシティブロックの検索と購入」を参照するか、「Create a managed node group with Capacity Blocks for ML」の手順を使用してキャパシティブロックでマネージド型ノードグループを設定して開始してください。

AWS マネジメントコンソールを使用してキャパシティを予約し、ML キャパシティブロックを使用するようにノードを設定します。ワークロードスケジュールに基づいて予約を計画し、ステージングクラスターでテストします。詳細については、キャパシティブロックのドキュメントを参照してください。

G Amazon EC2 インスタンスのオンデマンド、Amazon EC2 スポット、またはオンデマンドキャパシティ予約 (ODCRs) を検討する

G Amazon EC2 インスタンスでは、オンデマンド、Amazon EC2 スポットインスタンス、オンデマンドキャパシティ予約とは異なる購入オプションを検討してください。ODCRsを使用すると、特定のアベイラビリティーゾーンの EC2 インスタンス容量を一定期間予約できるため、需要が高い場合でも可用性を確保できます。P インスタンスと Trainium インスタンスでのみ使用できる ML キャパシティブロックとは異なり、ODCRs は G インスタンスを含む幅広いインスタンスタイプに使用できるため、推論やグラフィックスなど、さまざまな GPU 機能を必要とするワークロードに適しています。Amazon EC2 スポットインスタンスを使用する場合、さまざまなインスタンスタイプ、サイズ、アベイラビリティーゾーンに分散できることが、スポットに長く留まるための鍵となります。

ODCRsには長期的なコミットメントはありませんが、使用の有無にかかわらず、リザーブドキャパシティのオンデマンド料金を支払います。ODCRs はすぐに使用できるように作成することも、将来の日付にスケジュールすることもできます。これにより、キャパシティプランニングを柔軟に行うことができます。Amazon EKS ODCRs は Karpenterマネージド型ノードグループなどのノードタイプでサポートされています。Karpenter で ODCRs に優先順位を付けるには、 capacityReservationSelectorTermsフィールドを使用するように NodeClass を設定します。Karpenter NodePools ドキュメントを参照してください。CLI コマンドを含む ODCRs「オンデマンドキャパシティ予約の開始方法」を参照してください。

他の高速インスタンスタイプとサイズを検討する

Amazon EKS の ML ワークロードのパフォーマンスとコストの両方を最適化するには、適切な高速インスタンスとサイズを選択することが不可欠です。例えば、異なる GPU インスタンスファミリーには、GPU メモリなどの異なるパフォーマンスと機能があります。最も価格パフォーマンスの高いオプションを選択するには、高速コンピューティングEC2 インスタンスタイプページで使用可能な GPU インスタンスを確認してください。複数のインスタンスタイプとサイズを評価して、特定のワークロード要件に最適なものを見つけます。GPUs の数、メモリ、ネットワークパフォーマンスなどの要因を考慮してください。適切な GPU インスタンスタイプとサイズを慎重に選択することで、EKS クラスターのリソース使用率とコスト効率を向上させることができます。

EKS ノードで GPU インスタンスを使用する場合、デフォルトでkube-systemは名前空間にnvidia-device-plugin-daemonsetポッドがあります。インスタンスで 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 共有は、さまざまなオプションを通じて実現できます。

  • ノードセレクタ/ノードアフィニティを活用してスケジューリングに影響を与える: プロビジョニングされたノードとポッドがワークロードに適した GPUs でスケジュールされていることを確認します (例: karpenter.k8s.aws/instance-gpu-name: "a100")

  • タイムスライス: GPU のコンピューティングリソースを経時的に共有するようにワークロードをスケジュールし、物理パーティショニングなしで同時実行できるようにします。これは、コンピューティング要求が変化するワークロードに最適ですが、メモリの分離がない可能性があります。

  • マルチインスタンス GPU (MIG): MIG では、1 つの NVIDIA GPU を複数の独立したインスタンスに分割でき、NVIDIA Ampere (A100 GPU など)、NVIDIA Hopper (H100 GPU など)、NVIDIA Blackwell (Blackwell GPUs など) GPUs。各 MIG インスタンスは専用のコンピューティングリソースとメモリリソースを受け取るため、マルチテナント環境やリソースの保証を必要とするワークロードでリソースを共有できます。これにより、タイムスライスによってバッチサイズが異なる複数のモデルを提供するシナリオなど、GPU リソースの使用率を最適化できます。

  • 小数 GPU 割り当て: ソフトウェアベースのスケジューリングを使用して GPU のコンピューティングまたはメモリの一部をワークロードに割り当て、動的ワークロードに柔軟性を提供します。Run:ai プラットフォームの一部である NVIDIA KAI スケジューラは、ポッドが小数 GPU リソースをリクエストできるようにすることでこれを可能にします。

EKS でこれらの機能を有効にするには、GPUs をスケジュール可能なリソースとして公開し、タイムスライスと MIG をサポートする NVIDIA Device Plugin をデプロイできます。詳細については、「Kubernetes のタイムスライス GPUs」と「NVIDIA タイムスライスおよび高速 EC2 インスタンスを使用した Amazon EKS での GPU 共有」を参照してください。

たとえば、NVIDIA Device Plugin でタイムスライスを有効にするには:

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 と一緒にデプロイし、ポッド仕様で小数 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

ノードの耐障害性とトレーニングジョブの管理

自動復旧によるノードヘルスチェックの実装

複数のノードにまたがるマルチ GPU モデルトレーニングなど、ノード間の頻繁な通信を必要とする Amazon EKS の分散トレーニングジョブでは、GPU や EFA の障害などのハードウェアの問題により、トレーニングジョブが中断される可能性があります。これらの中断により、特に安定したハードウェアに依存する長時間実行される AI/ML ワークロードでは、トレーニングの進行状況が失われ、コストが増加する可能性があります。

GPU ワークロードを実行している EKS クラスターの GPU 障害など、ハードウェア障害に対する回復力を高めるために、EKS Node Monitoring Agent with Auto Repair または Amazon SageMaker HyperPod のいずれかを利用することをお勧めします。自動修復を備えた EKS Node Monitoring Agent は、ノードのヘルスモニタリングや標準の Kubernetes メカニズムを使用した自動修復などの機能を提供しますが、SageMaker HyperPod は、ディープヘルスチェックや自動ジョブ再開など、大規模な ML トレーニング用に特別に設計された、ターゲットを絞った回復力と追加機能を提供します。

  • Node Auto Repair を備えた EKS Node Monitoring Agent は、ログを読み取って NodeConditions を適用することでノードの状態を継続的にモニタリングします。これには、高速ハードウェアに固有の標準条件Readyや、GPU やネットワーク障害などの問題を特定するための条件が含まれます。ノードが異常であると判断された場合、ノードの自動修復はノードを遮断し、新しいノードに置き換えます。ポッドの再スケジュールとジョブの再起動は、標準の Kubernetes メカニズムとジョブの再起動ポリシーに依存します。

  • SageMaker HyperPod のディープヘルスチェックとヘルスモニタリングエージェントは、GPU および Trainium ベースのインスタンスのヘルスステータスを継続的にモニタリングします。これは AI/ML ワークロードに合わせて調整され、ラベル (node-health-status など) を使用してノードの状態を管理します。ノードが異常と見なされると、HyperPod は GPUs。デフォルトでは、基本的なヘルスチェックを通じて EFA のネットワーク関連の障害を検出し、中断されたトレーニングジョブの自動再開をサポートしているため、最後のチェックポイントからジョブを続行できるため、大規模な ML タスクの中断を最小限に抑えることができます。

EFA を使用して Auto Repair を使用する EKS Node Monitoring Agent と SageMaker HyperPod クラスターの両方について、リモートダイレクトメモリアクセス (RDMA) エラーやパケットドロップなどの EFA 固有のメトリクスをモニタリングするには、AWS EFA ドライバーがインストールされていることを確認してください。さらに、CloudWatch Observability アドオンをデプロイするか、Prometheus と Grafana を備えた DCGM Exporter などのツールを使用して EFA、GPU、SageMaker HyperPod の機能に関連する特定のメトリクスをモニタリングすることをお勧めします。

中断の影響を受けやすいワークロードの Karpenter 統合を無効にする

処理、大規模な AI/ML 予測タスク、トレーニングなどの中断の影響を受けやすいワークロードの場合は、ジョブ実行中の中断を防ぐために Karpenter 統合ポリシーを調整することをお勧めします。Karpenter の統合機能は、使用率の低いノードを終了するか、低価格の代替ノードに置き換えることで、クラスターコストを自動的に最適化します。ただし、ワークロードが GPU をフル活用している場合でも、Karpenter はポッドの要件を満たす低価格の適正サイズのインスタンスタイプを識別し、ジョブの中断につながる場合、ノードを統合することがあります。

WhenEmptyOrUnderutilized 統合ポリシーはノードを早期に終了し、実行時間が長くなる可能性があります。たとえば、ポッドの再スケジュール、データの再ロードが原因でジョブの再開が中断されると、長時間実行されるバッチ推論ジョブにはコストがかかる可能性があります。これを軽減するには、 consolidationPolicyを に設定WhenEmptyし、ワークロードの急増時にノードを保持するように 1 時間などのconsolidateAfter期間を設定できます。例:

disruption: consolidationPolicy: WhenEmpty consolidateAfter: 60m

このアプローチにより、リアルタイムのオンライン推論データ処理やモデルトレーニングなど、急増するバッチ推論ワークロードやその他の中断の影響を受けやすいジョブのポッド起動レイテンシーが改善され、中断のコストがコンピューティングコスト削減を上回るようになります。Karpenter NodePool Disruption Budgets は、Karpenter の中断を管理するためのもう 1 つの機能です。予算を使用すると、特定の時点で選択した NodePool で中断されるノード数が一定以下になるようにできます。また、中断予算を使用して、特定の時間 (ピーク時間など) にすべてのノードが中断されるのを防ぐこともできます。詳細については、「Karpenter 統合ドキュメント」を参照してください。

ttlSecondsAfterFinished を使用して Kubernetes ジョブを自動クリーンアップする

Amazon EKS の Kubernetes ジョブttlSecondsAfterFinishedに対して を設定して、完了したジョブオブジェクトを自動的に削除することをお勧めします。リンガージョブオブジェクトは、API サーバーメモリなどのクラスターリソースを消費し、ダッシュボード (Grafana、Amazon CloudWatch など) を整理してモニタリングを複雑にします。例えば、TTL を 1 時間に設定すると、ジョブは完了直後に削除され、クラスターが整理されます。詳細については、「終了したジョブの自動クリーンアップ」を参照してください。

優先度の高いジョブ/ワークロード用に優先度の低いジョブのプリエンプションを設定する

Amazon EKS の混合優先度 AI/ML ワークロードでは、優先度の高いタスク (リアルタイム推論など) がリソースを迅速に受信するように、優先度の低いジョブのプリエンプションを設定できます。プリエンプションがない場合、バッチプロセス (バッチ推論、データ処理など)、非バッチサービス (バックグラウンドタスク、cron ジョブなど)、CPU/メモリ集約型ジョブ (ウェブサービスなど) などの優先度の低いワークロードは、ノードを占有することで重要なポッドを遅らせる可能性があります。プリエンプションにより、優先度の高いポッドにリソースが必要な場合に Kubernetes は優先度の低いポッドを削除できるため、GPUs、CPUs、またはメモリを備えたノードで効率的なリソース割り当てが可能になります。Kubernetes を使用して優先順位PriorityClassを割り当てPodDisruptionBudget、エビクション動作を制御することをお勧めします。

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

詳細については、「Kubernetes Priority and Preemption Documentation」を参照してください。

アプリケーションのスケーリングとパフォーマンス

Karpenter または静的ノードを使用して ML ワークロードのコンピューティング容量を調整する

Amazon EKS での機械学習 (ML) ワークフローのコスト効率と応答性を確保するため、ワークロードの特性とコストコミットメントに合わせてノードプロビジョニング戦略を調整することをお勧めします。以下は、Karpenter just-in-timeスケーリングと、リザーブドキャパシティの静的ノードグループという 2 つの考慮すべきアプローチです。

  • Karpenter のようなJust-in-timeデータプレーンスケーラー: コンピューティング需要が変化する動的 ML ワークフロー (GPU ベースの推論と CPU ベースのプロットなど) では、Karpenter のようなjust-in-timeデータプレーンスケーラーを使用することをお勧めします。

  • 予測可能なワークロードに静的ノードグループを使用する: 予測可能な定常状態の ML ワークロードの場合、またはリザーブドインスタンスを使用する場合、EKS マネージド型ノードグループは、リザーブドキャパシティが完全にプロビジョニングおよび利用され、節約を最大化するのに役立ちます。このアプローチは、RIs または ODCRs を介してコミットされる特定のインスタンスタイプに最適です。

これは、インスタンス生成が 3 より大きい g Amazon EC2 インスタンスの起動を可能にする多様な Karpenter NodePool の例です。

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 リソースで高速化されていないワークロードをスケジュールすることはコンピューティング効率が高くありません。高速化されていないワークロードポッドが不適切なノードでスケジュールされないように、テイントと許容値を使用することをお勧めします。詳細については、Kubernetes のドキュメントを参照してください。

モデルのパフォーマンスに基づいてスケールする

推論ワークロードの場合、Kubernetes Event-Driven Auto Scaling (KEDA) を使用して、推論リクエストやトークンスループットなどのモデルパフォーマンスメトリクスに基づいて適切なクールダウン期間でスケーリングすることをお勧めします。静的スケーリングポリシーでは、リソースのプロビジョニングが過剰または過小になり、コストとレイテンシーに影響する可能性があります。詳細については、KEDA ドキュメントを参照してください。

高度な GPU 管理のための動的リソース割り当て

動的リソース割り当て (DRA) は、Kubernetes GPU リソース管理の根本的な進歩を表します。DRA は従来のデバイスプラグインの制限を超えて、高度な GPU 共有、トポロジ対応、クロスノードリソース調整を可能にします。Amazon EKS バージョン 1.33 で利用可能な DRA は、以下を提供することで AI/ML ワークロードの重要な課題に対処します。

  • きめ細かな GPU 割り当て

  • マルチプロセスサービス (MPS) やマルチインスタンス GPU (MIG) などの高度な共有メカニズム

  • NVIDIA GB200 UltraServers を含む次世代ハードウェアアーキテクチャのサポート

従来の GPU 割り当てでは、GPUs不透明な整数リソースとして扱われ、使用率が大幅に低下します (多くの場合、本番稼働用クラスターでは 30~40%)。これは、ワークロードが小数リソースのみを必要とする場合でもGPUs 全体への排他的アクセスを受け取るために発生します。DRA は、Kubernetes スケジューラにハードウェア特性とワークロード要件を完全に可視化する構造化された宣言型割り当てを導入することで、このモデルを変換します。これにより、インテリジェントな配置の決定と効率的なリソース共有が可能になります。

NVIDIA デバイスプラグインの代わりに DRA を使用する利点

NVIDIA デバイスプラグイン (バージョン 以降0.12.0) は、タイムスライス、MPS、MIG などの GPU 共有メカニズムをサポートしています。ただし、DRA が対処するアーキテクチャ上の制限があります。

NVIDIA デバイスプラグインの制限事項

  • 静的設定: GPU 共有設定 (タイムスライスレプリカと MPS 設定) には、 を通じてクラスター全体の事前設定が必要ですConfigMaps。これにより、ワークロードごとに異なる共有戦略を提供することが困難になります。

  • め細かな選択の制限: デバイスプラグインはノードラベルを介して GPU 特性を公開しますが、ワークロードはスケジューリングの決定の一環として特定の GPU 設定 (メモリサイズとコンピューティング機能) を動的にリクエストすることはできません。

  • クロスノードリソースの調整なし: 複数のノードにまたがる分散 GPU リソースを管理したり、NVIDIA GB200 などのシステムの NVLink ドメインなどの複雑なトポロジ要件を表現したりすることはできません。

  • スケジューラの制約: Kubernetes スケジューラは GPU リソースを不透明な整数として扱い、トポロジ対応の決定や複雑なリソース依存関係の処理能力を制限します。

  • 設定の複雑さ: さまざまな共有戦略をセットアップするにはConfigMaps、複数の慎重なノードラベル付けが必要で、運用が複雑になります。

DRA を使用したソリューション

  • 動的リソース選択: DRA を使用すると、ワークロードは を通じてリクエスト時に詳細な要件 (GPU メモリ、ドライバーバージョン、および特定の属性) を指定できますresourceclaims。これにより、より柔軟なリソースマッチングが可能になります。

  • トポロジの認識: DRA は、構造化されたパラメータとデバイスセレクタを通じて、クロスノード GPU 通信やメモリコヒーレント相互接続などの複雑な要件を処理します。

  • クロスノードリソース管理: 複数のノードにまたがる分散 GPU リソースの調整computeDomainsを可能にします。これは、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): 1 つの GPU で複数の CUDA プロセスの同時実行を有効にします。

  • Internode Memory Exchange (IMEX): GB200 UltraServers のノード間のメモリコヒーレント通信。

その他のリソース

Kubernetes DRA および NVIDIA DRA ドライバーの詳細については、GitHub の以下のリソースを参照してください。

高度な GPU 管理のための動的リソース割り当てを設定する

次のトピックでは、高度な GPU 管理のために動的リソース割り当て (DRA) を設定する方法を示します。

前提条件

Amazon EKS に DRA を実装する前に、環境が次の要件を満たしていることを確認してください。

クラスターの設定
  • バージョン 1.33 以降を実行している Amazon EKS クラスター

  • Amazon EKS マネージド型ノードグループ (DRA は現在、Karpenter ではなく、AL2023 および Bottlerocket NVIDIA 最適化 AMIs を持つマネージド型ノードグループでのみサポートされています) https://github.com/kubernetes-sigs/karpenter/issues/1231

  • 適切なインスタンスタイプを持つ NVIDIA GPU 対応ワーカーノード

必要なコンポーネント
  • 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 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 チャートをデプロイする

  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

    予想される出力は次のとおりです。

    deviceclasses resource.k8s.io/v1beta1 false DeviceClass resourceclaims resource.k8s.io/v1beta1 true ResourceClaim resourceclaimtemplates resource.k8s.io/v1beta1 true ResourceClaimTemplate resourceslices 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に 2 つを作成します。

    • gpu.nvidia.com スライスは、物理 A10G GPU デバイスをその仕様 (メモリ、コンピューティング機能など) に登録します。

    • A10G は MIG パーティショニングをサポートしていないため、compute-domain.nvidia.comスライスは GPU のコンピューティングコンテキスト全体を表す単一のコンピューティングドメインを作成します。

    • 次にresourceslices、これらは Kubernetes API サーバーに発行され、GPU リソースが を通じてスケジューリングできるようになりますresourceclaims

      DRA スケジューラは、 を介して GPU リソースをリクエストする Pod にこの GPU をインテリジェントに割り当てることができるようになりresourceclaimtemplates、従来のデバイスプラグインアプローチよりも柔軟なリソース管理が可能になりました。これは、手動操作なしで自動的に行われます。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. という名前のファイルを使用して GPU 割り当てResourceClaimTemplateの基本 を作成します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で を使用する Pod を作成しますbasic-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 は、さまざまなユースケースとハードウェア機能に対応するいくつかの高度な最適化手法を可能にします。

これらの手法により、リソースの使用率が大幅に向上します。組織は、GPU 使用率が従来の割り当てで 30~40% から、最適化された共有戦略で 80~90% に増加すると報告しています。手法の選択は、ワークロードの特性、分離要件、ハードウェア機能によって異なります。

タイムスライスによる GPU ワークロードの最適化

タイムスライスを使用すると、複数のワークロードが同じ物理 GPU で順次実行されるようにスケジュールすることで、GPU コンピューティングリソースを共有できます。GPU を散発的に使用する推論ワークロードに最適です。

次の手順を実行します。

  1. という名前のファイルを使用してタイムスライスResourceClaimTemplate用の を定義しますtimeslicing-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. という名前のファイルでタイムスライスを使用してポッドを定義しますtimeslicing-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

最初のポッド (inference-pod-1)

  • 状態: allocated,reserved

  • 意味: DRA が使用可能な GPU を見つけ、この Pod 用に予約しました

  • ポッドステータス: すぐに実行を開始します

2 番目のポッド (training-pod-2)

  • 状態: pending

  • 意味: DRA が同じ GPU でタイムスライスを設定するのを待つ

  • ポッドのステータス: スケジュールの待機中

  • 状態は から pending allocated,reservedに変わります running

MPS で GPU ワークロードを最適化する

マルチプロセスサービス (MPS) を使用すると、タイムスライスよりも優れた分離で、単一の GPU で複数の CUDA コンテキストを同時に実行できます。

次の手順を実行します。

  1. という名前のファイルを使用して MPS ResourceClaimTemplateの を定義します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 を使用してポッドを定義しますmps-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 ドライバーは Pod ResourceClaimに 1 つを割り当て、推論コンテナとトレーニングコンテナの両方を同時に実行できるように MPS を自動的に設定します。

各コンテナは、独自の独立した GPU メモリスペースとコンピューティングリソースを取得し、MPS デーモンが基盤となるハードウェアへのアクセスを調整します。次の操作を行うことで、これが機能していることを確認できます。

  • をチェックするとnvidia-smi、両方のコンテナが同じ GPU デバイスを共有する M+C (MPS + Compute) プロセスとして表示されます。

  • 両方のコンテナからのログをモニタリングすると、同時実行を証明するインターリーブタイムスタンプが表示されます。

このアプローチは、補完的なワークロードが 1 つのプロセスで十分に活用されないままにするのではなく、高価な 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 設定を自動的に適用する MIG Manager コンポーネントを介した包括的な MIG 管理機能が含まれています。MIG プロファイルの変更がリクエストされると、オペレーターはすべての GPU クライアントを適切にシャットダウンし、新しいパーティションジオメトリを適用して、影響を受けるサービスを再起動します。このプロセスでは、GPU インスタンスのノードを再起動して、GPU の状態をクリーンに移行する必要があります。そのため、MIG Manager 設定WITH–0—REBOOT=trueで を有効にすることは、MIG デプロイを成功させるために不可欠です。

Amazon EKS で MIG を使用するには、NVIDIA DRA ドライバーと NVIDIA GPU Operator の両方が必要です。NVIDIA Device Plugin と DCGM Exporter は NVIDIA GPU Operator の一部であるため、これに加えては必要ありません。EKS NVIDIA AMIs には NVIDIA ドライバーがプリインストールされているため、競合を回避し、インスタンスに既に存在する最適化されたドライバーを活用するために、GPU Operator によるドライバーのデプロイを無効にしました。NVIDIA DRA ドライバーは MIG インスタンスの動的リソース割り当てを処理し、GPU オペレーターは 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 チャートは、以下のコンポーネントと複数の MIG プロファイルをデプロイします。

    • Device Plugin (GPU リソーススケジューリング)

    • DCGM Exporter (GPU メトリクスとモニタリング)

    • Node Feature Discovery (NFD - ハードウェアラベル付け)

    • GPU Feature Discovery (GFD - GPU 固有のラベル付け)

    • MIG Manager (マルチインスタンス GPU パーティショニング)

    • Container Toolkit (GPU コンテナランタイム)

    • オペレーターコントローラー (ライフサイクル管理)

  4. デプロイポッドを確認します。

    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. MIG の例をテストするための p4De マネージドノードグループを使用して Amazon EKS クラスターを作成します。

    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 インスタンスに p4de-half-balanced MIG プロファイルを正常に適用し、設定に従ってハードウェアレベルの 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 オペレーターが作成した内容は次のとおりです。

  • 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 ポッドとテストポッドをデプロイして、DRA ドライバーが使用可能な MIG パーティションにワークロードを配置する方法を確認し、複数のコンテナがハードウェアレベルの分離で GPU リソースを共有できるようにします。

  1. MIG を含めるmig-claim-template.yamlために を作成しますresourceclaimtemplates

    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. 3 つのテンプレートを適用します。

    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. この仕様を適用し、3 つの Pod をデプロイします。

    kubctl apply -f mig-pod.yaml

    これらのポッドは 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

    ご覧のとおり、すべての Pod は DRA ドライバーallocated,reservedによって保留中から に移動しました。

  8. ノードnvidia-smiから を実行します。3 つの 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 UltraServers での分散トレーニングのために、ノード間のメモリコヒーレント通信を可能にします。

次の手順を実行します。

  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 チャネルを使用してポッドを定義しますimex-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
  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 の例を参照してください。