使用 DRA 安裝驅動程式並分配裝置

特性狀態: Kubernetes v1.34 [穩定] (預設啟用:true)

本教程將向你展示如何在叢集中安裝動態資源分配 (DRA) 驅動程式,以及如何結合 DRA API 使用它們將裝置分配給 Pod。本頁面適用於叢集管理員。

動態資源分配 (DRA) 允許叢集管理硬體資源的可用性和分配,以滿足基於 Pod 的硬體需求和偏好宣告。為了支援這一點,Kubernetes 內建元件(如 Kubernetes 排程器、kubelet 和 kube-controller-manager)和裝置所有者提供的第三方驅動程式(稱為 DRA 驅動程式)共同負責在 Pod 生命週期中通告、分配、準備、掛載、健康檢查、解除準備和清理資源。這些元件透過一系列 DRA 特定的 API(位於 resource.k8s.io API 組中)共享資訊,其中包括 DeviceClassesResourceSlicesResourceClaims,以及 Pod 規約本身中的新欄位。

目標

  • 部署示例 DRA 驅動程式
  • 使用 DRA API 部署請求硬體宣告的 Pod
  • 刪除具有宣告的 Pod

準備工作

你的叢集應該支援 RBAC。你可以在使用不同授權機制的叢集上嘗試本教程,但在這種情況下,你需要調整關於定義角色和許可權的步驟。

你需要一個 Kubernetes 叢集,並且 kubectl 命令列工具必須配置為與你的叢集通訊。建議在至少有兩個不是控制平面主機的節點組成的叢集上執行本教程。如果你還沒有叢集,可以使用 minikube 建立一個,或者你可以使用這些 Kubernetes 操場之一。

本教程已在 Linux 節點上進行測試,但可能也適用於其他型別的節點。

你的 Kubernetes 伺服器版本必須是 v1.34。

要檢查版本,請輸入 kubectl version

如果你的叢集目前沒有執行 Kubernetes 1.34,請查閱你計劃使用的 Kubernetes 版本的文件。

探索初始叢集狀態

你可以花一些時間觀察已啟用 DRA 的叢集的初始狀態,特別是如果你以前沒有廣泛使用過這些 API。如果你為本教程設定了一個新叢集,但未安裝驅動程式且尚未滿足 Pod 宣告,則這些命令的輸出將不顯示任何資源。

  1. 獲取 DeviceClasses 列表

    kubectl get deviceclasses
    

    輸出類似於:

    No resources found
    
  2. 獲取 ResourceSlices 列表

    kubectl get resourceslices
    

    輸出類似於:

    No resources found
    
  3. 獲取 ResourceClaimsResourceClaimTemplates 列表

    kubectl get resourceclaims -A
    kubectl get resourceclaimtemplates -A
    

    輸出類似於:

    No resources found
    No resources found
    

至此,你已確認 DRA 在叢集中已啟用並正確配置,並且尚未有任何 DRA 驅動程式向 DRA API 通告任何資源。

安裝示例 DRA 驅動程式

DRA 驅動程式是執行在叢集每個節點上的第三方應用程式,用於與該節點的硬體和 Kubernetes 內建的 DRA 元件進行介面。安裝過程取決於你選擇的驅動程式,但很可能以 DaemonSet 的形式部署到叢集中的所有節點或選定的節點(使用選擇器或類似機制)。

請查閱驅動程式的文件以獲取具體的安裝說明,其中可能包括 Helm chart、一組清單或其他部署工具。

本教程使用 kubernetes-sigs/dra-example-driver 倉庫中的示例驅動程式來演示驅動程式安裝。這個示例驅動程式向 Kubernetes 通告模擬 GPU,供你的 Pod 與之互動。

準備叢集以進行驅動程式安裝

為了簡化清理,建立一個名為 dra-tutorial 的名稱空間

  1. 建立名稱空間

    kubectl create namespace dra-tutorial 
    

在生產環境中,你可能會使用驅動程式供應商或你自己的組織釋出的或經過驗證的映象,並且你的節點需要能夠訪問託管驅動程式映象的映象倉庫。在本教程中,你將使用 dra-example-driver 的公共釋出映象來模擬訪問 DRA 驅動程式映象。

  1. 透過在叢集中的一個節點內執行以下命令來確認你的節點可以訪問該映象

    docker pull registry.k8s.io/dra-example-driver/dra-example-driver:v0.2.0
    

部署 DRA 驅動程式元件

對於本教程,你將使用 kubectl 單獨安裝關鍵的示例資源驅動程式元件。

  1. 建立表示此 DRA 驅動程式支援的裝置型別的 DeviceClass

    apiVersion: resource.k8s.io/v1
    kind: DeviceClass
    metadata:
      name: gpu.example.com
    spec:
      selectors:
      - cel: 
          expression: "device.driver == 'gpu.example.com'"
    kubectl apply --server-side -f http://k8s.io/examples/dra/driver-install/deviceclass.yaml
    
  2. 建立 ServiceAccount、ClusterRole 和 ClusterRoleBinding,驅動程式將使用它們來獲得與此叢集上的 Kubernetes API 互動的許可權。

    1. 建立服務賬號

      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: dra-example-driver-service-account
        namespace: dra-tutorial
        labels:
          app.kubernetes.io/name: dra-example-driver
          app.kubernetes.io/instance: dra-example-driver
      kubectl apply --server-side -f http://k8s.io/examples/dra/driver-install/serviceaccount.yaml
      
    2. 建立叢集角色

      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRole
      metadata:
        name: dra-example-driver-role
      rules:
      - apiGroups: ["resource.k8s.io"]
        resources: ["resourceclaims"]
        verbs: ["get"]
      - apiGroups: [""]
        resources: ["nodes"]
        verbs: ["get"]
      - apiGroups: ["resource.k8s.io"]
        resources: ["resourceslices"]
        verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
      kubectl apply --server-side -f http://k8s.io/examples/dra/driver-install/clusterrole.yaml
      
    3. 建立叢集角色繫結

      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRoleBinding
      metadata:
        name: dra-example-driver-role-binding
      subjects:
      - kind: ServiceAccount
        name: dra-example-driver-service-account
        namespace: dra-tutorial
      roleRef:
        kind: ClusterRole
        name: dra-example-driver-role
        apiGroup: rbac.authorization.k8s.io
      kubectl apply --server-side -f http://k8s.io/examples/dra/driver-install/clusterrolebinding.yaml
      
  3. 為 DRA 驅動程式建立一個 PriorityClass。PriorityClass 可防止 DRA 驅動程式元件被搶佔,該元件負責 Pod 生命週期中的重要操作。在此處瞭解有關 Pod 優先順序和搶佔的更多資訊

    apiVersion: scheduling.k8s.io/v1
    kind: PriorityClass
    metadata:
      name: dra-driver-high-priority
    value: 1000000
    globalDefault: false
    description: "This priority class should be used for DRA driver pods only."
    kubectl apply --server-side -f http://k8s.io/examples/dra/driver-install/priorityclass.yaml
    
  4. 部署實際的 DRA 驅動程式作為一個 DaemonSet,配置為使用上面提供的許可權執行示例驅動程式二進位制檔案。DaemonSet 具有你在前幾個步驟中授予 ServiceAccount 的許可權。

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: dra-example-driver-kubeletplugin
      namespace: dra-tutorial
      labels:
        app.kubernetes.io/name: dra-example-driver
    spec:
      selector:
        matchLabels:
          app.kubernetes.io/name: dra-example-driver
      updateStrategy:
        type: RollingUpdate
      template:
        metadata:
          labels:
            app.kubernetes.io/name: dra-example-driver
        spec:
          priorityClassName: dra-driver-high-priority
          serviceAccountName: dra-example-driver-service-account
          securityContext:
            {}
          containers:
          - name: plugin
            securityContext:
              privileged: true
            image: registry.k8s.io/dra-example-driver/dra-example-driver:v0.2.0
            imagePullPolicy: IfNotPresent
            command: ["dra-example-kubeletplugin"]
            resources:
              {}
            # Production drivers should always implement a liveness probe
            # For the tutorial we simply omit it
            # livenessProbe:
            #   grpc:
            #     port: 51515
            #     service: liveness
            #   failureThreshold: 3
            #   periodSeconds: 10
            env:
            - name: CDI_ROOT
              value: /var/run/cdi
            - name: KUBELET_REGISTRAR_DIRECTORY_PATH
              value: "/var/lib/kubelet/plugins_registry"
            - name: KUBELET_PLUGINS_DIRECTORY_PATH
              value: "/var/lib/kubelet/plugins"
            - name: NODE_NAME
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
            - name: NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            # Simulated number of devices the example driver will pretend to have.
            - name: NUM_DEVICES
              value: "9"
            - name: HEALTHCHECK_PORT
              value: "51515"
            volumeMounts:
            - name: plugins-registry
              mountPath: "/var/lib/kubelet/plugins_registry"
            - name: plugins
              mountPath: "/var/lib/kubelet/plugins"
            - name: cdi
              mountPath: /var/run/cdi
          volumes:
          - name: plugins-registry
            hostPath:
              path: "/var/lib/kubelet/plugins_registry"
          - name: plugins
            hostPath:
              path: "/var/lib/kubelet/plugins"
          - name: cdi
            hostPath:
              path: /var/run/cdi
    kubectl apply --server-side -f http://k8s.io/examples/dra/driver-install/daemonset.yaml
    

    DaemonSet 配置了必要的卷掛載,用於與底層容器裝置介面 (CDI) 目錄互動,並透過 kubelet/plugins 目錄將其套接字暴露給 kubelet

驗證 DRA 驅動程式安裝

  1. 獲取所有工作節點上 DRA 驅動程式 DaemonSet 的 Pod 列表

    kubectl get pod -l app.kubernetes.io/name=dra-example-driver -n dra-tutorial
    

    輸出類似於:

    NAME                                     READY   STATUS    RESTARTS   AGE
    dra-example-driver-kubeletplugin-4sk2x   1/1     Running   0          13s
    dra-example-driver-kubeletplugin-cttr2   1/1     Running   0          13s
    
  2. 每個節點的本地 DRA 驅動程式的初始職責是更新叢集中可供 Pod 使用的裝置,方法是將其元資料釋出到 ResourceSlices API。你可以檢查該 API,檢視每個帶有驅動程式的節點都在通告其所代表的裝置類。

    檢查可用的 ResourceSlices

    kubectl get resourceslices
    

    輸出類似於:

    NAME                                 NODE           DRIVER            POOL           AGE
    kind-worker-gpu.example.com-k69gd    kind-worker    gpu.example.com   kind-worker    19s
    kind-worker2-gpu.example.com-qdgpn   kind-worker2   gpu.example.com   kind-worker2   19s
    

至此,你已成功安裝了示例 DRA 驅動程式,並確認了其初始配置。現在你可以使用 DRA 排程 Pod 了。

宣告資源並部署 Pod

要使用 DRA 請求資源,你需要建立 ResourceClaims 或 ResourceClaimTemplates,它們定義了你的 Pod 所需的資源。在示例驅動程式中,為模擬 GPU 裝置公開了一個記憶體容量屬性。本節將向你展示如何使用 通用表示式語言 在 ResourceClaim 中表達你的需求,在 Pod 規範中選擇該 ResourceClaim,並觀察資源分配。

本教程僅展示一個基本的 DRA ResourceClaim 示例。閱讀 動態資源分配 以瞭解更多關於 ResourceClaim 的資訊。

建立 ResourceClaim

在本節中,你將建立一個 ResourceClaim 並在 Pod 中引用它。無論宣告如何,deviceClassName 都是一個必需欄位,它將請求的範圍縮小到特定的裝置類。請求本身可以包含一個 通用表示式語言 表示式,該表示式引用管理該裝置類的驅動程式可能通告的屬性。

在此示例中,你將建立一個請求,要求任何通告超過 10Gi 記憶體容量的 GPU。從示例驅動程式公開容量的屬性形式為 device.capacity['gpu.example.com'].memory。另請注意,宣告的名稱設定為 some-gpu

apiVersion: resource.k8s.io/v1
kind: ResourceClaim
metadata:
 name: some-gpu
 namespace: dra-tutorial
spec:
   devices:
     requests:
     - name: some-gpu
       exactly:
         deviceClassName: gpu.example.com
         selectors:
         - cel:
             expression: "device.capacity['gpu.example.com'].memory.compareTo(quantity('10Gi')) >= 0"
kubectl apply --server-side -f http://k8s.io/examples/dra/driver-install/example/resourceclaim.yaml

建立引用該 ResourceClaim 的 Pod

下面是 Pod 清單,它在 spec.resourceClaims.resourceClaimName 欄位中引用了你剛剛建立的 ResourceClaim some-gpu。然後,該宣告的本地名稱 gpu 用於 spec.containers.resources.claims.name 欄位,以將宣告分配給 Pod 的底層容器。

apiVersion: v1
kind: Pod
metadata:
  name: pod0
  namespace: dra-tutorial
  labels:
    app: pod
spec:
  containers:
  - name: ctr0
    image: ubuntu:24.04
    command: ["bash", "-c"]
    args: ["export; trap 'exit 0' TERM; sleep 9999 & wait"]
    resources:
      claims:
      - name: gpu
  resourceClaims:
  - name: gpu
    resourceClaimName: some-gpu
kubectl apply --server-side -f http://k8s.io/examples/dra/driver-install/example/pod.yaml
  1. 確認 Pod 已部署

    kubectl get pod pod0 -n dra-tutorial
    

    輸出類似於:

    NAME   READY   STATUS    RESTARTS   AGE
    pod0   1/1     Running   0          9s
    

探索 DRA 狀態

建立 Pod 後,叢集會嘗試將該 Pod 排程到 Kubernetes 可以滿足 ResourceClaim 的節點。在本教程中,DRA 驅動程式部署在所有節點上,並在所有節點上通告模擬 GPU,所有這些 GPU 都通告了足夠的容量來滿足 Pod 的宣告,因此 Kubernetes 可以將此 Pod 排程到任何節點,並可以分配該節點上的任何模擬 GPU。

當 Kubernetes 將模擬 GPU 分配給 Pod 時,示例驅動程式會在每個分配給它的容器中新增環境變數,以指示真正的資源驅動程式將會注入哪些 GPU 以及如何配置它們,因此你可以檢查這些環境變數以檢視系統如何處理 Pod。

  1. 檢查 Pod 日誌,其中報告了已分配的模擬 GPU 的名稱

    kubectl logs pod0 -c ctr0 -n dra-tutorial | grep -E "GPU_DEVICE_[0-9]+=" | grep -v "RESOURCE_CLAIM"
    

    輸出類似於:

    declare -x GPU_DEVICE_0="gpu-0"
    
  2. 檢查 ResourceClaim 物件的狀態

    kubectl get resourceclaims -n dra-tutorial
    

    輸出類似於:

    NAME       STATE                AGE
    some-gpu   allocated,reserved   34s
    

    在此輸出中,STATE 列顯示 ResourceClaim 已分配並保留。

  3. 檢查 some-gpu ResourceClaim 的詳細資訊。ResourceClaim 的 status 節包含有關已分配裝置及其已保留的 Pod 的資訊。

    kubectl get resourceclaim some-gpu -n dra-tutorial -o yaml
    

    輸出類似於:

     1apiVersion: resource.k8s.io/v1
     2kind: ResourceClaim
     3metadata:
     4    creationTimestamp: "2025-08-20T18:17:31Z"
     5    finalizers:
     6    - resource.kubernetes.io/delete-protection
     7    name: some-gpu
     8    namespace: dra-tutorial
     9    resourceVersion: "2326"
    10    uid: d3e48dbf-40da-47c3-a7b9-f7d54d1051c3
    11spec:
    12    devices:
    13        requests:
    14        - exactly:
    15            allocationMode: ExactCount
    16            count: 1
    17            deviceClassName: gpu.example.com
    18            selectors:
    19            - cel:
    20                expression: device.capacity['gpu.example.com'].memory.compareTo(quantity('10Gi'))
    21                >= 0
    22        name: some-gpu
    23status:
    24    allocation:
    25        devices:
    26        results:
    27        - device: gpu-0
    28            driver: gpu.example.com
    29            pool: kind-worker
    30            request: some-gpu
    31        nodeSelector:
    32        nodeSelectorTerms:
    33        - matchFields:
    34            - key: metadata.name
    35            operator: In
    36            values:
    37            - kind-worker
    38    reservedFor:
    39    - name: pod0
    40        resource: pods
    41        uid: c4dadf20-392a-474d-a47b-ab82080c8bd7

  4. 要檢查驅動程式如何處理裝置分配,請獲取驅動程式 DaemonSet Pod 的日誌

    kubectl logs -l app.kubernetes.io/name=dra-example-driver -n dra-tutorial
    

    輸出類似於:

    I0820 18:17:44.131324       1 driver.go:106] PrepareResourceClaims is called: number of claims: 1
    I0820 18:17:44.135056       1 driver.go:133] Returning newly prepared devices for claim 'd3e48dbf-40da-47c3-a7b9-f7d54d1051c3': [{[some-gpu] kind-worker gpu-0 [k8s.gpu.example.com/gpu=common k8s.gpu.example.com/gpu=d3e48dbf-40da-47c3-a7b9-f7d54d1051c3-gpu-0]}]
    

你現在已經成功部署了一個使用 DRA 宣告裝置的 Pod,驗證了該 Pod 已排程到合適的節點,並看到相關的 DRA API 種類已更新為分配狀態。

刪除具有宣告的 Pod

當帶有宣告的 Pod 被刪除時,DRA 驅動程式會解除分配資源,以便將來可以用於排程。為了驗證此行為,請刪除你在前幾個步驟中建立的 Pod,並觀察 ResourceClaim 和驅動程式的相應更改。

  1. 刪除 pod0 Pod

    kubectl delete pod pod0 -n dra-tutorial
    

    輸出類似於:

    pod "pod0" deleted
    

觀察 DRA 狀態

當 Pod 被刪除時,驅動程式會從 ResourceClaim 中解除分配裝置,並更新 Kubernetes API 中的 ResourceClaim 資源。ResourceClaim 處於 pending 狀態,直到在新的 Pod 中引用它。

  1. 檢查 some-gpu ResourceClaim 的狀態

    kubectl get resourceclaims -n dra-tutorial
    

    輸出類似於:

    NAME       STATE     AGE
    some-gpu   pending   76s
    
  2. 透過檢查驅動程式日誌,驗證驅動程式已處理此宣告的裝置解除準備操作。

    kubectl logs -l app.kubernetes.io/name=dra-example-driver -n dra-tutorial
    

    輸出類似於:

    I0820 18:22:15.629376       1 driver.go:138] UnprepareResourceClaims is called: number of claims: 1
    

你現在已刪除一個帶有宣告的 Pod,並觀察到驅動程式採取了行動來解除底層硬體資源的準備,並更新 DRA API 以反映該資源再次可用於將來的排程。

清理

要清理你在本教程中建立的資源,請按照以下步驟操作

kubectl delete namespace dra-tutorial
kubectl delete deviceclass gpu.example.com
kubectl delete clusterrole dra-example-driver-role
kubectl delete clusterrolebinding dra-example-driver-role-binding
kubectl delete priorityclass dra-driver-high-priority

下一步

最後修改於太平洋標準時間 2025 年 8 月 27 日上午 4:08:修復映象標籤拼寫錯誤,簡化前提條件 (b5ca1c9e43)