- Introduction
- DRA Architecture Overview
- Installing and Configuring the DRA Driver
- Defining DeviceClasses and Managing GPU Tiers
- Pod Scheduling with ResourceClaim
- Multi-cloud DRA Comparison (AKS vs GKE vs EKS)
- Migrating from the Extended Resource Model to DRA
- Operational Cautions and Monitoring
- Failure Cases and Recovery Procedures
- Production Deployment Checklist
- References

Introduction
Scheduling hardware accelerators such as GPUs on Kubernetes has been a hard problem for operators for a long time. Because the existing Extended Resource model allocated GPUs as a simple integer count, like nvidia.com/gpu: 1, scheduling on a GPU's detailed attributes (VRAM capacity, MIG partition, a specific model) was fundamentally impossible.
DRA (Dynamic Resource Allocation) - introduced as alpha in Kubernetes 1.26 to solve this problem, substantially redesigned in 1.31 and promoted to beta in 1.32 - is a framework for requesting and allocating complex hardware resources such as GPUs, FPGAs and network devices in a structured way.
The Limits of the Existing Extended Resource Model
In the existing model, GPU allocation looked like this:
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
This approach has a few fundamental limitations:
- No attribute-based selection: you cannot distinguish an A100 80GB from a T4 16GB. You simply ask for "2 GPUs", with no way to state which kind of GPU you want.
- No partial allocation: NVIDIA MIG (Multi-Instance GPU) can split an A100 into 7 independent instances, but the Extended Resource model has no fine-grained way to express that.
- No control over device initialization: there is no way to standardize the procedure for applying MPS (Multi-Process Service) settings or a particular driver mode before handing the GPU to the container.
- Device topology ignored: getting a pair of NVLink-connected GPUs allocated together matters for performance, but the existing model does not take it into account.
DRA removes all of these limitations and fundamentally improves the scheduling quality of GPU workloads. In this article, we cover DRA systematically, from its architecture through practical deployment to operational troubleshooting.
DRA Architecture Overview
DRA belongs to Kubernetes' resource.k8s.io/v1beta1 API group (as of 1.32) and consists of the following four core resources.
The Core Resource Structure
DeviceClass: defines a type of device. Create a DeviceClass per GPU model so that a workload can request a specific GPU type. It plays a role similar to StorageClass for storage.
ResourceClaim: represents an actual device allocation request. Just as a PersistentVolumeClaim requests storage, a ResourceClaim requests a device from a particular DeviceClass. It can exist independently of a Pod's lifecycle, so a device can be shared between several Pods, or kept the same across a Pod restart.
ResourceClaimTemplate: a template for creating a ResourceClaim automatically when a Pod is created. Use it when each Pod needs its own dedicated ResourceClaim.
ResourceSlice: the list of devices that the DRA driver installed on a node reports to the API server. The scheduler consults ResourceSlices to learn which devices are available on which node.
The Scheduling Flow
DRA-based scheduling proceeds through the following steps:
- Pod submission: the user creates a Pod that references a ResourceClaim.
- Scheduler filtering: kube-scheduler uses the ResourceSlice information to filter for nodes where a device of the requested DeviceClass is available.
- Structured parameter matching: the scheduler matches the ResourceClaim's requirements directly against the available devices on each node. This is the heart of DRA's "Structured Parameters" model.
- Allocation decision: the scheduler allocates a specific device on a specific node to the ResourceClaim.
- Device preparation: that node's DRA driver (the kubelet plugin) prepares the allocated device so the container can use it (CDI device configuration and so on).
- Container start: kubelet starts the container with the prepared device.
Unlike the existing Device Plugin approach, in DRA the scheduler itself understands the device attributes and decides the optimal placement. That is a fundamentally different approach from the Device Plugin merely reporting an "available count".
Installing and Configuring the DRA Driver
Prerequisites
Using DRA requires Kubernetes 1.32 or later, with the DynamicResourceAllocation feature gate enabled. In Kubernetes 1.32 it is beta, so it is enabled by default.
# check the cluster version
kubectl version --short
# check that the DRA feature gate is enabled (needed on kube-apiserver, kube-scheduler and kubelet)
# on a kubeadm-based cluster this is set in the ClusterConfiguration
kubectl get configmap -n kube-system kubeadm-config -o yaml | grep -A 5 "featureGates"
# check the DRA-related API resources
kubectl api-resources | grep resource.k8s.io
# example output:
# 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
Installing the NVIDIA DRA Driver
NVIDIA provides an official DRA driver, nvidia-dra-driver. It is a separate project from the existing k8s-device-plugin, and it fully supports DRA's structured parameter model.
# add the NVIDIA DRA driver Helm chart repository
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm repo update
# install nvidia-dra-driver
# if the NVIDIA GPU Operator is already installed, the device-plugin has to be disabled
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
# confirm the installation
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
# confirm the ResourceSlices were created - the driver reports the node's GPU information
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
Inspecting a ResourceSlice in Detail
Once the driver is installed correctly, each GPU node's device information is reported as a ResourceSlice. That is how the scheduler learns each GPU's detailed attributes.
# view a specific node's ResourceSlice in detail
kubectl get resourceslice gpu-node1-nvidia-gpu-slice-0 -o yaml
The example output shows that a rich set of attributes is reported for each GPU: model name, VRAM, UUID, architecture, MIG support and more. Those attributes are exactly what DeviceClass and ResourceClaim use as filter conditions.
Defining DeviceClasses and Managing GPU Tiers
Defining a DeviceClass per GPU Model
Like StorageClass, DeviceClass defines a "class" of device. Once the cluster administrator defines them up front, workload developers can request the GPU they want simply by referencing the DeviceClass name.
# 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'
The example above defines three DeviceClasses:
- gpu.nvidia.com-a100: allocates a whole A100 80GB GPU in time-slicing mode
- gpu.nvidia.com-h100: allocates an H100 80GB GPU with short-interval time-slicing
- gpu.nvidia.com-a100-mig-3g20gb: allocates an A100 MIG 3g.20gb profile (20GB VRAM, 3 compute slices)
MIG Partitioning Strategy
Using MIG on an NVIDIA A100/H100 splits one physical GPU into several independent instances, which maximizes utilization. In DRA you can define a DeviceClass per MIG profile, which makes fine-grained GPU resource management possible.
| MIG profile | Compute slices | VRAM | Max instances (on A100) | Primary use |
|---|---|---|---|---|
| 1g.5gb | 1/7 | 5GB | 7 | Inference (small models), dev/test |
| 1g.10gb | 1/7 | 10GB | 7 | Inference (medium models) |
| 2g.10gb | 2/7 | 10GB | 3 | Small-scale training, batch inference |
| 3g.20gb | 3/7 | 20GB | 2 | Mid-scale training, fine-tuning |
| 4g.40gb | 4/7 | 40GB | 1 | Large-scale training |
| 7g.80gb | 7/7 | 80GB | 1 | The whole GPU (same as no MIG) |
A100 vs H100 Specifications
When designing a DeviceClass it matters that you understand the characteristics of the GPU model precisely.
| Category | NVIDIA A100 80GB | NVIDIA H100 80GB |
|---|---|---|
| Architecture | Ampere | Hopper |
| FP16 performance | 312 TFLOPS | 989 TFLOPS |
| FP8 performance | Not supported | 1,979 TFLOPS |
| VRAM | 80GB HBM2e | 80GB HBM3 |
| Memory bandwidth | 2 TB/s | 3.35 TB/s |
| NVLink bandwidth | 600 GB/s | 900 GB/s |
| Max MIG instances | 7 | 7 |
| TDP | 300W | 700W |
| DRA driver support | nvidia-dra-driver v0.6+ | nvidia-dra-driver v0.7+ |
Because FP8 arithmetic and the Transformer Engine give the H100 more than 3x the LLM training/inference performance of the A100, it is worth establishing a policy that allocates the H100 DeviceClass to LLM workloads first.
Pod Scheduling with ResourceClaim
Basic ResourceClaim Usage
This approach creates a ResourceClaim directly and references it from the Pod. Use it when the device has to be managed independently of the Pod lifecycle, or shared between several Pods.
# create a standalone 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'
---
# a Pod that references the ResourceClaim
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
The thing to notice in the example above is the constraints field. matchAttribute sets a constraint so that the 4 A100 GPUs are allocated as a set interconnected by NVLink. That has a decisive effect on inter-GPU communication performance during distributed training.
Using a ResourceClaimTemplate
For a workload that creates several Pods, such as a Job or a Deployment, use a ResourceClaimTemplate so that a dedicated ResourceClaim is created automatically for each Pod.
# deploying a MIG-based inference service
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
In this configuration 6 Triton Inference Server replicas each get 1 MIG 3g.20gb slice of an A100. Running 6 inference instances on 2 physical A100s improves resource utilization considerably compared with the existing Extended Resource model, which would have had to allocate 2 whole GPUs.
Inline Device Requests
In simple cases you can request a device directly from the Pod spec, without creating a separate ResourceClaim or ResourceClaimTemplate.
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
Multi-cloud DRA Comparison (AKS vs GKE vs EKS)
Here is a comparison of DRA support and GPU instance options across the cloud providers.
| Category | AKS (Azure) | GKE (Google) | EKS (AWS) |
|---|---|---|---|
| Minimum Kubernetes version | 1.31+ (Preview) | 1.32+ (Preview) | 1.32+ (Preview) |
| DRA feature gate | Must be enabled manually | Auto-enabled per GKE channel | Managed via an EKS addon |
| GPU instance (A100) | NC A100 v4 | a2-highgpu / a3-highgpu | p4d.24xlarge |
| GPU instance (H100) | ND H100 v5 | a3-ultragpu-8g | p5.48xlarge |
| NVIDIA DRA driver | Manual Helm install | Integrated into the GKE GPU Operator | EKS NVIDIA addon |
| MIG support | Supported (manual setup) | Supported (GKE MIG manager) | Supported (manual setup) |
| Node autoscaling integration | Karpenter / Cluster Autoscaler | NAP / Karpenter | Karpenter |
| Price (A100 80GB, per hour) | ~$3.67 | ~$3.67 | ~$32.77 (all 8 GPUs) |
| Main limitations | Preview feature, no SLA | Rapid channel only | Only certain regions |
Configuration Differences by Cloud
On GKE you can enable DRA when creating the GPU node pool:
# create a DRA-capable GPU node pool on GKE
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"
# enable the DRA feature gate (GKE Rapid channel)
gcloud container clusters update ml-cluster \
--zone=us-central1-c \
--release-channel=rapid \
--enable-kubernetes-unstable-apis=resource.k8s.io/v1beta1
On EKS the DRA driver is managed through an EKS managed addon:
# install the NVIDIA DRA driver addon on the EKS cluster
aws eks create-addon \
--cluster-name ml-cluster \
--addon-name nvidia-dra-driver \
--addon-version v0.8.0-eksbuild.1 \
--region us-east-1
# create the GPU node group (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
The maturity of DRA and the depth of the integration differ from provider to provider, so before deploying to production you must read that provider's DRA support documentation and, where possible, review a separate support agreement covering the preview/beta feature.
Migrating from the Extended Resource Model to DRA
Migrating from Extended Resource-based GPU allocation to DRA affects the whole cluster, so it has to be done in stages.
The Migration Stages
Stage 1 - Assessment and inventory (1-2 weeks)
Work out how GPUs are currently being used in the cluster.
# list every Pod currently using a GPU through the Extended Resource model
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 allocation per node
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"
Stage 2 - Preparing the DRA infrastructure (1 week)
- Upgrade Kubernetes to 1.32 or later.
- Confirm the DRA feature gate is enabled.
- Install the NVIDIA DRA driver.
- Do not remove the existing NVIDIA Device Plugin yet (they can coexist).
Stage 3 - Defining the DeviceClasses (1-2 days)
Create a DeviceClass for every GPU model present in the cluster. Use the YAML examples above as a reference and define the DeviceClasses to match your production GPU inventory.
Stage 4 - Converting the pilot workload (2-4 weeks)
Convert non-critical workloads to DRA first. Validate in development/staging, then extend to low-priority production workloads.
Stage 5 - Full conversion (2-4 weeks)
Convert every GPU workload to DRA and remove the existing NVIDIA Device Plugin. At this stage you must have a rollback plan prepared.
Cautions During the Migration
- The coexistence period: the DRA driver and the existing Device Plugin can run at the same time, but the two approaches must not be mixed within a single Pod. One Pod has to use either the Extended Resource approach in
resources.limitsor the DRA approach inresourceClaims, not both. - RBAC updates: the relevant service accounts have to be granted RBAC permissions on the DRA resources (
resourceclaims,resourceclaimtemplates,deviceclasses). - Reworking the monitoring: dashboards and alerts that were based on the
nvidia.com/gpumetric have to be updated to the DRA-based metrics.
Operational Cautions and Monitoring
Capacity Planning
GPU capacity planning becomes more fine-grained in a DRA environment. When using MIG you have to consider not only the number of physical GPUs but also the mix of MIG profiles.
Recommended capacity planning principles:
- Do not mix MIG profiles on one physical GPU: configuring 1g.5gb and 3g.20gb on the same A100 makes management complexity jump. Applying the same MIG profile across a node is recommended.
- Over-provisioning ratio: keep 10-15% spare capacity for training workloads and 20-30% for inference workloads. Because DRA schedules on device attributes, plan against the available capacity per DeviceClass rather than a simple GPU count.
- Preparing for node failure: when a GPU node fails, every ResourceClaim on that node is affected. Keep at least N+1 nodes of headroom.
Monitoring Setup
In a DRA environment you should monitor the following metrics:
# monitor ResourceClaim status
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'
# check for ResourceClaims stuck in Pending (detecting allocation failures)
kubectl get resourceclaims --all-namespaces \
--field-selector="status.allocation=" \
-o custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,AGE:.metadata.creationTimestamp'
# check utilization per 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'
Collecting Prometheus Metrics
The NVIDIA DRA driver exposes Prometheus metrics. Include the following key metrics in your monitoring dashboard:
| Metric name | Description | Alert threshold |
|---|---|---|
dra_resource_claims_total | Total number of ResourceClaims | - |
dra_resource_claims_pending | Number of pending ResourceClaims | Warn when pending 5 minutes or more |
dra_resource_claims_allocated | Number of allocated ResourceClaims | - |
dra_devices_available | Available devices per DeviceClass | Warn when availability drops under 10% |
dra_devices_allocated | Number of allocated devices | - |
dra_allocation_duration_seconds | Time taken to allocate | Warn when p99 exceeds 30 seconds |
dra_plugin_errors_total | Number of driver errors | Critical at 5 or more within 1 minute |
Failure Cases and Recovery Procedures
Case 1: A ResourceClaim Stays Pending Forever
Symptom: the Pod never leaves the Pending state, and kubectl describe pod shows the message "waiting for ResourceClaim to be allocated".
Cause analysis:
- There is no available device matching the requested DeviceClass
- The DeviceClass CEL expression is wrong and matches no device at all
- The DRA driver's kubelet plugin is unhealthy
Recovery procedure:
# 1. check the ResourceClaim status
kubectl describe resourceclaim training-gpu-claim -n ml-workloads
# 2. check whether a device matching the requested DeviceClass exists
kubectl get resourceslices -o json | \
jq '.items[].spec.devices[] |
select(.basic.attributes["gpu.nvidia.com"].productName.stringValue == "NVIDIA A100 80GB PCIe")'
# 3. check the DRA driver status
kubectl get pods -n nvidia-dra-driver
kubectl logs -n nvidia-dra-driver -l app=nvidia-dra-driver-kubelet-plugin --tail=50
# 4. look for DRA-related errors in the scheduler logs
kubectl logs -n kube-system -l component=kube-scheduler --tail=100 | grep -i "dra\|resourceclaim\|deviceclass"
# 5. if necessary, delete the ResourceClaim and recreate it
kubectl delete resourceclaim training-gpu-claim -n ml-workloads
kubectl apply -f training-gpu-claim.yaml
Case 2: A GPU Device Leak After a Node Failure
Symptom: the node went NotReady and then recovered, but its GPUs still show as "allocated" in the ResourceSlice and are not handed to new Pods.
Cause: the node failure killed the DRA driver's kubelet plugin abnormally, so the device release procedure never completed.
Recovery procedure:
- Check whether the ResourceClaim of the Pod that was running on that node still exists.
- If the Pod was deleted, the ResourceClaim should have gone with it (when there is an owner reference); if it did not, delete it by hand.
- Restart the DRA driver's kubelet plugin.
# restart the DRA driver plugin Pod on that node
kubectl delete pod -n nvidia-dra-driver -l app=nvidia-dra-driver-kubelet-plugin \
--field-selector spec.nodeName=problematic-node
# confirm the ResourceSlice updated correctly (wait 30 seconds after the restart)
sleep 30
kubectl get resourceslices --field-selector spec.nodeName=problematic-node -o yaml
Case 3: Existing Workloads Interrupted During a DRA Driver Upgrade
Symptom: while upgrading the DRA driver with Helm, the kubelet plugin DaemonSet's Pods restart and the GPU workloads running on those nodes throw device access errors.
Preventive measures:
- Drain the GPU workloads to other nodes before upgrading the DRA driver.
- Set the rolling update strategy to
maxUnavailable: 1so the driver restarts on only one node at a time. - For training workloads, enable checkpointing so training progress survives a driver restart.
Case 4: DeviceClass Matching Fails Because of a CEL Expression Error
Symptom: the DeviceClass was created but the ResourceClaim is never allocated. kubectl describe reports that no device matches.
Cause: the attribute name in the DeviceClass selectors.cel.expression is wrong, or the comparison value differs from what the device actually reports.
How to debug it:
# check the attribute names and values the device actually reports
kubectl get resourceslices -o json | \
jq '.items[0].spec.devices[0].basic.attributes'
# example output:
# {
# "gpu.nvidia.com": {
# "driverVersion": {"stringValue": "550.54.15"},
# "productName": {"stringValue": "NVIDIA A100 80GB PCIe"},
# "architecture": {"stringValue": "Ampere"},
# "cudaComputeCapability": {"versionValue": "8.0"},
# "memory": {"quantityValue": "80Gi"}
# }
# }
# confirm the attribute names used in the DeviceClass CEL expression match the output above exactly.
Case 5: The ResourceClaim Quota Is Exceeded
Symptom: the namespace's ResourceQuota rejects the ResourceClaim creation.
In a DRA environment you can set a per-namespace limit on the number of ResourceClaims. Be careful in particular with a Deployment that uses a ResourceClaimTemplate and has many replicas, since it can hit the quota faster than you expect.
Production Deployment Checklist
Work through the following checklist before deploying DRA-based GPU workloads to production.
Infrastructure preparation
- The upgrade to Kubernetes 1.32 or later is complete
- The
DynamicResourceAllocationfeature gate is enabled on kube-apiserver, kube-scheduler and kubelet - The NVIDIA DRA driver is installed and healthy on every GPU node
- ResourceSlices report each node's GPU information accurately
DeviceClass design
- A DeviceClass is defined for every GPU model in the cluster
- Per-MIG-profile DeviceClasses are defined where needed
- The DeviceClass CEL expressions match the real device attributes exactly (verified with a test ResourceClaim)
Workload configuration
resourceClaimsis referenced correctly in the Pod spec- The ResourceClaimTemplate is configured to suit the Deployment/Job workload
- Constraints are set on workloads that need GPU topology guarantees (NVLink and the like)
RBAC and security
- Per-namespace permission to create ResourceClaims is set appropriately
- Because DeviceClass is a cluster-scoped resource, only administrators can create or modify it
- A per-namespace limit on the number of ResourceClaims is set through ResourceQuota
Monitoring and alerting
- Collection of the DRA-related Prometheus metrics is configured
- An alert on pending ResourceClaims is configured (when pending 5 minutes or more)
- An alert on DRA driver errors is configured
- Dashboards for GPU utilization and per-DeviceClass availability are configured
Incident response
- The ResourceClaim recovery procedure for a node failure is documented
- The DRA driver upgrade procedure and a rollback plan are established
- GPU workload checkpointing is enabled (for training workloads)
- A rollback plan to the existing Extended Resource model is prepared (during the migration period)
Performance validation
- Confirm device allocation latency is within the acceptable range (p99 within 30 seconds)
- Confirm the scheduler's DRA-related throughput is sufficient for the workload scale
- Confirm the isolation performance of each slice in the MIG environment
References
- Kubernetes official documentation - 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