使用 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 組中)共享資訊,其中包括 DeviceClasses、ResourceSlices、ResourceClaims,以及 Pod 規約本身中的新欄位。
目標
- 部署示例 DRA 驅動程式
- 使用 DRA API 部署請求硬體宣告的 Pod
- 刪除具有宣告的 Pod
準備工作
你的叢集應該支援 RBAC。你可以在使用不同授權機制的叢集上嘗試本教程,但在這種情況下,你需要調整關於定義角色和許可權的步驟。
你需要一個 Kubernetes 叢集,並且 kubectl 命令列工具必須配置為與你的叢集通訊。建議在至少有兩個不是控制平面主機的節點組成的叢集上執行本教程。如果你還沒有叢集,可以使用 minikube 建立一個,或者你可以使用這些 Kubernetes 操場之一。
本教程已在 Linux 節點上進行測試,但可能也適用於其他型別的節點。
你的 Kubernetes 伺服器版本必須是 v1.34。要檢查版本,請輸入 kubectl version。
如果你的叢集目前沒有執行 Kubernetes 1.34,請查閱你計劃使用的 Kubernetes 版本的文件。
探索初始叢集狀態
你可以花一些時間觀察已啟用 DRA 的叢集的初始狀態,特別是如果你以前沒有廣泛使用過這些 API。如果你為本教程設定了一個新叢集,但未安裝驅動程式且尚未滿足 Pod 宣告,則這些命令的輸出將不顯示任何資源。
獲取 DeviceClasses 列表
kubectl get deviceclasses輸出類似於:
No resources found獲取 ResourceSlices 列表
kubectl get resourceslices輸出類似於:
No resources found獲取 ResourceClaims 和 ResourceClaimTemplates 列表
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 的名稱空間
建立名稱空間
kubectl create namespace dra-tutorial
在生產環境中,你可能會使用驅動程式供應商或你自己的組織釋出的或經過驗證的映象,並且你的節點需要能夠訪問託管驅動程式映象的映象倉庫。在本教程中,你將使用 dra-example-driver 的公共釋出映象來模擬訪問 DRA 驅動程式映象。
透過在叢集中的一個節點內執行以下命令來確認你的節點可以訪問該映象
docker pull registry.k8s.io/dra-example-driver/dra-example-driver:v0.2.0
部署 DRA 驅動程式元件
對於本教程,你將使用 kubectl 單獨安裝關鍵的示例資源驅動程式元件。
建立表示此 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建立 ServiceAccount、ClusterRole 和 ClusterRoleBinding,驅動程式將使用它們來獲得與此叢集上的 Kubernetes API 互動的許可權。
建立服務賬號
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-driverkubectl apply --server-side -f http://k8s.io/examples/dra/driver-install/serviceaccount.yaml建立叢集角色
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建立叢集角色繫結
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.iokubectl apply --server-side -f http://k8s.io/examples/dra/driver-install/clusterrolebinding.yaml
為 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部署實際的 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/cdikubectl apply --server-side -f http://k8s.io/examples/dra/driver-install/daemonset.yamlDaemonSet 配置了必要的卷掛載,用於與底層容器裝置介面 (CDI) 目錄互動,並透過
kubelet/plugins目錄將其套接字暴露給kubelet。
驗證 DRA 驅動程式安裝
獲取所有工作節點上 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每個節點的本地 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-gpukubectl apply --server-side -f http://k8s.io/examples/dra/driver-install/example/pod.yaml
確認 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。
檢查 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"檢查 ResourceClaim 物件的狀態
kubectl get resourceclaims -n dra-tutorial輸出類似於:
NAME STATE AGE some-gpu allocated,reserved 34s在此輸出中,
STATE列顯示 ResourceClaim 已分配並保留。檢查
some-gpuResourceClaim 的詳細資訊。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要檢查驅動程式如何處理裝置分配,請獲取驅動程式 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 和驅動程式的相應更改。
刪除
pod0Podkubectl delete pod pod0 -n dra-tutorial輸出類似於:
pod "pod0" deleted
觀察 DRA 狀態
當 Pod 被刪除時,驅動程式會從 ResourceClaim 中解除分配裝置,並更新 Kubernetes API 中的 ResourceClaim 資源。ResourceClaim 處於 pending 狀態,直到在新的 Pod 中引用它。
檢查
some-gpuResourceClaim 的狀態kubectl get resourceclaims -n dra-tutorial輸出類似於:
NAME STATE AGE some-gpu pending 76s透過檢查驅動程式日誌,驗證驅動程式已處理此宣告的裝置解除準備操作。
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