View a markdown version of this page

Amazon EKS 上の NVIDIA GPU でタイムスライシングを使用する - Amazon EKS

このページの改善にご協力ください

このユーザーガイドに貢献するには、すべてのページの右側のペインにある「GitHub でこのページを編集する」リンクを選択してください。

Amazon EKS 上の NVIDIA GPU でタイムスライシングを使用する

タイムスライシングを使用すると、複数の Pod が単一の物理 NVIDIA GPU を共有できます。Kubernetes スケジューラは同じ GPU に複数の Pod を配置し、GPU の CUDA スケジューラは作業をタイムマルチプレックスします。タイムスライシングは、最もシンプルな GPU 共有戦略です。ソフトウェアのみを使用し、特別なハードウェアを必要とせず、AWS 上のすべての NVIDIA GPU インスタンスタイプで動作します。タイムスライシングでは、GPU を共有する Pod 間でメモリやコンピューティングの分離を行うことはありません。これは、リクエスト間でアイドル状態になる推論サービスや、複数のユーザーが GPU を共有する開発環境など、GPU 使用率が低いワークロードに最適です。ハードウェアレベルのメモリとコンピューティングの分離を必要とするワークロードでは、代わりにマルチインスタンス GPU (MIG) を使用します。

Amazon EKS では、NVIDIA DRA ドライバーまたは NVIDIA デバイスプラグインを使用してタイムスライシングを管理できます。

タイムスライシングは、静的キャパシティのプロビジョニングを使用している場合にのみ Karpenter で使用できます。タイムスライシングは現在、EKS Auto Mode では使用できません。

タイムスライシングは、次の場合に適しています:

  • GPU 使用率が一貫して低い。例えば、リクエスト間でアイドル状態になるレイテンシーの影響を受けやすい推論サービスなど。

  • 複数の開発者がノートブックまたは開発作業用に単一の GPU ノードを共有している。

  • ノードが、g5g6g6e ファミリーなど、MIG をサポートしていない GPU インスタンスタイプを使用している。

  • 同じ GPU 上の別の Pod がビジー状態であるため、Pod が低速になる場合があることを許容できる。

次の場合は、別のアプローチを検討してください:

  • メモリの分離が必要である。タイムスライスされた GPU 上のポッドは同じ GPU メモリを共有し、1 つのポッドは他のポッドが依存するメモリを使い果たすことができます。メモリの分離には MIG を使用します。

  • 予測可能なポッドごとのレイテンシーまたはサービス品質が必要である。GPU スケジューラは、保証なしでベストエフォートベースでスロット間でコンピューティングを共有します。

  • トレーニングワークロードを実行している。タイムスライシングは、トレーニング効率を低下させるコンテキスト切り替えを追加します。別の Pod によって遅くなるチェックポイントジョブは、最後のチェックポイントから再試行する必要があります。

考慮事項

本番環境でタイムスライシングを使用する前に、以下の考慮事項を確認してください。

一般的な考慮事項

  • メモリ分離がない: タイムスライスされた GPU を共有する Pod はメモリを共有します。1 つの Pod が他の Pod に必要なメモリを割り当てることができるため、メモリ不足エラーが発生する可能性があります。各 GPU を共有する Pod の数をワークロードのメモリフットプリントに一致させます。Pod が定期的に大きなモデルをロードする場合は、GPU あたりの Pod 数を減らすか、MIG を使用します。

  • ベストエフォートのコンピューティング共有: GPU スケジューラは、ベストエフォートベースで Pod 間でコンピューティングを共有し、各 Pod に対して比例するコンピューティングを保証するものではありません。

  • タイムスライシングと MPS は同じ GPU を共有できない: タイムスライシングは GPU コンピューティングモードを DEFAULT に設定しますが、NVIDIA Multi-Process Service (MPS) には EXCLUSIVE_PROCESS が必要です。両方の戦略を同じクラスターで使用できますが、同じ物理 GPU で同時に使用することはできません。タイムスライシングは MIG インスタンスにも影響しません。コンテナ間で単一の MIG インスタンスを共有するには、代わりに MPS を使用します。

  • コンテナごとのメトリクス: タイムスライシングがアクティブな場合、NVIDIA Data Center GPU Manager (DCGM) はメトリクスを個々のコンテナに帰属させることができません。GPU レベルのメトリクスは引き続き使用できますが、どの Pod が一定量の GPU リソースを消費したかを特定することはできません。

NVIDIA DRA ドライバーに関する考慮事項

  • アルファ機能: DRA ドライバーを通じたタイムスライシングには、デフォルトで無効になっているアルファ機能である TimeSlicingSettings 機能ゲートが必要です。詳細については、「NVIDIA DRA ドライバーで GPU タイムスライシングを使用する」を参照してください。

  • ユーザーによる共有のみ: Pod は、名前空間スコープされている同じ ResourceClaim または ResourceClaimTemplate を参照することによってのみ GPU を共有するため、共有は名前空間を横断できません。システムによる共有は、将来の機能として提案されています。

  • Bottlerocket の組み込みデバイスプラグインを無効にする: DRA ドライバーを同じノードの NVIDIA デバイスプラグインと一緒に実行することはできません。Bottlerocket で、組み込みデバイスプラグインを無効にします。これには Bottlerocket バージョン 1.63.0 以降が必要です。詳細については、「NVIDIA DRA ドライバーをインストールする」を参照してください。

  • コンピューティングサポート: NVIDIA DRA ドライバーは、Karpenter、EKS マネージドノードグループ、またはセルフマネージドノードの静的キャパシティのプロビジョニングでサポートされており、EKS Auto Mode ではサポートされていません。詳細については、Karpenter ウェブサイトの「Karpenter 静的 NodePool ドキュメント」を参照してください。

NVIDIA デバイスプラグインに関する考慮事項

  • スロットを使用したベストエフォートのコンピューティング共有: デバイスプラグインは、GPU ごとに固定数のスロットをアドバタイズします。単一の Pod が複数のスロットをリクエストした場合、追加のコンピューティングは受け取りません。fail-requests-greater-than-one オプションを有効にして、複数のスロットをリクエストする Pod を拒否します。

  • Karpenter を使用したプロビジョニング: Karpenter は、GPU でタイムスライシングスが有効になっている場合でも、各 nvidia.com/gpu リクエストを物理 GPU としてカウントします。詳細については、GitHub の「Karpenter の問題 #2140」を参照してください。

  • EKS Auto Mode でのサポートがない: EKS Auto Mode は NVIDIA デバイスプラグインを管理し、その設定を公開しません。タイムスライシングにはデバイスプラグイン設定が必要であるため、EKS Auto Mode ノードでタイムスライシング設定を適用することはできません。

  • タイムスライシング設定の変更: NVIDIA デバイスプラグインはタイムスライシング ConfigMap の変更をモニタリングしません。設定を更新したら、デバイスプラグインを再起動します。

設定オプション

EKS 最適化 AL2023 および Bottlerocket NVIDIA AMI では、NVIDIA GPU のタイムスライシングを使用できます。タイムスライシング設定は、NVIDIA DRA ドライバーと NVIDIA デバイスプラグインのどちらを使用しているかによって異なります。

NVIDIA DRA driver

EKS 最適化高速 AMI には NVIDIA DRA ドライバーは含まれていません。Bottlerocket を使用している場合は、ノードユーザーデータで settings.kubelet-device-plugins.nvidia.enabled = false を設定して、NVIDIA DRA ドライバーを使用する前に組み込み NVIDIA デバイスプラグインを無効にする必要があります。これには Bottlerocket バージョン 1.63.0 以降が必要です。詳細については、「NVIDIA DRA ドライバーをインストールする」を参照してください。

NVIDIA DRA ドライバーでは、タイムスライシングは ResourceClaimTemplates を介して設定されます。interval フィールドは、CUDA タイムスライス期間を制御します。

Interval 説明

デフォルト

NVIDIA GPU ドライバーの組み込みデフォルト間隔を使用する

ショート

短い間隔、コンテキストの切り替え頻度が高い

中間の間隔

ロング

各コンテキストは、プリエンプトされる前に、ターンごとに実行時間が長くなる

NVIDIA device plugin
  • Bottlerocket – AMI には、NVIDIA デバイスプラグインがプリインストールされています。Bottlerocket 設定を介してタイムスライシングを設定します。個別のデバイスプラグインのインストール、Helm チャート、または ConfigMap はありません。

  • AL2023NVIDIA Kubernetes デバイスプラグインをインストールする で説明されているように NVIDIA デバイスプラグインをインストールし、ConfigMap を介してタイムスライス設定を指定します。

    以下のオプションは、NVIDIA デバイスプラグインがタイムスライスされた GPU をアドバタイズおよび管理する方法を制御します。フィールド名は、以下の手順に示すように、Bottlerocket 設定と AL2023 ConfigMap で異なります。

    オプション 推奨値 説明

    レプリカ

    2~8

    物理 GPU ごとにアドバタイズするスケジュール可能なスロットの数。値を大きくすると、より多くの共有が可能になりますが、Pod 間の競合が増加します。

    デフォルトで名前を変更

    false

    false の場合、Pod は既存のマニフェストとの互換性を維持する nvidia.com/gpu をリクエストします。true の場合、デバイスプラグインはリソースを nvidia.com/gpu.shared としてアドバタイズし、Pod はその名前をリクエストする必要があります。共有 GPU ノードプールと専用 GPU ノードプールの両方を実行し、ワークロードで共有リソースを明示的に選択する場合は、これを true に設定します。

    複数のリクエストの失敗

    true

    複数のタイムスライスされたスロットをリクエストする Pod を拒否します。複数のスロットをリクエストする Pod は、比例コンピューティングを受け取りません。この設定を有効にすると、一般的な設定ミスを防ぐことができます。

    GPU 共有オプションとそのデフォルト値の完全なリストについては、GitHub の「NVIDIA Kubernetes デバイスプラグインドキュメント」を参照してください。

NVIDIA DRA ドライバーで GPU タイムスライシングを使用する

NVIDIA DRA ドライバーを使用して、Pod はタイムスライシング GpuConfig を持つ gpu.nvidia.com DeviceClass をリクエストする共通の ResourceClaim を参照することで GPU を共有します。

NVIDIA DRA ドライバーは現在、ユーザーによるタイムスライシングを実装しています。GPU は、同じクレームを明示的に指定した Pod とコンテナ間でのみ共有されます。ResourceClaimResourceClaimTemplate は名前空間スコープされているため、この方法で GPU を共有する Pod は同じ名前空間にある必要があります。単一の Pod 内のコンテナ間で GPU を共有するには、各コンテナにクレーム内の同じリクエスト名を参照させます。異なるリクエスト名を参照するコンテナはそれぞれ個別の GPU を受け取ります。必要なタイムスライス間隔ごとに個別の ResourceClaimTemplate を作成し、GPU を共有する各名前空間にも 1 つ作成します。

システムによるタイムスライシングは、ドライバーが、設定したクレームではなく、システムが定義する基準に基づいて、独立したクレーム間 (名前空間間を含む) で GPU を共有する場合に行われます。システムによるタイムスライシングの詳細については、GitHub の「GPU のシステムによるタイムスライシング (問題 #659)」および「プルリクエスト #1257」を参照してください。

重要

DRA ドライバーを通じたタイムスライシングには、デフォルトで無効になっているアルファ機能である TimeSlicingSettings 機能ゲートが必要です。この機能ゲートを有効にせずに TimeSlicing 共有戦略をリクエストした場合、ドライバーはデバイスの準備に失敗し、Pod は error validating GPU config: unknown GPU sharing strategy: TimeSlicing をレポートする FailedPrepareDynamicResources イベントとともに ContainerCreating のままになります。アルファ機能を使用するリスクを受け入れる場合にのみ、機能ゲートを有効にします。

前提条件

  • Amazon EKS クラスターで Kubernetes バージョン 1.34 以降が動作していること。NVIDIA DRA ドライバーは、Karpenter、EKS マネージドノードグループ、またはセルフマネージドノードでの静的キャパシティのプロビジョニングでサポートされています。

  • ノードのインスタンスタイプが NVIDIA GPU であり、EKS 最適化 AL2023 NVIDIA AMI を使用していること。

  • NVIDIA DRA ドライバーをインストールする で説明されているように NVIDIA DRA ドライバーがインストールされ、TimeSlicingSettings 機能ゲートが有効になっています。

手順

  1. TimeSlicing 共有戦略を使用して GPU をリクエストする ResourceClaim を作成します。このクレームを参照する複数の Pod は、同じ物理 GPU を共有します。

    cat <<EOF | kubectl apply -f - apiVersion: resource.k8s.io/v1 kind: ResourceClaim metadata: name: shared-timeslice-gpu spec: devices: requests: - name: gpu exactly: deviceClassName: gpu.nvidia.com count: 1 config: - requests: ["gpu"] opaque: driver: gpu.nvidia.com parameters: apiVersion: resource.nvidia.com/v1beta1 kind: GpuConfig sharing: strategy: TimeSlicing timeSlicingConfig: interval: Long EOF
  2. 名前で共有された ResourceClaim を参照する 2 つ以上の Pod をデプロイします。各 Pod は、resourceClaims および resources.claims を通じてクレームを参照します。

    cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: share-a spec: tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule containers: - name: cuda image: nvidia/cuda:12.6.0-base-ubuntu22.04 command: ["nvidia-smi", "-L"] resources: claims: - name: gpu resourceClaims: - name: gpu resourceClaimName: shared-timeslice-gpu restartPolicy: OnFailure EOF
  3. Pod が同じ物理 GPU を共有していることを確認します。各 Pod で nvidia-smi -L を実行し、同じ GPU UUID がレポートされていることを確認します。

    kubectl logs share-a

    出力例は次のとおりです。同じクレームを参照する 2 番目の Pod は、同一の GPU UUID をレポートし、両方の Pod が 1 つの物理 GPU を共有していることを確認します。

    GPU 0: NVIDIA L4 (UUID: GPU-b41973ee-5d0a-cde8-6287-12b53f861f02)

NVIDIA デバイスプラグインで Bottlerocket ノードの GPU タイムスライシングを使用する

Bottlerocket では、EKS 最適化高速 AMI には NVIDIA デバイスプラグインが含まれています。ノードの起動時に Bottlerocket がデバイスプラグイン設定にレンダリングする settings.kubelet-device-plugins.nvidia 設定を通じてタイムスライシングを有効にします。

前提条件

  • Amazon EKS クラスター。次の手順では、EKS 最適化 Bottlerocket NVIDIA AMI を使用して NVIDIA GPU ノードをプロビジョニングします。

  • Karpenter がクラスターにインストールおよび設定されていること。それは、次の手順で、Karpenter EC2NodeClass を使用して Bottlerocket ノードのユーザーデータにタイムスライシング設定を指定するからです。詳細については、Karpenter ウェブサイトの「Karpenter の開始方法」を参照してください。

  • クラスターと通信するように kubectl が設定されていること。詳細については、「kubectl をインストールまたは更新する」を参照してください。

手順

GPU ノードの Bottlerocket ユーザーデータにタイムスライシング設定を追加します。以下の例では、GPU ごとに 4 つのスロットを設定します。ユーザーデータの提供方法は、ノードのプロビジョニング方法によって異なります。次の例は、Karpenter EC2NodeClass を示しています。

cat <<EOF | kubectl apply -f - apiVersion: karpenter.k8s.aws/v1 kind: EC2NodeClass metadata: name: gpu-bottlerocket-timeslicing spec: amiFamily: Bottlerocket amiSelectorTerms: - alias: bottlerocket@latest role: eksctl-KarpenterNodeRole-<cluster-name> subnetSelectorTerms: - tags: karpenter.sh/discovery: <cluster-name> securityGroupSelectorTerms: - tags: karpenter.sh/discovery: <cluster-name> userData: | [settings.kubelet-device-plugins.nvidia] device-sharing-strategy = "time-slicing" [settings.kubelet-device-plugins.nvidia.time-slicing] replicas = 4 rename-by-default = false fail-requests-greater-than-one = true EOF

これらの設定でプロビジョニングされたノードがクラスターを結合すると、デバイスプラグインは物理 GPU ごとに 4 個の nvidia.com/gpu スロットをアドバタイズします。nvidia.com/gpu 拡張リソースのコンテナリソースリクエストまたは制限を使用して、ワークロード仕様でリクエストします。

NVIDIA デバイスプラグインで AL2023 ノードの GPU タイムスライシングを使用する

AL2023 では、NVIDIA Kubernetes デバイスプラグインをインストールする で説明されているように NVIDIA デバイスプラグインをインストールし、ConfigMap でタイムスライス設定を指定します。

前提条件

  • NVIDIA GPU インスタンスタイプを使用しているノードと EKS 最適化 AL2023 NVIDIA AMI がある Amazon EKS クラスター。

  • コマンドライン環境に Helm がインストールされていること。詳細については、「Setup Helm instructions」を参照してください。

  • クラスターと通信するように kubectl が設定されていること。詳細については、「kubectl をインストールまたは更新する」を参照してください。

手順

  1. NVIDIA Kubernetes デバイスプラグインをインストールする にデバイスプラグインをインストールした nvidia 名前空間にタイムスライシング ConfigMap を作成します。この例では、GPU ごとに 4 個のスロットを設定します。

    cat <<EOF | kubectl apply -f - apiVersion: v1 kind: ConfigMap metadata: name: nvidia-device-plugin-config namespace: nvidia data: config.yaml: | version: v1 sharing: timeSlicing: renameByDefault: false failRequestsGreaterThanOne: true resources: - name: nvidia.com/gpu replicas: 4 EOF
  2. 既存の NVIDIA デバイスプラグインリリースを更新して、config.name 値で ConfigMap を参照します。--reuse-values フラグは、NVIDIA Kubernetes デバイスプラグインをインストールする にデバイスプラグインをインストールしたときに設定した値を保持します。

    helm upgrade nvdp nvdp/nvidia-device-plugin \ --namespace nvidia \ --reuse-values \ --set config.name=nvidia-device-plugin-config
注記

ConfigMap を変更しても、デバイスプラグインは自動的に再ロードされません。タイムスライシング設定を更新したら、デバイスプラグイン Pod を再起動して変更を適用します。

GPU タイムスライシングがアクティブであることを確認する

タイムスライスされたノードが Ready になったら、デバイスプラグインが予想されるスロット数をアドバタイズし、Pod が物理 GPU を共有していることを確認します。

注記

この手順の共有 UUID チェックは、Pod が同じ物理 GPU に配置されたときに最も明確にタイムスライシングを示します。単一の GPU を持つノードでは、デバイスプラグインは 4 個のスロットをアドバタイズし、4 個の Pod すべてがその GPU を共有するため、それらは同じ UUID をレポートします。複数の物理 GPU を持つノードでは、スケジューラは異なる GPU に Pod を配置できます。これらの Pod は、タイムスライシングがアクティブであっても、異なる UUID をレポートします。1 個の GPU での共有をデモンストレーションするには、ワークロードを単一 GPU インスタンスタイプにスケジュールします。例えば、node.kubernetes.io/instance-type: g6.2xlarge などのノードセレクターを Pod 仕様に追加します。

  1. 設定された数の GPU スロットをノードがアドバタイズしていることを確認します。GPU ごとに 4 個のスロットがある場合、1 個の物理 GPU を持つノードは 4 をレポートします。

    kubectl get nodes "-o=custom-columns=NAME:.metadata.name,GPU:.status.allocatable.nvidia\.com/gpu"

    出力例は次のとおりです。

    NAME GPU ip-192-168-11-225.us-west-2.compute.internal 4
  2. 4 個のレプリカを実行するデプロイを作成し、それぞれが 1 個の GPU スロットをリクエストします。

    cat <<EOF | kubectl apply -f - apiVersion: apps/v1 kind: Deployment metadata: name: timeslicing-demo spec: replicas: 4 selector: matchLabels: app: timeslicing-demo template: metadata: labels: app: timeslicing-demo spec: tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule containers: - name: cuda image: nvidia/cuda:12.6.0-base-ubuntu22.04 command: ["bash", "-c", "nvidia-smi --query-gpu=uuid --format=csv,noheader; sleep infinity"] resources: limits: nvidia.com/gpu: 1 EOF
  3. 4 個の Pod がすべて同じノードでスケジュールされていることを確認します。

    kubectl get pods -l app=timeslicing-demo -o wide
  4. 4 個の Pod がすべて同じ GPU UUID をレポートしていることを確認します。4 個の Pod すべてにまたがる単一の共有 UUID は、1 個の物理 GPU が時間多重化されていることを確認します。

    kubectl logs -l app=timeslicing-demo --prefix

    出力例は次のとおりです。

    [pod/timeslicing-demo-xxxxxxxxxx-aaaaa/cuda] GPU-c0583cce-87c5-c736-db7f-6d3128c84d03 [pod/timeslicing-demo-xxxxxxxxxx-bbbbb/cuda] GPU-c0583cce-87c5-c736-db7f-6d3128c84d03 [pod/timeslicing-demo-xxxxxxxxxx-ccccc/cuda] GPU-c0583cce-87c5-c736-db7f-6d3128c84d03 [pod/timeslicing-demo-xxxxxxxxxx-ddddd/cuda] GPU-c0583cce-87c5-c736-db7f-6d3128c84d03