

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

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

# Amazon EKS 上の NVIDIA GPU でタイムスライシングを使用する
<a name="device-management-nvidia-time-slicing"></a>

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

Amazon EKS では、[NVIDIA DRA ドライバー](device-management-nvidia-dra-device-plugin.md#eks-nvidia-dra-driver)または [NVIDIA デバイスプラグイン](device-management-nvidia-dra-device-plugin.md#eks-nvidia-device-plugin)を使用してタイムスライシングを管理できます。

タイムスライシングは、[静的キャパシティのプロビジョニング](https://karpenter.sh/docs/concepts/nodepools/#static-nodepool)を使用している場合にのみ Karpenter で使用できます。タイムスライシングは現在、EKS Auto Mode では使用できません。

タイムスライシングは、次の場合に適しています:
+ GPU 使用率が一貫して低い。例えば、リクエスト間でアイドル状態になるレイテンシーの影響を受けやすい推論サービスなど。
+ 複数の開発者がノートブックまたは開発作業用に単一の GPU ノードを共有している。
+ ノードが、`g5`、`g6`、`g6e` ファミリーなど、MIG をサポートしていない GPU インスタンスタイプを使用している。
+ 同じ GPU 上の別の Pod がビジー状態であるため、Pod が低速になる場合があることを許容できる。

次の場合は、別のアプローチを検討してください:
+ メモリの分離が必要である。タイムスライスされた GPU 上のポッドは同じ GPU メモリを共有し、1 つのポッドは他のポッドが依存するメモリを使い果たすことができます。メモリの分離には MIG を使用します。
+ 予測可能なポッドごとのレイテンシーまたはサービス品質が必要である。GPU スケジューラは、保証なしでベストエフォートベースでスロット間でコンピューティングを共有します。
+ トレーニングワークロードを実行している。タイムスライシングは、トレーニング効率を低下させるコンテキスト切り替えを追加します。別の Pod によって遅くなるチェックポイントジョブは、最後のチェックポイントから再試行する必要があります。

## 考慮事項
<a name="eks-time-slicing-considerations"></a>

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

### 一般的な考慮事項
<a name="_general_considerations"></a>
+  **メモリ分離がない:** タイムスライスされた 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 ドライバーに関する考慮事項
<a name="_nvidia_dra_driver_considerations"></a>
+  **アルファ機能:** DRA ドライバーを通じたタイムスライシングには、デフォルトで無効になっているアルファ機能である `TimeSlicingSettings` 機能ゲートが必要です。詳細については、「[NVIDIA DRA ドライバーで GPU タイムスライシングを使用する](#eks-time-slicing-dra)」を参照してください。
+  **ユーザーによる共有のみ:** Pod は、名前空間スコープされている同じ `ResourceClaim` または `ResourceClaimTemplate` を参照することによってのみ GPU を共有するため、共有は名前空間を横断できません。システムによる共有は、将来の機能として提案されています。
+  **Bottlerocket の組み込みデバイスプラグインを無効にする:** DRA ドライバーを同じノードの NVIDIA デバイスプラグインと一緒に実行することはできません。Bottlerocket で、組み込みデバイスプラグインを無効にします。これには Bottlerocket バージョン 1.63.0 以降が必要です。詳細については、「[NVIDIA DRA ドライバーをインストールする](device-management-nvidia-dra-device-plugin.md#eks-nvidia-dra-driver)」を参照してください。
+  **コンピューティングサポート:** NVIDIA DRA ドライバーは、Karpenter、EKS マネージドノードグループ、またはセルフマネージドノードの静的キャパシティのプロビジョニングでサポートされており、EKS Auto Mode ではサポートされていません。詳細については、Karpenter ウェブサイトの「[Karpenter 静的 NodePool ドキュメント](https://karpenter.sh/docs/concepts/nodepools/#static-nodepool)」を参照してください。

### NVIDIA デバイスプラグインに関する考慮事項
<a name="_nvidia_device_plugin_considerations"></a>
+  **スロットを使用したベストエフォートのコンピューティング共有:** デバイスプラグインは、GPU ごとに固定数のスロットをアドバタイズします。単一の Pod が複数のスロットをリクエストした場合、追加のコンピューティングは受け取りません。`fail-requests-greater-than-one` オプションを有効にして、複数のスロットをリクエストする Pod を拒否します。
+  **Karpenter を使用したプロビジョニング:** Karpenter は、GPU でタイムスライシングスが有効になっている場合でも、各 `nvidia.com/gpu` リクエストを物理 GPU としてカウントします。詳細については、GitHub の「[Karpenter の問題 \#2140](https://github.com/kubernetes-sigs/karpenter/issues/2140)」を参照してください。
+  **EKS Auto Mode でのサポートがない:** EKS Auto Mode は NVIDIA デバイスプラグインを管理し、その設定を公開しません。タイムスライシングにはデバイスプラグイン設定が必要であるため、EKS Auto Mode ノードでタイムスライシング設定を適用することはできません。
+  **タイムスライシング設定の変更:** NVIDIA デバイスプラグインはタイムスライシング `ConfigMap` の変更をモニタリングしません。設定を更新したら、デバイスプラグインを再起動します。

## 設定オプション
<a name="eks-time-slicing-configuration-options"></a>

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 ドライバーをインストールする](device-management-nvidia-dra-device-plugin.md#eks-nvidia-dra-driver)」を参照してください。

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


| Interval | 説明 | 
| --- | --- | 
| デフォルト | NVIDIA GPU ドライバーの組み込みデフォルト間隔を使用する | 
| ショート | 短い間隔、コンテキストの切り替え頻度が高い | 
| 中 | 中間の間隔 | 
| ロング | 各コンテキストは、プリエンプトされる前に、ターンごとに実行時間が長くなる | 

------
#### [ NVIDIA device plugin ]
+  **Bottlerocket** – AMI には、NVIDIA デバイスプラグインがプリインストールされています。Bottlerocket 設定を介してタイムスライシングを設定します。個別のデバイスプラグインのインストール、Helm チャート、または `ConfigMap` はありません。
+  **AL2023** – [NVIDIA Kubernetes デバイスプラグインをインストールする](device-management-nvidia-dra-device-plugin.md#eks-nvidia-device-plugin) で説明されているように NVIDIA デバイスプラグインをインストールし、`ConfigMap` を介してタイムスライス設定を指定します。

  以下のオプションは、NVIDIA デバイスプラグインがタイムスライスされた GPU をアドバタイズおよび管理する方法を制御します。フィールド名は、以下の手順に示すように、Bottlerocket 設定と AL2023 `ConfigMap` で異なります。    
[See the AWS documentation website for more details](http://docs.aws.amazon.com/ja_jp/eks/latest/userguide/device-management-nvidia-time-slicing.html)

  GPU 共有オプションとそのデフォルト値の完全なリストについては、GitHub の「[NVIDIA Kubernetes デバイスプラグインドキュメント](https://github.com/NVIDIA/k8s-device-plugin/blob/main/README.md#shared-access-to-gpus)」を参照してください。

------

## NVIDIA DRA ドライバーで GPU タイムスライシングを使用する
<a name="eks-time-slicing-dra"></a>

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

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

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

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

### 前提条件
<a name="_prerequisites"></a>
+ Amazon EKS クラスターで Kubernetes バージョン 1.34 以降が動作していること。NVIDIA DRA ドライバーは、Karpenter、EKS マネージドノードグループ、またはセルフマネージドノードでの静的キャパシティのプロビジョニングでサポートされています。
+ ノードのインスタンスタイプが NVIDIA GPU であり、EKS 最適化 AL2023 NVIDIA AMI を使用していること。
+ [NVIDIA DRA ドライバーをインストールする](device-management-nvidia-dra-device-plugin.md#eks-nvidia-dra-driver) で説明されているように NVIDIA DRA ドライバーがインストールされ、`TimeSlicingSettings` 機能ゲートが有効になっています。

### 手順
<a name="_procedure"></a>

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
   ```

1. 名前で共有された `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
   ```

1. 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 タイムスライシングを使用する
<a name="eks-time-slicing-device-plugin-bottlerocket"></a>

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

### 前提条件
<a name="_prerequisites_2"></a>
+ Amazon EKS クラスター。次の手順では、EKS 最適化 Bottlerocket NVIDIA AMI を使用して NVIDIA GPU ノードをプロビジョニングします。
+ Karpenter がクラスターにインストールおよび設定されていること。それは、次の手順で、Karpenter `EC2NodeClass` を使用して Bottlerocket ノードのユーザーデータにタイムスライシング設定を指定するからです。詳細については、Karpenter ウェブサイトの「[Karpenter の開始方法](https://karpenter.sh/docs/getting-started/getting-started-with-karpenter/)」を参照してください。
+  クラスターと通信するように `kubectl` が設定されていること。詳細については、「[`kubectl` をインストールまたは更新する](install-kubectl.md#kubectl-install-update)」を参照してください。

### 手順
<a name="_procedure_2"></a>

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 タイムスライシングを使用する
<a name="eks-time-slicing-device-plugin-al2023"></a>

AL2023 では、[NVIDIA Kubernetes デバイスプラグインをインストールする](device-management-nvidia-dra-device-plugin.md#eks-nvidia-device-plugin) で説明されているように NVIDIA デバイスプラグインをインストールし、`ConfigMap` でタイムスライス設定を指定します。

### 前提条件
<a name="_prerequisites_3"></a>
+ NVIDIA GPU インスタンスタイプを使用しているノードと EKS 最適化 AL2023 NVIDIA AMI がある Amazon EKS クラスター。
+ コマンドライン環境に Helm がインストールされていること。詳細については、「[Setup Helm instructions](helm.md)」を参照してください。
+  クラスターと通信するように `kubectl` が設定されていること。詳細については、「[`kubectl` をインストールまたは更新する](install-kubectl.md#kubectl-install-update)」を参照してください。

### 手順
<a name="_procedure_3"></a>

1. [NVIDIA Kubernetes デバイスプラグインをインストールする](device-management-nvidia-dra-device-plugin.md#eks-nvidia-device-plugin) にデバイスプラグインをインストールした `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
   ```

1. 既存の NVIDIA デバイスプラグインリリースを更新して、`config.name` 値で `ConfigMap` を参照します。`--reuse-values` フラグは、[NVIDIA Kubernetes デバイスプラグインをインストールする](device-management-nvidia-dra-device-plugin.md#eks-nvidia-device-plugin) にデバイスプラグインをインストールしたときに設定した値を保持します。

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

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

## GPU タイムスライシングがアクティブであることを確認する
<a name="verify-eks-time-slicing"></a>

タイムスライスされたノードが `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
   ```

1. 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
   ```

1. 4 個の Pod がすべて同じノードでスケジュールされていることを確認します。

   ```
   kubectl get pods -l app=timeslicing-demo -o wide
   ```

1. 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
   ```