This page describes how Kubernetes allocates devices to workloads with dynamic resource allocation (DRA), and how pre-scheduled Pods interact with the process.
The following sections describe the workflow for the various types of DRA users and for the Kubernetes system during dynamic resource allocation.
ResourceSlice creation: drivers in the cluster create ResourceSlices that represent one or more devices in a managed pool of similar devices.
Workload creation: the cluster control plane checks new workloads for references to ResourceClaimTemplates or to specific ResourceClaims.
resourceclaim-controller generates ResourceClaims for the workload.ResourceSlice filtering: for every Pod, Kubernetes checks the ResourceSlices in the cluster to find a device that satisfies all of the following criteria:
Resource allocation: after finding an eligible ResourceSlice for a Pod's ResourceClaim, the Kubernetes scheduler updates the ResourceClaim with the allocation details. The scheduler uses a first-fit strategy and evaluates pools and ResourceSlices in lexicographical order by their names. Drivers can prioritize specific slices or pools by naming them appropriately. For details, see Naming and prioritization.
Pod scheduling: when resource allocation is complete, the scheduler places the Pod on a node that can access the allocated resource. The device driver and the kubelet on that node configure the device and the Pod's access to the device.
When you - or another API client - create a Pod with spec.nodeName already set, the scheduler gets bypassed.
If some ResourceClaim needed by that Pod does not exist yet, is not allocated
or not reserved for the Pod, then the kubelet will fail to run the Pod and
re-check periodically because those requirements might still get fulfilled later.
Such a situation can also arise when support for dynamic resource allocation was not enabled in the scheduler at the time when the Pod got scheduled (version skew, configuration, feature gate, etc.). kube-controller-manager detects this and tries to make the Pod runnable by reserving the required ResourceClaims. However, this only works if those were allocated by the scheduler for some other pod.
It is better to avoid bypassing the scheduler because a Pod that is assigned to a node blocks normal resources (RAM, CPU) that then cannot be used for other Pods while the Pod is stuck. To make a Pod run on a specific node while still going through the normal scheduling flow, create the Pod with a node selector that exactly matches the desired node:
apiVersion: v1
kind: Pod
metadata:
name: pod-with-cats
spec:
nodeSelector:
kubernetes.io/hostname: name-of-the-intended-node
...
You may also be able to mutate the incoming Pod, at admission time, to unset
the .spec.nodeName field and to use a node selector instead.
Kubernetes v1.36 [beta](enabled by default)Device Binding Conditions allow the Kubernetes scheduler to delay Pod binding until external resources, such as fabric-attached GPUs or reprogrammable FPGAs, are confirmed to be ready.
This waiting behavior is implemented in the PreBind phase of the scheduling framework. During this phase, the scheduler checks whether all required device conditions are satisfied before proceeding with binding.
This improves scheduling reliability by avoiding premature binding and enables coordination with external device controllers.
To use this feature, device drivers (typically managed by driver owners) must publish the
following fields in the Device section of a ResourceSlice. Cluster administrators
must enable the DRADeviceBindingConditions and DRAResourceClaimDeviceStatus feature
gates for the scheduler to honor these fields.
bindingConditions.status.conditions field of the associated ResourceClaim) before the Pod can be bound. These conditions typically represent readiness signals, such as DeviceAttached or DeviceInitialized.bindingFailureConditionsbindsToNodetrue, the scheduler records the selected node name in the
status.allocation.nodeSelector field of the ResourceClaim.
This does not affect the Pod's spec.nodeSelector. Instead, it sets a node selector
inside the ResourceClaim, which external controllers can use to perform node-specific
operations such as device attachment or preparation.All condition types listed in bindingConditions and bindingFailureConditions are evaluated
from the status.conditions field of the ResourceClaim.
External controllers are responsible for updating these conditions using standard Kubernetes
condition semantics (type, status, reason, message, lastTransitionTime).
The scheduler waits up to 600 seconds (default) for all bindingConditions to become True.
If the timeout is reached or any bindingFailureConditions are True, the scheduler
clears the allocation and reschedules the Pod.
A cluster administration can configure this timeout duration by editing the kube-scheduler configuration file.
An example of configuring this timeout in KubeSchedulerConfiguration is given below:
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: default-scheduler
pluginConfig:
- name: DynamicResources
args:
apiVersion: kubescheduler.config.k8s.io/v1
kind: DynamicResourcesArgs
bindingTimeout: 60s
Here is an example of a ResourceSlice that you might see in a cluster where there's a DRA driver in use, and that driver supports binding conditions:
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: gpu-slice-1
spec:
driver: dra.example.com
nodeSelector:
nodeSelectorTerms:
- matchExpressions:
- key: accelerator-type
operator: In
values:
- "high-performance"
pool:
name: gpu-pool
generation: 1
resourceSliceCount: 1
devices:
- name: gpu-1
attributes:
vendor:
string: "example"
model:
string: "example-gpu"
bindsToNode: true
bindingConditions:
- dra.example.com/is-prepared
bindingFailureConditions:
- dra.example.com/preparing-failed
This example ResourceSlice has the following properties:
accelerator-type=high-performance,
so that the scheduler uses only a specific set of eligible nodes.node-3) and sets
the status.allocation.nodeSelector field in the ResourceClaim to that node name.dra.example.com/is-prepared binding condition indicates that the device gpu-1
must be prepared (the is-prepared condition has a status of True) before binding.gpu-1 device preparation fails (the preparing-failed condition has a status of True), the scheduler aborts binding.Device binding conditions is controlled by the
DRADeviceBindingConditions feature gate
in the kube-apiserver and kube-scheduler.
Kubernetes v1.36 [alpha](disabled by default)Devices managed by DRA can have an underlying footprint composed of node-allocatable
resources, such as cpu, memory, hugepages, or ephemeral-storage.
This feature integrates these DRA-based requests into the scheduler's standard
accounting alongside regular Pod spec requests for these resources.
Users (PodSpec authors) can use a mixture of Pod-level resources, container-level resources, and resource claims with associated node-allocatable resources. These devices represent resources like CPUs or memory directly, or they could be accelerators, network interface cards, or other devices that require some host resources when allocated. The DRA driver will populate information in the ResourceSlice that tells the scheduler how to calculate the node allocatable resources when the device is allocated to a ResourceClaim. PodSpec authors do not need to make that calculation themselves.
When authoring a PodSpec using claims for these types of devices, there are a few things to be aware of:
DRA drivers declare this node allocatable resource footprint using the
nodeAllocatableResourceMappings field on devices within a ResourceSlice.
This mapping translates the requested DRA device or capacity into standard
resources that are tracked in the node's status.allocatable (note that extended
resources are not supported for this mapping). This is useful both for drivers that directly
expose native resources (like a CPU or Memory DRA driver) and for devices that
require auxiliary node dependencies (like an accelerator that needs host memory).
This mapping defines the translation of the requested DRA device or capacity units to the corresponding quantity of the node-allocatable resource. The scheduler calculates the exact quantity using:
capacityKey is not set, the
allocationMultiplier multiplies the device count allocated to the claim.
The allocationMultiplier defaults to 1 if not specified.capacityKey is set, it references a
capacity name defined in the device's capacity map. The scheduler looks
up the amount of that capacity consumed by the claim and multiplies it by
the allocationMultiplier.Here is an example where a CPU DRA driver exposes a CPU socket as a pool of 128
CPUs using DRA consumable capacity. The capacityKey links the consumed
cpu.example.com/cpu capacity directly to the node's standard cpu
allocatable resource:
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: my-node-cpus
spec:
driver: cpu.example.com
nodeName: my-node
pool:
name: socket-cpus
generation: 1
resourceSliceCount: 1
devices:
- name: socket0cpus
allowMultipleAllocations: true
capacity:
"cpu.example.com/cpu": "128"
nodeAllocatableResourceMappings:
cpu:
capacityKey: "cpu.example.com/cpu"
# allocationMultiplier defaults to 1 if omitted
- name: socket1cpus
allowMultipleAllocations: true
capacity:
"cpu.example.com/cpu": "128"
nodeAllocatableResourceMappings:
cpu:
capacityKey: "cpu.example.com/cpu"
# allocationMultiplier defaults to 1 if omitted
Here is an example of a resource slice where an accelerator requires an additional 8Gi of memory per device instance to function:
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: my-node-xpus
spec:
driver: xpu.example.com
nodeName: my-node
pool:
name: xpu-pool
generation: 1
resourceSliceCount: 1
devices:
- name: xpu-model-x-001
attributes:
example.com/model:
string: "model-x"
nodeAllocatableResourceMappings:
memory:
allocationMultiplier: "8Gi"
After a Pod is successfully bound to the node, the exact quantities of
node-allocatable resources allocated via DRA are included in the Pod's
status.nodeAllocatableResourceClaimStatuses field.
Node-allocatable resources is controlled by the
DRANodeAllocatableResources feature gate
in the kube-apiserver, kube-scheduler, and kubelet. While this feature is alpha,
the kubelet does not account for these resources when determining QoS classes,
configuring cgroups, or making eviction decisions.