機械学習のアプリに GPU を 1 枚使わせたい。 Kubernetes は、どのノードに空きがあるかを調べ、選んだ GPU をコンテナから使えるようにする必要があります。 さらに、GPU なら何でもよいのではなく、種類やメモリ容量を指定したい場合もあります。
この章では、デバイスの個数を要求する Device Plugin と、属性などの条件で選ぶ DRA を比べます。 実習環境には GPU がないため、実機への割り当てではなく、API とデバイス情報の置き場所を確認します。
GOAL この章のゴール
- GPU の一覧が報告され、Pod に割り当てられる流れが分かる
- 個数で要求する方式と、属性の条件で選ぶ方式を区別できる
- API でデバイスの情報を確認する場所が分かる
Device Plugin
ノードに GPU があっても、kubelet がその種類や状態をすべて自力で調べられるわけではありません。 そこで、GPU を扱うプログラムが「このノードには何枚あり、どれが使えるか」を kubelet に知らせます。 この役を担うのが Device Plugin です。
通常は、ベンダーが提供するプラグインを対象の各ノードで動かします。 プラグインと kubelet は、同じノード上のプログラム同士をつなぐ UNIX socket を使い、gRPC という方式で情報をやり取りします。
流れは 3 段です。
まず plugin が /var/lib/kubelet/device-plugins/ に自分の socket を置いて gRPC を提供し始め、同じディレクトリの kubelet.sock で kubelet が提供する Registration サービスに「nvidia.com/gpu というリソース名で、この socket に居る」と登録します。
次に kubelet が plugin の ListAndWatch を呼び、デバイスの ID と健全性の一覧をストリームで受け取り続けます。
kubelet はその数を Node の status.capacity に nvidia.com/gpu: 4 のように載せ、scheduler はこの数を見て Pod を置きます。
最後に、Pod が limits: nvidia.com/gpu: 1 を要求してノードに乗ると、kubelet は plugin の Allocate を呼びます。
Allocate の応答には、コンテナからデバイスを使うために必要なデバイスノード、環境変数、マウント、注釈、そして CDI のデバイス名が入っていて、kubelet はそれを CRI の CreateContainer に載せます。
kubelet は最初に GetDevicePluginOptions を呼んで、plugin が任意の機能 (割り当ての助言をする GetPreferredAllocation、コンテナ起動前に初期化をする PreStartContainer) を実装しているかを確かめます。
Node の capacity に載る nvidia.com/gpu のような名前は 拡張リソース (extended resource) と呼ばれ、scheduler にとっては、ノードごとに残っている個数を表す整数でしかありません。
kubernetes.io は拡張リソースの制約として、整数でしか扱えないこと、オーバーコミットできないこと、デバイスをコンテナ間で共有できないことを挙げています。
これが Device Plugin の強みであり、限界でもあります。
整数なので scheduler の変更無しに済みますが、「メモリ 40GiB 以上の GPU」のような属性を条件にした要求は表現できません。
どの GPU を渡すかは kubelet (と plugin) がノードの中で決め、scheduler はノード選びにその情報を使えないのです。
DRA
DRA は、この限界を解くために作られました。 kubernetes.io は DRA の利点として、CEL (式の言語) による細かい絞り込み、複数のコンテナや Pod でのデバイス共有、デバイス設定をノード単位でなくワークロード単位で持てること、DeviceClass による種類の一元管理を挙げ、Device Plugin には「コンテナごとの個数指定しかできず、共有も式による絞り込みもできない」と対比しています。
DRA では、デバイスは属性付きのオブジェクトとして apiserver に公開されます。 Pod の作者は「どのクラスのデバイスを、どんな条件で、何個」と書き、scheduler がクラスタ全体の在庫と突き合わせて選びます。 kubernetes.io はこれを、StorageClass から PVC で容量を claim する動的ボリューム確保と似た体験だと説明しています。
- ResourceSlice:driver が公開するデバイスの一覧 (在庫)。似たデバイスのプールごとに「このデバイスが、この属性 (モデル、メモリなど) で存在する」と書く。
- DeviceClass:driver や管理者が定義するデバイスの種類。StorageClass にあたる。
- ResourceClaimTemplate:Pod の作者が書く要求のひな型。
deviceClassNameと、属性に対する条件と個数。 - ResourceClaim:実際の要求。Template を参照する Pod ごとに、kube-controller-manager の resourceclaim-controller が生成する。scheduler が割り当て結果を書き込み、複数の Pod が 1 つの Claim を共有することもできる。
「How DRA Works」によると、scheduler は Pod ごとに ResourceSlice を調べ、Pod を置けるノードからアクセスでき、Claim の条件に合う未割り当てのデバイスを探し、見つかったら ResourceClaim に割り当ての詳細を書いてから、そのデバイスにアクセスできるノードに Pod を置きます。
Pod がノードに乗ると、kubelet と driver が gRPC で協調してデバイスを準備します。
その gRPC は kubelet 側で DRAPlugin サービスとして定義され、NodePrepareResources の応答に、次に説明する CDI のデバイス名が入ります。
制約もあり、DRA のリソースは preemption (優先度の高い Pod のために低い Pod を追い出す仕組み) の対象にならないので、デバイスを低優先度の Pod が使っていると、高優先度の Pod は Pending のまま待ちます。
API の安定性とドライバーの対応範囲
DRA の API が GA でも、すべてのデバイス用ドライバーと機能が同じ段階にあるとは限りません。 NVIDIA GPU 向け DRA driver の公式 README は、複数ノードの NVLink を扱う ComputeDomain と、GPU の割り当てを扱う plugin を分けています。 2026 年 10 月の確認時点では、前者を正式サポートとし、後者の一部機能は試用できるが正式サポートではなく、Helm の既定でも無効と説明しています。 採用を判断するときは、Kubernetes のバージョンに加え、使いたいデバイス、ドライバーのリリース、個別機能のサポート範囲を確認します。
CDI
Device Plugin でも DRA でも、最後には「このコンテナに /dev/nvidia0 と、CUDA のライブラリと、環境変数を入れろ」という指示をランタイムに渡す必要があります。
その書式が CDI (Container Device Interface) です。
CDI の仕様は自身を「コンテナランタイムがサードパーティのデバイスを扱えるコンテナを作るための仕組み」と説明しています。
デバイスは vendor.com/class=name の形の完全修飾名で指し、spec ファイルには containerEdits として環境変数、デバイスノード、マウント、フックを書き、ランタイムはその内容を OCI の config.json に適用します。
CDI 以前、NVIDIA の GPU を使うには nvidia-container-runtime という runc の薄いラッパーが要りました。
NVIDIA のドキュメントによると、これは OCI の spec に prestart hook を差し込み、コンテナ起動前にデバイスとライブラリを注入するものです。
CDI では、ベンダーのツール (NVIDIA なら nvidia-ctk cdi generate) が /etc/cdi/ か /var/run/cdi/ に spec を生成しておき、kubelet は nvidia.com/gpu=0 という名前を CRI の CDI_devices で渡すだけになります。
containerd や CRI-O がその名前で spec を引き、OCI の config.json にデバイスとマウントを展開します。
kubelet はデバイスの中身を知らなくてよく、ランタイムは Kubernetes を知らなくてよい。
それぞれが持つ実装が減りました。
実機: resource.k8s.io を眺める
GPU の無いこのクラスタでも、DRA の API が apiserver に登録されていることは確かめられます。
kubectl api-resources --api-group=resource.k8s.io出力例
NAME SHORTNAMES APIVERSION NAMESPACED KIND
deviceclasses resource.k8s.io/v1 false DeviceClass
resourceclaims resource.k8s.io/v1 true ResourceClaim
resourceclaimtemplates resource.k8s.io/v1 true ResourceClaimTemplate
resourceslices resource.k8s.io/v1 false ResourceSlicekubectl get resourceslices,deviceclasses
kubectl get node -o jsonpath='{.items[0].status.capacity}' | jq出力例
No resources found
{
"cpu": "4",
"ephemeral-storage": "...",
"memory": "...",
"pods": "110"
}ResourceSlice が無いのは DRA driver が居ないからで、capacity に nvidia.com/gpu が無いのは Device Plugin が居ないからです。
GPU ノードのあるクラスタでは、この 2 つのどちらか (または両方) に在庫が現れます。
GPU の Pod が Unschedulable のとき、最初に見るのはこの 2 行です。
ふりかえり
QDevice Plugin が報告したデバイス数は、どこに載る?
kubelet が ListAndWatch で受け取った数を Node の capacity に nvidia.com/gpu: 4 のように載せ、scheduler はこれを整数の在庫として扱います。ResourceSlice は DRA の仕組みです。
QDRA が Device Plugin と最も違う点は?
Device Plugin は整数で要求し、どのデバイスかは kubelet がノード内で決めます。DRA は ResourceSlice の属性に対して CEL の条件で要求し、scheduler がクラスタ全体から選びます。
QCDI の役割は?
kubelet は nvidia.com/gpu=0 のような名前を CRI で渡すだけで、containerd が /etc/cdi/ などの spec を引いて OCI の config.json に展開します。
参考
-
Device Plugins, Kubernetes Documentation: https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/
-
Extended resources (Resource Management for Pods and Containers), Kubernetes Documentation: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#extended-resources
-
Dynamic Resource Allocation, Kubernetes Documentation: https://kubernetes.io/docs/concepts/resource-management/dynamic-resource-allocation/
-
How DRA Works, Kubernetes Documentation: https://kubernetes.io/docs/concepts/resource-management/dynamic-resource-allocation/how-dra-works/
-
Kubernetes v1.34: DRA has graduated to GA, Kubernetes Blog: https://kubernetes.io/blog/2025/09/01/kubernetes-v1-34-dra-updates/
-
Feature gate
DynamicResourceAllocationの履歴 (kubernetes/website): https://github.com/kubernetes/website/blob/main/content/en/docs/reference/command-line-tools-reference/feature-gates/DynamicResourceAllocation.md -
Feature gate
DevicePluginCDIDevicesの履歴 (kubernetes/website): https://github.com/kubernetes/website/blob/main/content/en/docs/reference/command-line-tools-reference/feature-gates/DevicePluginCDIDevices.md -
kubelet の DRA gRPC 定義 (
api.proto), kubernetes/kubelet: https://github.com/kubernetes/kubelet/blob/master/pkg/apis/dra/v1beta1/api.proto -
CRI API 定義 (
CDI_devices), kubernetes/cri-api: https://github.com/kubernetes/cri-api/blob/master/pkg/apis/runtime/v1/api.proto -
Container Device Interface (CDI) README と Specification: https://github.com/cncf-tags/container-device-interface
-
CRI Plugin Config Guide, containerd (
cdi_spec_dirs): https://github.com/containerd/containerd/blob/main/docs/cri/config.md -
Support for Container Device Interface, NVIDIA Container Toolkit: https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/cdi-support.html
-
Architecture Overview, NVIDIA Container Toolkit: https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/arch-overview.html
-
NVIDIA/k8s-device-plugin: https://github.com/NVIDIA/k8s-device-plugin
-
NVIDIA/k8s-dra-driver-gpu: https://github.com/NVIDIA/k8s-dra-driver-gpu
-
Kubernetes SIGs「DRA Driver for NVIDIA GPUs」: https://github.com/kubernetes-sigs/dra-driver-nvidia-gpu