Skip to content
Published on

Kubernetes GPUワークロード管理:NVIDIA GPU Operator完全ガイド

Authors
  • Name
    Twitter

1. KubernetesでGPUを使用すべき理由

AI/MLワークロードの爆発的な増加により、GPUはもはや選択肢ではなく必須のインフラとなった。LLM学習、推論サービング、コンピュータビジョン、科学シミュレーションなど、さまざまな分野でGPUアクセラレーテッドコンピューティングが求められており、これらのワークロードを大規模に運用するにはKubernetesベースのオーケストレーションが必然的である。

KubernetesでGPUを使用すると、以下のメリットが得られる。

  • リソーススケジューリングの自動化nvidia.com/gpuリソースタイプを通じて、Pod単位でGPUを宣言的に要求・割り当てできる。
  • マルチテナンシー:Namespace、ResourceQuota、LimitRangeを活用して、チームごとのGPUリソースを分離し、公平に分配できる。
  • GPU共有:MIG、Time-Slicing、MPSなどの技術を通じて、単一のGPUを複数のワークロードで共有し、コスト効率を最大化できる。
  • オートスケーリング:HPA(Horizontal Pod Autoscaler)やKarpenterなどのツールと組み合わせ、GPUワークロードの需要に応じて自動スケーリングできる。
  • 運用の標準化:GPUドライバのインストール、監視、障害対応などの運用作業をOperatorパターンで自動化できる。

しかし、KubernetesでGPUを適切に活用するには、GPUドライバ、Container Toolkit、Device Plugin、監視ツールなど、複数のソフトウェアコンポーネントを正確にインストール・管理する必要がある。この複雑さを解決するためにNVIDIAが提供するのがGPU Operatorである。


2. NVIDIA GPU Operatorアーキテクチャ

NVIDIA GPU Operatorは、KubernetesのOperator Frameworkを活用して、GPUノードに必要なすべてのNVIDIAソフトウェアコンポーネントを自動的にプロビジョニング・管理する。公式ドキュメントによると、GPU Operatorには以下のコンポーネントが含まれる。

2.1 コアコンポーネント

コンポーネント役割
NVIDIA GPU DriverGPUとオペレーティングシステム間のインターフェースを提供し、CUDAを有効にする。
NVIDIA Container Toolkitコンテナランタイム(containerd、CRI-O)がGPUにアクセスできるようにする。
NVIDIA Device Pluginkubelet APIを通じてGPUをKubernetesリソースとして公開する。
GPU Feature Discovery (GFD)ノードに搭載されたGPUの属性(モデル、メモリ、CUDAバージョンなど)を検出し、自動的にNodeラベルを生成する。
DCGM ExporterNVIDIA DCGM(Data Center GPU Manager)を基にGPUメトリクスをPrometheus形式で公開する。
MIG ManagerMulti-Instance GPU構成をKubernetesコントローラパターンで管理する。
GPU Direct Storage (GDS)ストレージデバイスとGPUメモリ間の直接データ転送を有効にする。

2.2 動作原理

GPU Operatorがデプロイされると、以下の順序で初期化が進行する。

  1. gpu-operator Podの起動:全コンポーネントの状態を監視・調整(reconciliation)するコントローラの役割を果たす。
  2. **Node Feature Discovery(NFD)**のデプロイ:クラスタの各ノードにPodをデプロイし、GPUの有無を検知して関連ラベルを追加する。
  3. ドライバおよびToolkitのインストール:GPUが検知されたノードにNVIDIAドライバとContainer ToolkitをDaemonSetとしてデプロイする。
  4. Device Pluginのデプロイ:GPUをnvidia.com/gpuリソースとしてkubeletに登録する。
  5. 付加コンポーネントのデプロイ:GFD、DCGM Exporter、MIG Managerなどをデプロイする。

すべてのコンポーネントはClusterPolicyというCustom Resourceによって宣言的に管理される。OperatorはClusterPolicyのdesired stateとactual stateを継続的に比較し、差異が発生すると自動的に修正する。


3. GPU Operatorのインストール

GPU OperatorはHelm Chartを通じてインストールする。公式ドキュメントのインストールガイドに基づき、ステップバイステップで確認する。

3.1 前提条件

  • kubectlhelm CLIがインストールされていること。
  • コンテナランタイムとしてcontainerdまたはCRI-Oが使用されていること。
  • GPUワークロードを実行するすべてのWorker Nodeは同一のOSバージョンであること(ドライバを別途事前インストールしない場合)。
  • Pod Security Admission(PSA)を使用する場合、Namespaceにprivilegedレベルを設定すること。

3.2 インストール手順

# 1. Namespace作成およびPSA設定
kubectl create ns gpu-operator
kubectl label --overwrite ns gpu-operator \
  pod-security.kubernetes.io/enforce=privileged

# 2. NVIDIA Helmリポジトリの追加
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm repo update

# 3. GPU Operatorのインストール(デフォルト構成)
helm install --wait --generate-name \
  -n gpu-operator --create-namespace \
  nvidia/gpu-operator \
  --version=v25.10.1

3.3 主要インストールオプション

パラメータ用途デフォルト値
driver.enabledNVIDIAドライバのデプロイ有無true
toolkit.enabledContainer Toolkitのデプロイ有無true
nfd.enabledNode Feature Discoveryのデプロイ有無true
dcgmExporter.enabledGPUテレメトリの有効化有無true
cdi.enabledContainer Device Interfaceの使用有無true
driver.version特定のドライババージョンの指定リリースにより異なる
mig.strategyMIG戦略設定(nonesinglemixednone

ホストにすでにNVIDIAドライバがインストールされている場合:

helm install --wait --generate-name \
  -n gpu-operator --create-namespace \
  nvidia/gpu-operator \
  --version=v25.10.1 \
  --set driver.enabled=false

ドライバとToolkitの両方が事前インストールされている場合:

helm install --wait --generate-name \
  -n gpu-operator --create-namespace \
  nvidia/gpu-operator \
  --version=v25.10.1 \
  --set driver.enabled=false \
  --set toolkit.enabled=false

3.4 インストール検証

インストール完了後、簡単なCUDAサンプルでGPU動作を確認できる。

apiVersion: v1
kind: Pod
metadata:
  name: cuda-vectoradd
spec:
  restartPolicy: OnFailure
  containers:
    - name: cuda-vectoradd
      image: 'nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda11.7.1-ubuntu20.04'
      resources:
        limits:
          nvidia.com/gpu: 1
kubectl apply -f cuda-vectoradd.yaml
kubectl logs pod/cuda-vectoradd
# [Vector addition of 50000 elements]
# Test PASSED

4. NVIDIA Device Pluginの詳細分析

NVIDIA Device PluginはKubernetesのDevice Plugin Frameworkを実装したコンポーネントで、GPU Operatorの中核構成要素である。

4.1 主要機能

  • GPU列挙(Enumeration):ノードに搭載されたすべてのGPUを検出し、数量をkubeletに報告する。
  • GPUヘルス監視:GPUの状態を継続的に確認し、unhealthy状態のGPUをスケジューリングから除外する。
  • GPU割り当て:Podがnvidia.com/gpuリソースを要求すると、利用可能なGPUを割り当てる。
  • リソース共有:Time-Slicing、MIGなどのGPU共有戦略をサポートする。

4.2 動作方式

Device PluginはDaemonSetとしてデプロイされ、各GPUノードで実行される。動作フローは以下の通りである。

  1. PluginがgRPCサーバーを起動し、kubeletのDevice Pluginソケットに登録する。
  2. kubeletはnvidia.com/gpuリソースの容量(capacity)をNodeオブジェクトに反映する。
  3. Podが当該リソースを要求すると、kube-schedulerが適切なノードにスケジューリングする。
  4. kubeletはDevice PluginにGPU割り当てを要求し、Pluginはコンテナに必要なデバイスファイルと環境変数を設定する。

4.3 リソース要求/制限の設定

GPUリソースはresources.limitsを通じてのみ要求できる。CPUやメモリとは異なりrequestsを別途設定できず、limitsを設定すると自動的に同じ値がrequestsとして適用される。

apiVersion: v1
kind: Pod
metadata:
  name: gpu-pod
spec:
  containers:
    - name: gpu-container
      image: nvcr.io/nvidia/pytorch:24.01-py3
      resources:
        limits:
          nvidia.com/gpu: 2 # GPU 2個を要求

重要な制約事項:

  • GPUは整数単位でのみ要求できる(nvidia.com/gpu: 0.5は不可)。
  • GPUはノード間で共有されない(1つのPodが複数のノードのGPUを同時に使用することはできない)。
  • limitsを指定しないとGPUは割り当てられない。

5. GPUリソース要求/制限の詳細

5.1 基本リソースモデル

KubernetesにおいてGPUはExtended Resourceとして扱われる。nvidia.com/gpuというリソース名で要求し、これはNVIDIA Device Pluginがkubeletに登録したものである。

resources:
  limits:
    nvidia.com/gpu: 1 # GPU 1個を専用割り当て
    memory: '16Gi' # GPUとは別にシステムメモリも設定
    cpu: '4'

5.2 ResourceQuotaによるGPU制限

マルチテナント環境でNamespaceごとのGPU使用量を制限できる。

apiVersion: v1
kind: ResourceQuota
metadata:
  name: gpu-quota
  namespace: team-ml
spec:
  hard:
    requests.nvidia.com/gpu: '4' # 最大4 GPU
    limits.nvidia.com/gpu: '4'

5.3 LimitRangeによるデフォルト値の設定

apiVersion: v1
kind: LimitRange
metadata:
  name: gpu-limit-range
  namespace: team-ml
spec:
  limits:
    - type: Container
      default:
        nvidia.com/gpu: '1'
      defaultRequest:
        nvidia.com/gpu: '1'
      max:
        nvidia.com/gpu: '2'

6. GPU共有戦略:MIG(Multi-Instance GPU)

6.1 MIGの概要

Multi-Instance GPU(MIG)は、NVIDIA Ampereアーキテクチャ以上のGPU(A100、A30、H100など)でサポートされるハードウェアレベルのGPUパーティショニング技術である。単一のGPUを最大7つの独立したGPUインスタンスに分割でき、各インスタンスは専用のコンピューティングリソース、メモリ、キャッシュを持つ。

MIGの中核的な利点はハードウェアレベルの分離である。各MIGインスタンスは独立したメモリ空間と障害分離を提供するため、1つのインスタンスの障害が他のインスタンスに影響を与えない。

6.2 MIG戦略

GPU Operatorは2つのMIG戦略をサポートする。

  • Single Strategy:ノードのすべてのGPUが同一のMIG構成を持つ。リソース名はnvidia.com/gpuのまま維持される。
  • Mixed Strategy:一部のGPUはMIGモード、残りはFull GPUモードで運用できる。MIGインスタンスはnvidia.com/mig-<slice>形式の別リソースとして公開される。

6.3 MIGのインストールと構成

MIGを有効にしてGPU Operatorをインストールする。

helm install --wait --generate-name \
  -n gpu-operator --create-namespace \
  nvidia/gpu-operator \
  --version=v25.10.1 \
  --set mig.strategy=single

事前定義されたMIGプロファイルをノードに適用する。

# ノードにMIG構成ラベルを適用
kubectl label nodes gpu-node-01 \
  nvidia.com/mig.config=all-1g.10gb --overwrite

主要な事前定義プロファイル:

プロファイル説明
all-1g.10gbすべてのGPUを1g.10gbインスタンスに分割
all-3g.40gbすべてのGPUを3g.40gbインスタンスに分割
all-balancedさまざまなサイズのインスタンスを混合配置
all-disabledMIGモードを無効化

6.4 カスタムMIG構成

デフォルトプロファイル以外にユーザー定義の構成も可能である。

apiVersion: v1
kind: ConfigMap
metadata:
  name: custom-mig-config
  namespace: gpu-operator
data:
  config.yaml: |
    version: v1
    mig-configs:
      custom-profile:
        - devices: all
          mig-enabled: true
          mig-devices:
            "1g.10gb": 5
            "2g.20gb": 1

カスタムConfigMapをClusterPolicyに連携する。

kubectl patch clusterpolicies.nvidia.com/cluster-policy \
  --type='json' \
  -p='[{"op":"replace","path":"/spec/migManager/config/name","value":"custom-mig-config"}]'

構成状態を確認する。

kubectl get node gpu-node-01 -o=jsonpath='{.metadata.labels}' | jq .
# "nvidia.com/mig.config.state": "success" を確認

6.5 MIGリソースの使用

MIGインスタンスを使用するPodは次のようにリソースを要求する。

apiVersion: v1
kind: Pod
metadata:
  name: mig-workload
spec:
  containers:
    - name: cuda-app
      image: nvcr.io/nvidia/pytorch:24.01-py3
      resources:
        limits:
          nvidia.com/mig-1g.10gb: 1 # 1g.10gb MIGインスタンス1個を要求

7. GPU Time-Slicingの設定

7.1 Time-Slicingの概要

Time-Slicingは、NVIDIA GPUの時分割スケジューラを活用して、1つのGPUを複数のPodが時間的に共有する方式である。MIGとは異なりメモリ分離や障害分離は提供されないが、MIGをサポートしない旧型GPU(T4、V100など)でも使用でき、GPUをより多くのユーザー/ワークロードと共有できるという利点がある。

7.2 ConfigMapの構成

Time-SlicingはConfigMapを通じて設定する。

apiVersion: v1
kind: ConfigMap
metadata:
  name: time-slicing-config
  namespace: gpu-operator
data:
  any: |-
    version: v1
    flags:
      migStrategy: none
    sharing:
      timeSlicing:
        renameByDefault: false
        failRequestsGreaterThanOne: false
        resources:
          - name: nvidia.com/gpu
            replicas: 4

主要な設定フィールド:

フィールド説明
renameByDefaultbooleantrueの場合、リソースをnvidia.com/gpu.sharedとしてアドバタイズする。falseの場合、productラベルに-SHAREDサフィックスを追加する。
failRequestsGreaterThanOneboolean1つのPodが1個以上のGPUレプリカを要求することを拒否する。trueの設定を推奨。
resources.namestringリソース名(nvidia.com/gpuなど)
resources.replicasintegerGPU当たりのTime-Sliceレプリカ数

7.3 クラスタへの適用

クラスタ全体に適用:

kubectl apply -f time-slicing-config.yaml

kubectl patch clusterpolicies.nvidia.com/cluster-policy \
  -n gpu-operator --type merge \
  -p '{"spec":{"devicePlugin":{"config":{"name":"time-slicing-config","default":"any"}}}}'

特定のノードにのみ適用:

# ConfigMapにGPUモデルごとの設定を定義した場合
kubectl patch clusterpolicies.nvidia.com/cluster-policy \
  -n gpu-operator --type merge \
  -p '{"spec":{"devicePlugin":{"config":{"name":"time-slicing-config"}}}}'

# 対象ノードにラベルを適用
kubectl label node gpu-node-01 \
  nvidia.com/device-plugin.config=tesla-t4

7.4 適用結果の確認

Time-Slicingが適用されると、ノードのラベルとallocatableリソースが変更される。

kubectl get node gpu-node-01 -o jsonpath='{.status.allocatable}' | jq .
# "nvidia.com/gpu": "4"  (物理GPU 1個 * レプリカ数 4)

kubectl get node gpu-node-01 --show-labels | grep nvidia
# nvidia.com/gpu.replicas=4
# nvidia.com/gpu.product=Tesla-T4-SHARED

7.5 主要な制約事項

  • メモリ/障害分離なし:Time-Sliceレプリカ間でGPUメモリが共有され、1つのプロセスの障害が他のプロセスに影響を与える可能性がある。
  • 比例的なコンピューティング保証なし:複数のGPUレプリカを要求しても、比例的により多くのコンピューティングパワーが保証されるわけではない。
  • DCGM Exporterの制限:GPU Time-Slicingが有効な場合、メトリクスを個別のコンテナに関連付けることはサポートされない。
  • ConfigMap変更時に手動再起動が必要:OperatorはConfigMapの変更を自動検知しないため、手動でDaemonSetを再起動する必要がある。
kubectl rollout restart -n gpu-operator \
  daemonset/nvidia-device-plugin-daemonset

8. MPS(Multi-Process Service)の設定

8.1 MPSの概要

NVIDIA MPS(Multi-Process Service)は、複数のCUDAプロセスが単一のGPU上で同時に実行できるようにするクライアント-サーバーアーキテクチャである。従来のCUDAコンテキストスイッチングのオーバーヘッドを削減し、複数プロセスのCUDAカーネルを1つのGPUコンテキストにマルチプレクシングして、GPU使用率を向上させる。

8.2 MIG vs Time-Slicing vs MPSの比較

特性MIGTime-SlicingMPS
メモリ分離あり(ハードウェア)なし部分的(ソフトウェア)
障害分離ありなしなし
対応GPUAmpere以上すべてのNVIDIA GPUVolta以上推奨
最大パーティション数7無制限48(Pre-Volta: 16)
カーネル同時実行ありなし(時分割)あり
パーティションの柔軟性固定プロファイル均等分割任意サイズ

8.3 MPSの長所と短所

長所:

  • MIGとは異なり、任意サイズのGPUスライスを作成できる。
  • Time-Slicingとは異なり、メモリ割り当て制限を強制でき、OOMエラーを軽減できる。
  • 複数プロセスのCUDAカーネルが実際に同時に実行されるため、GPU使用率が高い。

短所:

  • 障害分離が提供されない。1つのクライアントプロセスのクラッシュがGPUリセットを引き起こし、他のすべてのプロセスに影響を与える可能性がある。
  • メモリ保護が完全ではない。

8.4 KubernetesでのMPS活用

現在、NVIDIA Device PluginはMPSを直接サポートしていないが、NVIDIAのDRA(Dynamic Resource Allocation)ドライバを通じてMPSを構成できる。または、MPSをサポートする別のDevice Pluginをインストールして使用できる。

GKE(Google Kubernetes Engine)など一部のマネージドKubernetesサービスではMPSをネイティブにサポートしている。

# GKEでのMPS使用例
apiVersion: v1
kind: Pod
metadata:
  name: mps-workload
spec:
  containers:
    - name: cuda-app
      image: nvcr.io/nvidia/pytorch:24.01-py3
      resources:
        limits:
          nvidia.com/gpu: 1

一般的なオンプレミスKubernetes環境でMPSを使用するには、MPS Control DaemonをサイドカーパターンまたはDaemonSetとしてデプロイし、CUDA_MPS_PIPE_DIRECTORYCUDA_MPS_LOG_DIRECTORY環境変数を設定する必要がある。


9. Node Affinity、Taint/TolerationによるGPUノード分離

GPUノードは高価なリソースであるため、GPUが不要なワークロードがGPUノードにスケジューリングされることを防ぐ必要がある。KubernetesのTaint/TolerationとNode Affinityを組み合わせてこれを実現する。

9.1 GPUノードへのTaint適用

# GPUノードにTaintを追加
kubectl taint nodes gpu-node-01 \
  nvidia.com/gpu=present:NoSchedule

kubectl taint nodes gpu-node-02 \
  nvidia.com/gpu=present:NoSchedule

このTaintが適用されると、対応するTolerationを持たないPodはGPUノードにスケジューリングされない。

9.2 GPUワークロードへのToleration追加

apiVersion: v1
kind: Pod
metadata:
  name: gpu-training-job
spec:
  tolerations:
    - key: 'nvidia.com/gpu'
      operator: 'Equal'
      value: 'present'
      effect: 'NoSchedule'
  containers:
    - name: training
      image: nvcr.io/nvidia/pytorch:24.01-py3
      resources:
        limits:
          nvidia.com/gpu: 1

9.3 Node Affinityによる特定GPUモデルの選択

GPU Feature Discoveryが生成したラベルを活用して、特定のGPUモデルが搭載されたノードにのみワークロードをスケジューリングできる。

apiVersion: v1
kind: Pod
metadata:
  name: a100-training
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
              - key: nvidia.com/gpu.product
                operator: In
                values:
                  - 'A100-SXM4-80GB'
                  - 'A100-SXM4-40GB'
              - key: nvidia.com/gpu.memory
                operator: Gt
                values:
                  - '40000'
  tolerations:
    - key: 'nvidia.com/gpu'
      operator: 'Equal'
      value: 'present'
      effect: 'NoSchedule'
  containers:
    - name: llm-training
      image: nvcr.io/nvidia/pytorch:24.01-py3
      command: ['python', 'train.py']
      resources:
        limits:
          nvidia.com/gpu: 4

9.4 本番戦略:Taint + Affinityの組み合わせ

GPUノード管理のベストプラクティスは、TaintでGPU以外のワークロードをブロックし、Node AffinityでGPUワークロードを適切なノードに誘導する二重戦略である。

  • Taint:GPUノードにアクセスできるPodを制限する「ハード」制約
  • Node Affinity:Podが望むGPU仕様のノードに配置されるようにする「ソフト」または「ハード」の優先設定

TolerationはPodがTaintされたノードにスケジューリングされることを許可するだけで、そのノードを強制するわけではない。そのため、Node Affinityと必ず併用して、GPUワークロードが正確にGPUノードにのみ配置されるようにする必要がある。


10. DCGM Exporter + Prometheus + Grafana監視

10.1 DCGM Exporterの概要

DCGM Exporterは、NVIDIA Data Center GPU Manager(DCGM)のGo APIを使用してGPUテレメトリデータを収集し、Prometheus形式で公開するコンポーネントである。GPU Operatorをインストールすると、デフォルトでDCGM ExporterがDaemonSetとしてデプロイされる。

主要な収集メトリクス:

メトリクス説明
DCGM_FI_DEV_GPU_UTILGPU使用率(%)
DCGM_FI_DEV_MEM_COPY_UTILメモリコピー使用率(%)
DCGM_FI_DEV_FB_USEDFramebuffer使用メモリ(MB)
DCGM_FI_DEV_FB_FREEFramebuffer空きメモリ(MB)
DCGM_FI_DEV_GPU_TEMPGPU温度(C)
DCGM_FI_DEV_POWER_USAGE消費電力(W)
DCGM_FI_DEV_SM_CLOCKSM Clockの周波数(MHz)
DCGM_FI_DEV_PCIE_TX_THROUGHPUTPCIe TXスループット
DCGM_FI_DEV_PCIE_RX_THROUGHPUTPCIe RXスループット

10.2 Prometheusスタックのインストール

kube-prometheus-stackを使用してPrometheusとGrafanaを一緒にデプロイする。

# PrometheusコミュニティHelmリポジトリの追加
helm repo add prometheus-community \
  https://prometheus-community.github.io/helm-charts
helm repo update

GPUメトリクス収集用のvaluesファイルを作成する。

# kube-prometheus-stack-values.yaml
prometheus:
  service:
    type: NodePort
    nodePort: 30090
  prometheusSpec:
    serviceMonitorSelectorNilUsesHelmValues: false
    additionalScrapeConfigs:
      - job_name: gpu-metrics
        scrape_interval: 1s
        metrics_path: /metrics
        scheme: http
        kubernetes_sd_configs:
          - role: endpoints
            namespaces:
              names:
                - gpu-operator
        relabel_configs:
          - source_labels: [__meta_kubernetes_pod_node_name]
            action: replace
            target_label: kubernetes_node

grafana:
  service:
    type: NodePort
    nodePort: 32322
helm install prometheus-community/kube-prometheus-stack \
  --create-namespace --namespace prometheus \
  --generate-name \
  --values kube-prometheus-stack-values.yaml

10.3 Grafanaダッシュボードの構成

NVIDIA公式DCGM Exporterダッシュボードをインポートする。

  1. Grafanaにアクセスする(http://<node-ip>:32322)。
  2. Dashboards > Importに移動する。
  3. Dashboard ID 12239を入力する(NVIDIA DCGM Exporter Dashboard)。
  4. Data SourceとしてPrometheusを選択する。

このダッシュボードはGPU使用率、メモリ使用量、温度、消費電力などをリアルタイムで可視化する。MIGとNon-MIG GPUの両方をサポートするダッシュボードはID 23382を使用する。

10.4 アラート設定例

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: gpu-alerts
  namespace: prometheus
spec:
  groups:
    - name: gpu.rules
      rules:
        - alert: GPUHighTemperature
          expr: DCGM_FI_DEV_GPU_TEMP > 85
          for: 5m
          labels:
            severity: warning
          annotations:
            summary: 'GPU temperature is high on {{ $labels.kubernetes_node }}'
            description: 'GPU {{ $labels.gpu }} temperature is {{ $value }}C'
        - alert: GPUMemoryAlmostFull
          expr: (DCGM_FI_DEV_FB_USED / (DCGM_FI_DEV_FB_USED + DCGM_FI_DEV_FB_FREE)) > 0.95
          for: 5m
          labels:
            severity: critical
          annotations:
            summary: 'GPU memory usage above 95% on {{ $labels.kubernetes_node }}'
        - alert: GPUHighUtilization
          expr: DCGM_FI_DEV_GPU_UTIL > 95
          for: 30m
          labels:
            severity: info
          annotations:
            summary: 'Sustained high GPU utilization on {{ $labels.kubernetes_node }}'

11. GPU Feature Discoveryの活用

11.1 概要

GPU Feature Discovery(GFD)は、ノードに搭載されたGPUの属性を自動的に検出し、Kubernetes Nodeラベルを生成するコンポーネントである。Node Feature Discovery(NFD)を基盤に動作し、GPU Operatorに含まれて自動デプロイされる。

11.2 生成されるラベル一覧

ラベル説明値の例
nvidia.com/gpu.productGPUモデル名Tesla-T4A100-SXM4-80GB
nvidia.com/gpu.memoryGPUメモリ容量(MB)40960
nvidia.com/gpu.countGPU数量4
nvidia.com/gpu.familyGPUアーキテクチャファミリーamperehopper
nvidia.com/gpu.compute.majorCUDA Compute Capability(Major)8
nvidia.com/gpu.compute.minorCUDA Compute Capability(Minor)0
nvidia.com/cuda.driver.majorCUDAドライバMajorバージョン535
nvidia.com/cuda.driver.minorCUDAドライバMinorバージョン129
nvidia.com/cuda.runtime.majorCUDA Runtime Majorバージョン12
nvidia.com/cuda.runtime.minorCUDA Runtime Minorバージョン2
nvidia.com/gpu.machineマシンタイプ(クラウドではインスタンスタイプ)p4d.24xlarge
nvidia.com/gpu.replicasGPUレプリカ数(共有時)4
nvidia.com/mig.strategyMIG戦略singlemixed

11.3 ラベル活用例

GFDラベルを活用すると、GPUの仕様に基づいたきめ細かなスケジューリングが可能になる。

# Hopperアーキテクチャ GPUでのみ実行
apiVersion: batch/v1
kind: Job
metadata:
  name: h100-inference
spec:
  template:
    spec:
      nodeSelector:
        nvidia.com/gpu.family: hopper
      containers:
        - name: inference
          image: nvcr.io/nvidia/tritonserver:24.01-py3
          resources:
            limits:
              nvidia.com/gpu: 1
      restartPolicy: Never
# 80GB以上のGPUメモリが必要な大規模モデル学習
apiVersion: batch/v1
kind: Job
metadata:
  name: large-model-training
spec:
  template:
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: nvidia.com/gpu.memory
                    operator: Gt
                    values:
                      - '79000'
                  - key: nvidia.com/gpu.count
                    operator: Gt
                    values:
                      - '7'
      containers:
        - name: training
          image: nvcr.io/nvidia/pytorch:24.01-py3
          resources:
            limits:
              nvidia.com/gpu: 8
      restartPolicy: Never

12. 本番YAML例とトラブルシューティング

12.1 PyTorch分散学習Job

apiVersion: batch/v1
kind: Job
metadata:
  name: distributed-training
spec:
  parallelism: 2
  completions: 2
  template:
    metadata:
      labels:
        app: distributed-training
    spec:
      tolerations:
        - key: 'nvidia.com/gpu'
          operator: 'Equal'
          value: 'present'
          effect: 'NoSchedule'
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: nvidia.com/gpu.product
                    operator: In
                    values:
                      - 'A100-SXM4-80GB'
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchExpressions:
                    - key: app
                      operator: In
                      values:
                        - distributed-training
                topologyKey: kubernetes.io/hostname
      containers:
        - name: pytorch-trainer
          image: nvcr.io/nvidia/pytorch:24.01-py3
          command:
            - torchrun
            - --nproc_per_node=4
            - --nnodes=2
            - train.py
          resources:
            limits:
              nvidia.com/gpu: 4
              memory: '64Gi'
              cpu: '16'
            requests:
              memory: '64Gi'
              cpu: '16'
          env:
            - name: NCCL_DEBUG
              value: 'INFO'
          volumeMounts:
            - name: dshm
              mountPath: /dev/shm
            - name: training-data
              mountPath: /data
      volumes:
        - name: dshm
          emptyDir:
            medium: Memory
            sizeLimit: '16Gi'
        - name: training-data
          persistentVolumeClaim:
            claimName: training-data-pvc
      restartPolicy: Never
  backoffLimit: 3

注意事項:PyTorch分散学習で/dev/shm(共有メモリ)のサイズが不足すると、DataLoadernum_workers > 0設定時にクラッシュが発生する可能性がある。emptyDirをMemory mediumでマウントし、十分なサイズを割り当てる必要がある。

12.2 Triton Inference Serverのデプロイ

apiVersion: apps/v1
kind: Deployment
metadata:
  name: triton-inference
spec:
  replicas: 2
  selector:
    matchLabels:
      app: triton-inference
  template:
    metadata:
      labels:
        app: triton-inference
    spec:
      tolerations:
        - key: 'nvidia.com/gpu'
          operator: 'Equal'
          value: 'present'
          effect: 'NoSchedule'
      nodeSelector:
        nvidia.com/gpu.family: ampere
      containers:
        - name: triton
          image: nvcr.io/nvidia/tritonserver:24.01-py3
          args:
            - tritonserver
            - --model-repository=/models
            - --strict-model-config=false
          ports:
            - containerPort: 8000
              name: http
            - containerPort: 8001
              name: grpc
            - containerPort: 8002
              name: metrics
          resources:
            limits:
              nvidia.com/gpu: 1
              memory: '16Gi'
              cpu: '4'
          readinessProbe:
            httpGet:
              path: /v2/health/ready
              port: 8000
            initialDelaySeconds: 30
            periodSeconds: 10
          livenessProbe:
            httpGet:
              path: /v2/health/live
              port: 8000
            initialDelaySeconds: 30
            periodSeconds: 15
          volumeMounts:
            - name: model-store
              mountPath: /models
      volumes:
        - name: model-store
          persistentVolumeClaim:
            claimName: model-store-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: triton-inference
spec:
  selector:
    app: triton-inference
  ports:
    - name: http
      port: 8000
      targetPort: 8000
    - name: grpc
      port: 8001
      targetPort: 8001
    - name: metrics
      port: 8002
      targetPort: 8002

12.3 トラブルシューティングガイド

GPUがノードで認識されない場合

# 1. GPU Operator Podの状態確認
kubectl get pods -n gpu-operator

# 2. ドライバPodのログ確認
kubectl logs -n gpu-operator -l app=nvidia-driver-daemonset

# 3. Device Plugin Podのログ確認
kubectl logs -n gpu-operator -l app=nvidia-device-plugin-daemonset

# 4. ノードのallocatableリソース確認
kubectl describe node gpu-node-01 | grep -A 5 "Allocatable"

# 5. NFDラベルの確認
kubectl get node gpu-node-01 -o json | \
  jq '.metadata.labels | to_entries[] | select(.key | startswith("nvidia"))'

PodがGPUノードにスケジューリングされない場合

# 1. Podイベントの確認
kubectl describe pod <pod-name>
# "Insufficient nvidia.com/gpu"メッセージを確認

# 2. ノードのGPU割り当て状態の確認
kubectl describe node gpu-node-01 | grep -A 3 "Allocated resources"

# 3. GPUを使用中のPodの一覧確認
kubectl get pods --all-namespaces -o json | \
  jq '.items[] | select(.spec.containers[].resources.limits["nvidia.com/gpu"] != null) | .metadata.name'

MIG構成が適用されない場合

# 1. MIG Managerのログ確認
kubectl logs -n gpu-operator -l app=nvidia-mig-manager

# 2. MIG構成状態ラベルの確認
kubectl get node gpu-node-01 -o jsonpath='{.metadata.labels.nvidia\.com/mig\.config\.state}'
# "success"でなければ構成失敗

# 3. GPUモードの確認(ノード上で)
nvidia-smi -L
nvidia-smi --query-gpu=mig.mode.current --format=csv

Time-Slicing適用後にGPU数が変更されない場合

# 1. ConfigMapの内容確認
kubectl get configmap -n gpu-operator time-slicing-config -o yaml

# 2. Device Pluginの再起動
kubectl rollout restart -n gpu-operator \
  daemonset/nvidia-device-plugin-daemonset

# 3. 再起動後のノードリソース確認
kubectl get node gpu-node-01 -o jsonpath='{.status.allocatable.nvidia\.com/gpu}'

References