- はじめに
- DRAアーキテクチャ概要
- DRAドライバのインストールと設定
- DeviceClassの定義とGPUティア管理
- ResourceClaimベースのPodスケジューリング
- マルチクラウドDRA比較 (AKS vs GKE vs EKS)
- 既存のExtended ResourceモデルからDRAへのマイグレーション
- 運用時の注意事項とモニタリング
- 障害事例と復旧手順
- プロダクションデプロイのチェックリスト
- 参考資料

はじめに
KubernetesでGPUのようなハードウェアアクセラレータをスケジューリングすることは、長らく運用者にとって難題でした。従来のExtended Resourceモデルはnvidia.com/gpu: 1のように単純な整数カウント方式でGPUを割り当てていたため、GPUの詳細な属性(VRAM容量、MIGパーティション、特定のモデル)を基準にスケジューリングすることが根本的に不可能でした。
この問題を解決するためにKubernetes 1.26でアルファとして導入され、1.31で大幅に再設計されて1.32でベータに昇格したDRA(Dynamic Resource Allocation)は、GPU/FPGA/ネットワークデバイスなど複雑なハードウェアリソースを構造化された方式で要求し割り当てられるフレームワークです。
従来のExtended Resourceモデルの限界
従来のモデルでのGPU割り当ては次のように行われていました:
apiVersion: v1
kind: Pod
metadata:
name: gpu-training-legacy
spec:
containers:
- name: trainer
image: nvcr.io/nvidia/pytorch:24.01-py3
resources:
limits:
nvidia.com/gpu: 2
この方式にはいくつかの根本的な限界があります:
- 属性ベースの選択が不可能: A100 80GBとT4 16GBを区別できません。単に「GPU 2個」を要求するだけで、どの種類のGPUなのかを明示する方法がありません。
- 部分割り当てが不可能: NVIDIA MIG(Multi-Instance GPU)技術でA100を7個の独立インスタンスに分割できますが、Extended Resourceモデルではこれを細かく表現することが困難です。
- デバイス初期化の制御が不在: GPUをコンテナに渡す前にMPS(Multi-Process Service)設定や特定のドライバモードを適用する手順を標準化できません。
- デバイス間のトポロジーを無視: NVLinkで接続されたGPUのペアをまとめて割り当てられることが性能上重要ですが、従来のモデルはこれを考慮しません。
DRAはこれらすべての限界を解消し、GPUワークロードのスケジューリング品質を根本的に改善します。この記事ではDRAのアーキテクチャから実践的なデプロイ、運用トラブルシューティングまで体系的に扱います。
DRAアーキテクチャ概要
DRAはKubernetesのresource.k8s.io/v1beta1(1.32基準)APIグループに属し、次の4つの中核リソースで構成されます。
中核リソースの構造
DeviceClass: デバイスの種類を定義します。GPUモデルごとにDeviceClassを作成することで、ワークロードが特定のGPUタイプを要求できるようになります。ストレージのStorageClassと類似した役割を果たします。
ResourceClaim: 実際のデバイス割り当て要求を表します。PersistentVolumeClaimがストレージを要求するのと同じように、ResourceClaimは特定のDeviceClassのデバイスを要求します。Podのライフサイクルとは独立して存在できるため、デバイスを複数のPod間で共有したり、Podの再起動時にも同一のデバイスを維持したりできます。
ResourceClaimTemplate: Pod作成時に自動でResourceClaimを生成するためのテンプレートです。Podごとに専用のResourceClaimが必要な場合に使用します。
ResourceSlice: ノードにインストールされたDRAドライバがAPIサーバーへ報告するデバイスの一覧です。スケジューラはResourceSliceを参照して、どのノードにどのデバイスが利用可能かを把握します。
スケジューリングフロー
DRAベースのスケジューリングは次のような段階で進みます:
- Podの提出: ユーザーがResourceClaimを参照するPodを作成します。
- スケジューラのフィルタリング: kube-schedulerがResourceSliceの情報を基に、要求されたDeviceClassのデバイスが利用可能なノードをフィルタリングします。
- 構造化パラメータのマッチング: スケジューラがResourceClaimの要件と各ノードの利用可能なデバイスを直接マッチングします。これがDRAの「Structured Parameters」モデルの中核です。
- 割り当ての決定: スケジューラが特定のノードの特定のデバイスをResourceClaimに割り当てます。
- デバイスの準備: 該当ノードのDRAドライバ(kubeletプラグイン)が、割り当てられたデバイスをコンテナが使用できるように準備します (CDIデバイス設定など)。
- コンテナの起動: kubeletが準備されたデバイスとともにコンテナを起動します。
従来のDevice Plugin方式とは異なり、DRAではスケジューラが直接デバイスの属性を理解し、最適な配置を決定します。これはDevice Pluginが単に「利用可能な個数」だけを報告していたのとは根本的に異なるアプローチです。
DRAドライバのインストールと設定
事前要件
DRAを使用するにはKubernetes 1.32以上が必要で、DynamicResourceAllocationフィーチャーゲートが有効になっている必要があります。Kubernetes 1.32ではベータ状態のため、デフォルトで有効になっています。
# クラスタバージョンの確認
kubectl version --short
# DRAフィーチャーゲート有効化の確認 (kube-apiserver, kube-scheduler, kubelet すべてに必要)
# kubeadmベースのクラスタの場合はClusterConfigurationで設定
kubectl get configmap -n kube-system kubeadm-config -o yaml | grep -A 5 "featureGates"
# DRA関連のAPIリソース確認
kubectl api-resources | grep resource.k8s.io
# 出力例:
# 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
NVIDIA DRAドライバのインストール
NVIDIAは公式のDRAドライバであるnvidia-dra-driverを提供しています。従来のk8s-device-pluginとは別のプロジェクトであり、DRAの構造化パラメータモデルを完全にサポートします。
# NVIDIA DRAドライバのHelmチャートリポジトリを追加
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm repo update
# nvidia-dra-driver のインストール
# 既存のNVIDIA GPU Operatorがインストールされている場合、device-pluginは無効にする必要があります
helm install nvidia-dra-driver nvidia/nvidia-dra-driver \
--namespace nvidia-dra-driver \
--create-namespace \
--set controller.enabled=true \
--set kubeletPlugin.enabled=true \
--version v0.8.0
# インストールの確認
kubectl get pods -n nvidia-dra-driver
# NAME READY STATUS RESTARTS AGE
# nvidia-dra-driver-controller-7d8f9b6c4d-k2xvn 1/1 Running 0 2m
# nvidia-dra-driver-kubelet-plugin-node1-abcde 1/1 Running 0 2m
# nvidia-dra-driver-kubelet-plugin-node2-fghij 1/1 Running 0 2m
# ResourceSlice生成の確認 - ドライバがノードのGPU情報を報告
kubectl get resourceslices -o wide
# NAME DRIVER NODE POOL DEVICES
# gpu-node1-nvidia-gpu-slice-0 gpu.nvidia.com node1 nvidia-gpu 4
# gpu-node2-nvidia-gpu-slice-0 gpu.nvidia.com node2 nvidia-gpu 8
ResourceSliceの詳細確認
ドライバが正常にインストールされると、各GPUノードのデバイス情報がResourceSliceとして報告されます。これによりスケジューラは各GPUの詳細な属性を把握できます。
# 特定ノードのResourceSliceの詳細を表示
kubectl get resourceslice gpu-node1-nvidia-gpu-slice-0 -o yaml
出力例を見ると、各GPUについてモデル名、VRAM、UUID、アーキテクチャ、MIGサポートの有無など豊富な属性が報告されていることを確認できます。これらの属性こそがDeviceClassとResourceClaimでフィルタリング条件として活用されます。
DeviceClassの定義とGPUティア管理
GPUモデル別のDeviceClass定義
DeviceClassはStorageClassと同様にデバイスの「クラス」を定義します。クラスタ管理者があらかじめ定義しておけば、ワークロード開発者は単にDeviceClassの名前を参照するだけで目的のGPUを要求できます。
# gpu-deviceclasses.yaml
apiVersion: resource.k8s.io/v1beta1
kind: DeviceClass
metadata:
name: gpu.nvidia.com-a100
spec:
selectors:
- cel:
expression: "device.driver == 'gpu.nvidia.com' && device.attributes['gpu.nvidia.com'].productName == 'NVIDIA A100 80GB PCIe'"
config:
- opaque:
driver: gpu.nvidia.com
parameters:
apiVersion: gpu.nvidia.com/v1alpha1
kind: GpuConfig
sharing:
strategy: TimeSlicing
timeSlicingConfig:
interval: Long
---
apiVersion: resource.k8s.io/v1beta1
kind: DeviceClass
metadata:
name: gpu.nvidia.com-h100
spec:
selectors:
- cel:
expression: "device.driver == 'gpu.nvidia.com' && device.attributes['gpu.nvidia.com'].productName == 'NVIDIA H100 80GB HBM3'"
config:
- opaque:
driver: gpu.nvidia.com
parameters:
apiVersion: gpu.nvidia.com/v1alpha1
kind: GpuConfig
sharing:
strategy: TimeSlicing
timeSlicingConfig:
interval: Short
---
apiVersion: resource.k8s.io/v1beta1
kind: DeviceClass
metadata:
name: gpu.nvidia.com-a100-mig-3g20gb
spec:
selectors:
- cel:
expression: >-
device.driver == 'gpu.nvidia.com' &&
device.attributes['gpu.nvidia.com'].productName == 'NVIDIA A100 80GB PCIe' &&
device.attributes['gpu.nvidia.com'].migProfile == '3g.20gb'
上の例では3つのDeviceClassを定義しました:
- gpu.nvidia.com-a100: A100 80GB GPU全体をTime-Slicingモードで割り当て
- gpu.nvidia.com-h100: H100 80GB GPUを短期Time-Slicingで割り当て
- gpu.nvidia.com-a100-mig-3g20gb: A100のMIG 3g.20gbプロファイル(20GB VRAM、3個のコンピュートスライス)を割り当て
MIGパーティショニング戦略
NVIDIA A100/H100でMIGを活用すると、1枚の物理GPUを複数の独立インスタンスに分割して利用率を最大化できます。DRAではMIGプロファイルごとにDeviceClassを定義することで、きめ細かいGPUリソース管理が可能です。
| MIGプロファイル | コンピュートスライス | VRAM | 最大インスタンス(A100基準) | 主な用途 |
|---|---|---|---|---|
| 1g.5gb | 1/7 | 5GB | 7個 | 推論(小型モデル)、開発/テスト |
| 1g.10gb | 1/7 | 10GB | 7個 | 推論(中型モデル) |
| 2g.10gb | 2/7 | 10GB | 3個 | 小規模学習、バッチ推論 |
| 3g.20gb | 3/7 | 20GB | 2個 | 中規模学習、ファインチューニング |
| 4g.40gb | 4/7 | 40GB | 1個 | 大規模学習 |
| 7g.80gb | 7/7 | 80GB | 1個 | GPU全体 (MIG未使用と同一) |
A100 vs H100 スペック比較
DeviceClassを設計する際はGPUモデルの特性を正確に理解することが重要です。
| 項目 | NVIDIA A100 80GB | NVIDIA H100 80GB |
|---|---|---|
| アーキテクチャ | Ampere | Hopper |
| FP16性能 | 312 TFLOPS | 989 TFLOPS |
| FP8性能 | 非対応 | 1,979 TFLOPS |
| VRAM | 80GB HBM2e | 80GB HBM3 |
| メモリ帯域幅 | 2 TB/s | 3.35 TB/s |
| NVLink帯域幅 | 600 GB/s | 900 GB/s |
| MIG最大インスタンス | 7個 | 7個 |
| TDP | 300W | 700W |
| DRAドライバ対応 | nvidia-dra-driver v0.6+ | nvidia-dra-driver v0.7+ |
H100はFP8演算とTransformer EngineによってLLMの学習/推論性能がA100比で3倍以上向上するため、LLMワークロードにはH100 DeviceClassを優先的に割り当てるポリシーを策定するのがよいでしょう。
ResourceClaimベースのPodスケジューリング
基本的なResourceClaimの利用
ResourceClaimを直接作成し、Podから参照する方式です。デバイスをPodのライフサイクルとは独立して管理する場合や、複数のPodで共有する必要がある場合に使用します。
# 独立したResourceClaimの作成
apiVersion: resource.k8s.io/v1beta1
kind: ResourceClaim
metadata:
name: training-gpu-claim
namespace: ml-workloads
spec:
devices:
requests:
- name: gpu
deviceClassName: gpu.nvidia.com-a100
count: 4
constraints:
- requests: ['gpu']
matchAttribute: 'gpu.nvidia.com/nvlinkInterconnect'
---
# ResourceClaimを参照するPod
apiVersion: v1
kind: Pod
metadata:
name: distributed-training
namespace: ml-workloads
spec:
containers:
- name: trainer
image: nvcr.io/nvidia/pytorch:24.01-py3
command: ['torchrun', '--nproc_per_node=4', 'train.py']
resources:
claims:
- name: training-gpus
resourceClaims:
- name: training-gpus
resourceClaimName: training-gpu-claim
restartPolicy: Never
上の例で注目すべき点はconstraintsフィールドです。matchAttributeを使用して、4個のA100 GPUがNVLinkで相互接続された状態で割り当てられるように制約条件を設定しました。これは分散学習時のGPU間通信性能に決定的な影響を与えます。
ResourceClaimTemplateの利用
JobやDeploymentのように複数のPodを生成するワークロードでは、ResourceClaimTemplateを使用して各Podごとに専用のResourceClaimが自動生成されるようにします。
# MIGベースの推論サービスのデプロイ
apiVersion: apps/v1
kind: Deployment
metadata:
name: llm-inference-service
namespace: ml-workloads
spec:
replicas: 6
selector:
matchLabels:
app: llm-inference
template:
metadata:
labels:
app: llm-inference
spec:
containers:
- name: inference-server
image: nvcr.io/nvidia/tritonserver:24.01-py3
ports:
- containerPort: 8000
name: http
- containerPort: 8001
name: grpc
resources:
claims:
- name: inference-gpu
resourceClaims:
- name: inference-gpu
resourceClaimTemplateName: mig-inference-template
---
apiVersion: resource.k8s.io/v1beta1
kind: ResourceClaimTemplate
metadata:
name: mig-inference-template
namespace: ml-workloads
spec:
spec:
devices:
requests:
- name: mig-gpu
deviceClassName: gpu.nvidia.com-a100-mig-3g20gb
count: 1
この構成では6個のTriton Inference Serverレプリカがそれぞれ A100 の MIG 3g.20gb スライスを1個ずつ割り当てられます。物理A100 2枚で6個の推論インスタンスを運用できるため、従来のExtended ResourceモデルでGPU 2枚を丸ごと割り当てなければならなかったのに比べてリソース使用率が大きく改善されます。
インラインでのデバイス要求
単純なケースでは別途ResourceClaimやResourceClaimTemplateを作成せず、Podスペックで直接デバイスを要求することもできます。
apiVersion: v1
kind: Pod
metadata:
name: quick-gpu-job
namespace: ml-workloads
spec:
containers:
- name: compute
image: nvcr.io/nvidia/cuda:12.3.1-runtime-ubuntu22.04
command: ['python3', 'benchmark.py']
resources:
claims:
- name: gpu-req
resourceClaims:
- name: gpu-req
resourceClaimTemplateName: ''
source:
devices:
requests:
- name: gpu
deviceClassName: gpu.nvidia.com-h100
count: 1
restartPolicy: Never
マルチクラウドDRA比較 (AKS vs GKE vs EKS)
各クラウドプロバイダのDRAサポート状況とGPUインスタンスの選択肢を比較します。
| 項目 | AKS (Azure) | GKE (Google) | EKS (AWS) |
|---|---|---|---|
| Kubernetes最小バージョン | 1.31+ (Preview) | 1.32+ (Preview) | 1.32+ (Preview) |
| DRAフィーチャーゲート | 手動での有効化が必要 | GKEチャネル別に自動有効化 | EKSアドオンで管理 |
| GPUインスタンス (A100) | NC A100 v4 | a2-highgpu / a3-highgpu | p4d.24xlarge |
| GPUインスタンス (H100) | ND H100 v5 | a3-ultragpu-8g | p5.48xlarge |
| NVIDIA DRAドライバ | Helmで手動インストール | GKE GPU Operator統合 | EKS NVIDIAアドオン |
| MIGサポート | 対応 (手動構成) | 対応 (GKE MIG管理機能) | 対応 (手動構成) |
| ノードオートスケーリング連携 | Karpenter / Cluster Autoscaler | NAP / Karpenter | Karpenter |
| 価格 (A100 80GB、1時間あたり) | ~$3.67 | ~$3.67 | ~$32.77 (8GPU全体) |
| 主な制限事項 | Preview機能、SLA非保証 | Rapidチャネルのみ対応 | 特定リージョンのみ利用可 |
クラウドごとの設定の違い
GKEではGPUノードプール作成時にDRAを有効化できます:
# GKEでDRA対応のGPUノードプールを作成
gcloud container node-pools create gpu-pool-h100 \
--cluster=ml-cluster \
--zone=us-central1-c \
--machine-type=a3-highgpu-8g \
--accelerator=type=nvidia-h100-80gb,count=8 \
--num-nodes=2 \
--enable-autoscaling \
--min-nodes=0 \
--max-nodes=4 \
--node-labels="gpu-type=h100" \
--metadata="install-nvidia-driver=True"
# DRAフィーチャーゲートの有効化 (GKE Rapidチャネル)
gcloud container clusters update ml-cluster \
--zone=us-central1-c \
--release-channel=rapid \
--enable-kubernetes-unstable-apis=resource.k8s.io/v1beta1
EKSではEKSマネージドアドオンを通じてDRAドライバを管理します:
# EKSクラスタにNVIDIA DRAドライバのアドオンをインストール
aws eks create-addon \
--cluster-name ml-cluster \
--addon-name nvidia-dra-driver \
--addon-version v0.8.0-eksbuild.1 \
--region us-east-1
# GPUノードグループの作成 (Karpenter NodePool)
cat <<EOF | kubectl apply -f -
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: gpu-h100-pool
spec:
template:
spec:
requirements:
- key: "node.kubernetes.io/instance-type"
operator: In
values: ["p5.48xlarge"]
- key: "karpenter.sh/capacity-type"
operator: In
values: ["on-demand"]
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: gpu-nodes
limits:
cpu: "1000"
memory: 4000Gi
nvidia.com/gpu: "64"
disruption:
consolidationPolicy: WhenEmpty
consolidateAfter: 30m
EOF
各クラウドプロバイダごとにDRAの安定性の水準と統合の深さが異なるため、プロダクションへのデプロイ前には必ず該当プロバイダのDRAサポート文書を確認し、可能であればPreview/Beta機能に対する個別のサポート契約を検討する必要があります。
既存のExtended ResourceモデルからDRAへのマイグレーション
既存のExtended ResourceベースのGPU割り当てからDRAへ移行するのはクラスタ全体に影響を及ぼす作業のため、段階的に進める必要があります。
マイグレーションの段階
1段階 - 評価とインベントリ (1~2週間)
現在のクラスタのGPU使用状況を把握します。
# 現在Extended Resource方式でGPUを使用しているすべてのPodを取得
kubectl get pods --all-namespaces -o json | \
jq -r '.items[] |
select(.spec.containers[].resources.limits["nvidia.com/gpu"] != null) |
[.metadata.namespace, .metadata.name,
(.spec.containers[].resources.limits["nvidia.com/gpu"] // "0")] |
@tsv' | \
column -t -s $'\t'
# ノード別のGPU割り当て状況
kubectl get nodes -l nvidia.com/gpu.present=true -o json | \
jq -r '.items[] |
[.metadata.name,
.status.capacity["nvidia.com/gpu"],
.status.allocatable["nvidia.com/gpu"]] |
@tsv' | \
column -t -s $'\t' -N "NODE,CAPACITY,ALLOCATABLE"
2段階 - DRAインフラの準備 (1週間)
- Kubernetesのバージョンを1.32以上へアップグレードします。
- DRAフィーチャーゲートが有効になっているか確認します。
- NVIDIA DRAドライバをインストールします。
- 既存のNVIDIA Device Pluginはまだ削除しません (共存可能)。
3段階 - DeviceClassの定義 (1~2日)
クラスタに存在するGPUモデルごとにDeviceClassを作成します。先に説明したYAMLの例を参考に、運用環境のGPUインベントリに合わせてDeviceClassを定義します。
4段階 - パイロットワークロードの移行 (2~4週間)
中核ではないワークロードからDRA方式へ移行します。開発/ステージング環境でまず検証したうえで、プロダクションの優先度の低いワークロードへ広げます。
5段階 - 全面移行 (2~4週間)
すべてのGPUワークロードをDRAへ移行し、既存のNVIDIA Device Pluginを削除します。この段階ではロールバック計画を必ず準備しておく必要があります。
マイグレーション時の注意事項
- 共存期間: DRAドライバと既存のDevice Pluginは同時に運用できますが、同一のPodで両方の方式を混用してはいけません。1つのPodは
resources.limitsのExtended Resource方式かresourceClaimsのDRA方式のどちらか一方だけを使用する必要があります。 - RBACの更新: DRAリソース(
resourceclaims、resourceclaimtemplates、deviceclasses)に対するRBAC権限を、関連するサービスアカウントへ付与する必要があります。 - モニタリングの再構成: 従来
nvidia.com/gpuメトリクスを基にしていたダッシュボードとアラートを、DRAベースのメトリクスへ更新する必要があります。
運用時の注意事項とモニタリング
容量計画 (Capacity Planning)
DRA環境でのGPU容量計画は従来よりきめ細かくなります。MIGを活用する場合は物理GPU数だけでなくMIGプロファイルの組み合わせも考慮する必要があります。
推奨される容量計画の原則:
- 物理GPUごとのMIGプロファイル混在は禁止: 1枚のA100で1g.5gbと3g.20gbを同時に構成すると管理の複雑さが急増します。ノード単位で同一のMIGプロファイルを適用することを推奨します。
- オーバープロビジョニング率: 学習ワークロードは10~15%、推論ワークロードは20~30%の余裕容量を確保してください。DRAではデバイス属性ベースのスケジューリングのため、単純なGPU個数ではなくDeviceClass別の可用量を基準に計画します。
- ノード障害への備え: GPUノードに障害が発生すると、そのノードのすべてのResourceClaimが影響を受けます。最低でもN+1以上のノードの余裕を確保してください。
モニタリングの構成
DRA環境では次のメトリクスをモニタリングする必要があります:
# ResourceClaimの状態モニタリング
kubectl get resourceclaims --all-namespaces -o custom-columns=\
'NAMESPACE:.metadata.namespace,'\
'NAME:.metadata.name,'\
'DEVICECLASS:.spec.devices.requests[0].deviceClassName,'\
'ALLOCATED:.status.allocation.devices.results[0].device'
# Pending状態のResourceClaimの確認 (割り当て失敗の検知)
kubectl get resourceclaims --all-namespaces \
--field-selector="status.allocation=" \
-o custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,AGE:.metadata.creationTimestamp'
# DeviceClass別の使用率確認
kubectl get resourceslices -o json | \
jq -r '[.items[].spec.devices[] |
{driver: .basic.attributes["gpu.nvidia.com"].productName.stringValue}] |
group_by(.driver) |
map({gpu_model: .[0].driver, total: length}) |
.[] | [.gpu_model, .total] | @tsv'
Prometheusメトリクスの収集
NVIDIA DRAドライバはPrometheusメトリクスを公開します。次のような主要メトリクスをモニタリングダッシュボードに含めてください:
| メトリクス名 | 説明 | アラート閾値 |
|---|---|---|
dra_resource_claims_total | ResourceClaimの総数 | - |
dra_resource_claims_pending | 待機中のResourceClaim数 | 5分以上Pendingの場合に警告 |
dra_resource_claims_allocated | 割り当て完了したResourceClaim数 | - |
dra_devices_available | DeviceClass別の利用可能デバイス数 | 可用率10%未満の場合に警告 |
dra_devices_allocated | 割り当て済みデバイス数 | - |
dra_allocation_duration_seconds | 割り当て所要時間 | p99が30秒を超えた場合に警告 |
dra_plugin_errors_total | ドライバのエラー回数 | 1分以内に5回以上の場合は緊急 |
障害事例と復旧手順
事例1: ResourceClaimが恒久的にPending状態
症状: PodがPending状態から抜け出せず、kubectl describe podで「waiting for ResourceClaim to be allocated」というメッセージが表示されます。
原因分析:
- 要求したDeviceClassに該当する利用可能なデバイスが存在しない
- DeviceClassのCEL式が誤っており、どのデバイスにもマッチしない
- DRAドライバのkubeletプラグインが異常な状態
復旧手順:
# 1. ResourceClaimの状態確認
kubectl describe resourceclaim training-gpu-claim -n ml-workloads
# 2. 要求したDeviceClassにマッチするデバイスが存在するかを確認
kubectl get resourceslices -o json | \
jq '.items[].spec.devices[] |
select(.basic.attributes["gpu.nvidia.com"].productName.stringValue == "NVIDIA A100 80GB PCIe")'
# 3. DRAドライバの状態確認
kubectl get pods -n nvidia-dra-driver
kubectl logs -n nvidia-dra-driver -l app=nvidia-dra-driver-kubelet-plugin --tail=50
# 4. スケジューラのログからDRA関連のエラーを確認
kubectl logs -n kube-system -l component=kube-scheduler --tail=100 | grep -i "dra\|resourceclaim\|deviceclass"
# 5. 必要に応じてResourceClaimを削除して再作成
kubectl delete resourceclaim training-gpu-claim -n ml-workloads
kubectl apply -f training-gpu-claim.yaml
事例2: ノード障害時のGPUデバイスのリーク(Leak)
症状: ノードがNotReady状態になった後に復旧しましたが、そのノードのGPUがResourceSlice上では「割り当て済み」と表示され、新しいPodに割り当てられません。
原因: ノード障害でDRAドライバのkubeletプラグインが異常終了し、デバイスの解放手順が完了しませんでした。
復旧手順:
- そのノードで実行されていたPodのResourceClaimがまだ存在するかを確認します。
- 該当のPodが削除されていればResourceClaimも一緒に削除されるはずですが (オーナー参照がある場合)、そうでなければ手動で削除します。
- DRAドライバのkubeletプラグインを再起動します。
# 該当ノードのDRAドライバプラグインPodを再起動
kubectl delete pod -n nvidia-dra-driver -l app=nvidia-dra-driver-kubelet-plugin \
--field-selector spec.nodeName=problematic-node
# ResourceSliceが正しく更新されたかを確認 (再起動後30秒待機)
sleep 30
kubectl get resourceslices --field-selector spec.nodeName=problematic-node -o yaml
事例3: DRAドライバのアップグレード中に既存ワークロードが停止
症状: DRAドライバをHelmでアップグレードする過程でkubeletプラグインDaemonSetのPodが再起動し、そのノードで実行中だったGPUワークロードがデバイスアクセスエラーを発生させます。
予防措置:
- DRAドライバのアップグレード前にGPUワークロードを別のノードへ退避(drain)します。
- ローリングアップデート戦略を
maxUnavailable: 1に設定し、一度に1つのノードでのみドライバが再起動するようにします。 - 学習ワークロードの場合はチェックポインティングを有効にし、ドライバの再起動時にも学習の進行状況を保存します。
事例4: CEL式の誤りでDeviceClassのマッチングに失敗
症状: DeviceClassを作成しましたがResourceClaimが割り当てられません。kubectl describeの結果、マッチするデバイスがないと表示されます。
原因: DeviceClassのselectors.cel.expressionで属性名が誤っているか、比較する値が実際にデバイスが報告する値と異なっています。
デバッグ方法:
# 実際にデバイスが報告する属性名と値を確認
kubectl get resourceslices -o json | \
jq '.items[0].spec.devices[0].basic.attributes'
# 出力例:
# {
# "gpu.nvidia.com": {
# "driverVersion": {"stringValue": "550.54.15"},
# "productName": {"stringValue": "NVIDIA A100 80GB PCIe"},
# "architecture": {"stringValue": "Ampere"},
# "cudaComputeCapability": {"versionValue": "8.0"},
# "memory": {"quantityValue": "80Gi"}
# }
# }
# DeviceClassのCEL式で使用する属性名が上の出力と正確に一致するかを確認します。
事例5: ResourceClaimのクォータ超過
症状: ネームスペースのResourceQuotaによってResourceClaimの作成が拒否されます。
DRA環境ではネームスペースごとにResourceClaim数の上限を設定できます。特にResourceClaimTemplateを使用するDeploymentのレプリカが多いと想定より早くクォータに到達することがあるため、注意が必要です。
プロダクションデプロイのチェックリスト
DRAベースのGPUワークロードをプロダクションへデプロイする前に、次のチェックリストを確認してください。
インフラの準備
- Kubernetes 1.32以上へのアップグレードが完了している
DynamicResourceAllocationフィーチャーゲートがkube-apiserver、kube-scheduler、kubeletで有効になっている- NVIDIA DRAドライバがすべてのGPUノードにインストールされ正常に動作している
- ResourceSliceが各ノードのGPU情報を正確に報告している
DeviceClassの設計
- クラスタのすべてのGPUモデルに対してDeviceClassが定義されている
- MIGプロファイル別のDeviceClassが必要な場合に定義されている
- DeviceClassのCEL式が実際のデバイス属性と正確にマッチしている (テスト用ResourceClaimで検証)
ワークロードの構成
- Podスペックで
resourceClaimsが正しく参照されている - ResourceClaimTemplateがDeployment/Jobワークロードに合わせて構成されている
- GPUトポロジー制約(NVLinkなど)が必要なワークロードにconstraintsが設定されている
RBACとセキュリティ
- ネームスペースごとのResourceClaim作成権限が適切に設定されている
- DeviceClassはクラスタスコープのリソースのため、管理者だけが作成/変更できるよう制限されている
- ResourceQuotaでネームスペースごとのResourceClaim数の上限が設定されている
モニタリングとアラート
- DRA関連のPrometheusメトリクスの収集が構成されている
- Pending状態のResourceClaimに対するアラートが設定されている (5分以上Pendingの場合)
- DRAドライバのエラーに対するアラートが設定されている
- GPU使用率とDeviceClass別の可用量ダッシュボードが構成されている
障害対応
- ノード障害時のResourceClaim復旧手順が文書化されている
- DRAドライバのアップグレード手順とロールバック計画が策定されている
- GPUワークロードのチェックポインティングが有効になっている (学習ワークロード)
- 既存のExtended Resourceモデルへのロールバック計画が準備されている (マイグレーション期間中)
性能検証
- デバイス割り当ての遅延が許容範囲内かを確認 (p99基準で30秒以内)
- スケジューラのDRA関連スループットがワークロード規模に対して十分かを確認
- MIG環境で各スライスの分離性能が検証されている
参考資料
- Kubernetes公式ドキュメント - Dynamic Resource Allocation
- The New Stack - Kubernetes Primer: Dynamic Resource Allocation (DRA) for GPU Workloads
- The New Stack - Kubernetes: Get the Most from Dynamic Resource Allocation
- GitHub - DRA Example Driver (kubernetes-sigs)
- CloudKeeper - Kubernetes 1.34: Future of Dynamic Resource Allocation
- NVIDIA DRA Driver Documentation
- KEP-4381: DRA Structured Parameters