---
# System prepended metadata

title: Dynamically Allocate Devices to Workloads with DRA
tags: [ready-for-review]

---

**Reviewers: to add a comment, highlight some text in the rendered preview and click the Comment button**

---

# Dynamically Allocate Devices to Workloads with DRA

{{< feature-state feature_gate_name="DynamicResourceAllocation" >}}

<!-- overview --> 

This page shows you how to allocate devices to your Pods by using
_dynamic resource allocation (DRA)_. These instructions are for cluster
administrators and workload operators. 

## About dynamic resource allocation {#about-dra}

{{< glossary_definition term_id="dra" length="all" >}}

Ensure that you're familiar with how DRA works and with DRA terminology like
{{< glossary_tooltip text="DeviceClasses" term_id="deviceclass" >}},
{{< glossary_tooltip text="ResourceClaims" term_id="resourceclaim" >}}, and
{{< glossary_tooltip text="ResourceClaimTemplates" term_id="resourceclaimtemplate" >}}.
For details, see [Dynamic Resource Allocation (DRA)](/docs/concepts/scheduling-eviction/dynamic-resource-allocation/).

## {{% heading "prerequisites" %}}

{{< include "task-tutorial-prereqs.md" >}}

<!-- steps -->

## Attach devices and install drivers {#attach-devices-install-drivers}

For Kubernetes to identify and allocate resources using DRA, you must ensure that
those resources are attached to nodes and that DRA-compatible drivers are installed.
How you do this depends on the specific device and driver, so ensure that you
follow the relevant documentation. Before you proceed to
[Set up DRA in the cluster](#set-up-dra-cluster), ensure that the devices and drivers
are compatible with DRA.

## Set up DRA in the cluster {#set-up-dra-cluster}

To let Kubernetes dynamically allocate resources, complete the following configuration
steps:

1. Enable the DynamicResourceAllocation
   [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) on all
   of the following components:
   
   * `kube-apiserver`
   * `kube-controller-manager`
   * `kube-scheduler`
   * `kubelet`

1. Enable the following {{< glossary_tooltip text="API groups" term_id="api-group" >}}:

     * `resource.k8s.io/v1beta1`: required for DRA to function.
     * `resource.k8s.io/v1beta2`: optional, recommended improvements to the user
       experience.
     
   For more information, see
   [Enabling or disabling API groups](/docs/reference/using-api/#enabling-or-disabling).
   
1. To verify that the cluster is configured correctly, try to list DeviceClasses:

   ```shell
   kubectl get deviceclasses
   ```
   If your cluster supports DRA, the response is either a list of DeviceClasses
   or the following:

   ```
   No resources found
   ```
 
If DRA isn't correctly configured, the output of the preceding command is
similar to the following:
   
```
error: the server doesn't have a resource type "deviceclasses"
```
Try the following troubleshooting steps:

1. Ensure that the `kube-scheduler` component has the DynamicResourceAllocation
   feature gate enabled *and* uses the
   [v1 configuration API](/docs/reference/config-api/kube-scheduler-config.v1/).
   If you use a custom configuration, you might need to perform additional steps
   to enable the `DynamicResource` plugin.
1. Restart the `kube-apiserver` component and the `kube-controller-manager`
   component to propagate the API group changes.
   
## Create a DeviceClass {#create-deviceclass}

{{< glossary_definition term_id="deviceclass" length="all" >}}

In addition to any DeviceClasses that device drivers install by default, cluster
administrators can create custom DeviceClasses. You can use
[common expression language (CEL)](https://cel.dev) to perform fine-grained
filtering based on specific device attributes or capacity. The available parameters
for filtering depend on the device and the drivers.

1. Check whether the device drivers have created
   {{< glossary_tooltip term_id="resourceslice" text="ResourceSlices" >}} for the
   devices:
   
   ```shell
   kubectl get resourceslices
   ```
   The output is a list of available ResourceSlices. If the output doesn't display
   the specific device that you want, or if the output is empty, the driver hasn't
   registered the device yet.
   
1. Save the following example DeviceClass as `basic-dra-class.yaml`:

   ```yaml
   apiVersion: resource.k8s.io/v1beta2
   kind: DeviceClass
   metadata:
     name: example-device-class
   spec:
     selectors:
     - cel:
         expression: |-
           device.driver == "resource-driver.example.com"
   ```
   This DeviceClass lets you request devices that are managed by the
   `resource-driver.example.com` driver. 

1. Create the DeviceClass: 

   ```shell
   kubectl apply -f basic-dra-class.yaml
   ```

Workload operators can reference the DeviceClass in their ResourceClaims or
ResourceClaimTemplates, and can filter for specific device configurations in those
claims.

## Claim resources {#claim-resources}

You can request resources like devices from a DeviceClass by using a
{{< glossary_tooltip text="ResourceClaims" term_id="resourceclaim" >}}. You can
directly create a ResourceClaim or use a
{{< glossary_tooltip text="ResourceClaimTemplate" term_id="resourceclaimtemplate" >}}
to let Kubernetes generate and manage per-Pod ResourceClaims. 

### Create a ResourceClaim {#create-resourceclaim}

Manually create ResourceClaims if you want multiple Pods to share access to the
same devices, or if you want a claim to exist beyond the lifetime of a Pod.
If you directly reference a specific ResourceClaim in a Pod, that ResourceClaim
must already exist in the cluster. If a referenced ResourceClaim doesn't exist, the
Pod remains in a pending state until the ResourceClaim is created. 

You can reference an auto-generated ResourceClaim in a Pod, but this isn't
recommended because auto-generated ResourceClaims are bound to the lifetime of the Pod
that triggered the generation.

1. Save the following ResourceClaim as `basic-dra-resourceclaim.yaml`:

   ```yaml
   apiVersion: resource.k8s.io/v1beta2
   kind: ResourceClaim
   metadata:
     name: big-blue-claim
   spec:
     devices:
       constraints:
       - matchAttribute: "resource-driver.example.com/color"
       requests:
       - name: big-blue-request
         deviceClassName: example-device-class
         allocationMode: All
         selectors:
         - cel:
            expression: |-
              device.attributes["resource-driver.example.com"].color == "blue" &&
              device.attributes["resource-driver.example.com"].size == "big"
   ```
   This ResourceClaim requests devices in the `example-device-class` DeviceClass
   that match both of the following parameters:

   * `resource-driver.example.com/color` attribute with a value of `blue`
   * `resource-driver.example.com/size` attribute with a value of `big`

   The `constraints` field indicates that only devices that have an attribute named
   `resource-driver.example.com/color` can be allocated to this ResourceClaim.

1. Create the ResourceClaim: 

   ```shell
   kubectl apply -f basic-dra-resourceclaim.yaml
   ```

For every available field, see the
{{< api-reference page="workload-resources/resource-claim-v1beta2" text="ResourceClaim reference" >}}.

### Create a ResourceClaimTemplate {#create-resourceclaimtemplate}

Create a ResourceClaimTemplate if you want every Pod to have access to separate
devices that have similar configurations. For example, you might want simultaneous
access to devices for Pods in a Job that uses
[parallel execution](/docs/concepts/workloads/controllers/job/#parallel-jobs).

1. Save the following ResourceClaimTemplate as
   `basic-dra-resourceclaimtemplate.yaml`:

   ```yaml
   apiVersion: resource.k8s.io/v1beta2
   kind: ResourceClaimTemplate
   metadata:
     name: large-black-cat-claim-template
   spec:
     spec:
       devices:
         constraints:
         - matchAttribute: "resource-driver.example.com/cat"
         requests:
         - name: large-black-cat-claim
           deviceClassName: resource-driver.example.com
           selectors:
           - cel:
              expression: |-
                 device.attributes["resource-driver.example.com"].color == "black" &&
                 device.attributes["resource-driver.example.com"].size == "large"
   ``` 
   This ResourceClaimTemplate defines a ResourceClaim that does the following
   filtering:

   * Selects devices that have the following attributes:
       * `resource-driver.example.com/color` attribute with a value of `black`
       * `resource-driver.example.com/size` attribute with a value of `large`
   * Limits the devices that can be allocated to only devices that have the
     `resource-driver.example.com/cat` attribute.

1. Create the ResourceClaimTemplate: 

   ```shell
   kubectl apply -f basic-dra-resourceclaimtemplate.yaml
   ```

Kubernetes only generates ResourceClaims when you request this ResourceClaimTemplate
in a workload.

## Request devices in workloads using DRA {#request-devices-workloads}

To request device allocation, specify a ResourceClaim or a ResourceClaimTemplate
in the `resourceClaims` field of the Pod specification. Then, request a specific
claim by name in the `resources.claims` field of a container in that Pod.
You can specify multiple entries in the `resourceClaims` field and use specific
claims in different containers.

1. Save the following Job as `basic-dra-job.yaml`:

   ```yaml
   apiVersion: batch/v1
   kind: Job
   metadata:
     name: job-with-cats
   spec:
     completions: 10
     parallelism: 2
     template:
       spec:
         containers:
         - name: container0
           image: ubuntu:20.04
           command: ["sleep", "9999"]
           resources:
             claims:
             - name: cat-0
         - name: container1
           image: ubuntu:20.04
           command: ["sleep", "9999"]
           resources:
             claims:
             - name: cat-1
         resourceClaims:
         - name: cat-0
           resourceClaimTemplateName: large-black-cat-claim-template
         - name: cat-1
           resourceClaimName: big-blue-claim
   ```
   Each Pod in this Job has the following properties:
   
   * Makes a ResourceClaimTemplate named `cat-0` and a ResourceClaim named
     `cat-1` available to containers.
   * Runs the following containers:
       * `container0` requests the devices from the `cat-0` 
         ResourceClaimTemplate. 
       * `container1` requests the devices from the `cat-1` ResourceClaim.

1. Create the Job: 

   ```shell
   kubectl apply -f basic-dra-job.yaml
   ```

When you create this Job, devices are allocated as follows:

* `container0` in every Pod gets access to a separate device because the `cat-0`
  claim is a ResourceClaimTemplate.
* `container1` in every Pod shares access to a _specific_ device because the `cat-1`
  claim is a specific ResourceClaim. 
  
## {{% heading "whatsnext" %}}

- [Reduce the risk of hardware-related privilege escalation](TODO: concept for admin access and security guidance)
- [Good practices for dynamic resource allocation](TODO: good practices page)