向 Pod 和容器分配设备
1 - 在集群中安装 DRA
Kubernetes v1.35 [stable](默认启用)本文介绍如何在 Kubernetes 集群中通过启用 API 组并配置设备类别来设置动态资源分配(DRA)。这些指示说明适用于集群管理员。
关于 DRA
Kubernetes 提供的一项特性,允许你在多个 Pod 之间请求和共享资源。
这些资源通常是挂接的设备,例如硬件加速器。
借助 DRA,设备驱动和集群管理员可以定义设备的类别,这些类别可供工作负载中的 Pod 申领。Kubernetes 会将匹配的设备分配给特定的申领,并将相应的 Pod 调度到能够访问这些已分配设备的节点上。
确保你已了解 DRA 的工作机制及其术语,例如DeviceClasses、ResourceClaims以及ResourceClaimTemplates。更多信息请参见动态资源分配(DRA)。
准备开始
你必须拥有一个 Kubernetes 的集群,且必须配置 kubectl 命令行工具让其与你的集群通信。建议运行本教程的集群至少有两个节点,且这两个节点不能作为控制平面主机。如果你还没有集群,你可以通过 Minikube 构建一个你自己的集群,或者你可以使用下面的 Kubernetes 练习环境之一:
你的 Kubernetes 服务器版本必须不低于版本 v1.34.要获知版本信息,请输入 kubectl version.
- 将设备直接或间接挂接到你的集群中。为避免驱动相关的问题,请在安装驱动之前先完成 DRA 特性的配置。
可选:启用额外的 DRA API 组
DRA 整体上已经是 Kubernetes 中的稳定特性;但其中的某些具体功能仍可能处于 Alpha 或 Beta 阶段。如果你希望使用尚未稳定的 DRA 相关能力,并且该能力依赖于某个专用的 API 类别,则你必须显式启用对应的 Alpha 或 Beta 级别的 API 组。一些较旧的 DRA 驱动或工作负载可能仍需要 Kubernetes 1.30 的 v1beta1 API或 Kubernetes 1.32 的 v1beta2 API。当且仅当需要支持这些时,才启用以下API 组:
resource.k8s.io/v1beta1resource.k8s.io/v1beta2
带有独立 API 类型的 Alpha 特性需要启用:
resource.k8s.io/v1alpha3
更多信息请参阅启用或禁用 API 组。
验证是否启用了 DRA
若要验证集群是否配置正确,可尝试列出 DeviceClass:
kubectl get deviceclasses
如果组件配置正确,输出类似如下:
No resources found
如果 DRA 未正确配置,则上述命令的输出可能如下:
error: the server doesn't have a resource type "deviceclasses"
例如,当 resource.k8s.io API 组被禁用时,就可能出现这种情况。类似的检查同样适用于处于 Alpha 或 Beta 阶段的顶层 API 类型。
你可以尝试以下排查步骤:
重新配置并重启
kube-apiserver组件。如果从 Pod 中完全删除了
.spec.resourceClaims字段,或者 Pod 在不考虑 ResourceClaim 的情况下被调度,那么请验证DynamicResourceAllocation特性门控在kube-apiserver、kube-controller-manager、kube-schedule或 kubelet 组件中是否被关闭。
安装设备驱动
你启用集群的 DRA 特性后,你可以安装所挂接设备的驱动。安装方式请参见设备所有者或驱动维护方提供的文档。你安装的驱动必须与 DRA 兼容。
若要验证驱动是否正常工作,可列出集群中的 ResourceSlice:
kubectl get resourceslices
输出示例如下:
NAME NODE DRIVER POOL AGE
cluster-1-device-pool-1-driver.example.com-lqx8x cluster-1-node-1 driver.example.com cluster-1-device-pool-1-r1gc 7s
cluster-1-device-pool-2-driver.example.com-29t7b cluster-1-node-2 driver.example.com cluster-1-device-pool-2-446z 8s
尝试以下故障排查步骤:
- 检查 DRA 驱动的健康状况,并在其日志输出中查找关于发布 ResourceSlice的错误消息。驱动的供应商可能有关于安装和故障排除的进一步指示。
创建 DeviceClass
你可以通过创建DeviceClasses定义设备的分类,供应用运维人员在工作负载中申领这些设备。某些设备驱动提供方也可能在驱动安装过程中要求你创建 DeviceClass。
你的驱动所发布的 ResourceSlice 中包含了设备的相关信息,例如容量、元数据和属性。你可以使用通用表达式语言(CEL) 表达式按 DeviceClass 中的属性进行筛选,从而帮助工作负载运维人员更轻松地找到合适的设备。
若要查看可通过 CEL 表达式在 DeviceClass 中选择的设备属性,你可以查看某个 ResourceSlice 的规约:
kubectl get resourceslice <resourceslice-name> -o yaml输出类似如下:
apiVersion: resource.k8s.io/v1 kind: ResourceSlice # 为简洁省略部分内容 spec: devices: - attributes: type: string: gpu capacity: memory: value: 64Gi name: gpu-0 - attributes: type: string: gpu capacity: memory: value: 64Gi name: gpu-1 driver: driver.example.com nodeName: cluster-1-node-1 # 为简洁省略部分内容你也可以查阅驱动提供商的文档,了解可用的属性和对应值。
查看以下 DeviceClass 示例清单,它选择所有由
driver.example.com设备驱动管理的设备:apiVersion: resource.k8s.io/v1beta2 kind: DeviceClass metadata: name: example-device-class spec: selectors: - cel: expression: |- device.driver == "driver.example.com"
在集群中创建 DeviceClass:
kubectl apply -f https://k8s.io/examples/dra/deviceclass.yaml
清理
要删除本任务中创建的 DeviceClass,运行以下命令:
kubectl delete -f https://k8s.io/examples/dra/deviceclass.yaml
接下来
2 - 使用 DRA 为工作负载分配设备
Kubernetes v1.35 [stable](默认启用)本文介绍如何使用动态资源分配(DRA) 为 Pod 分配设备。这些指示说明面向工作负载运维人员。在阅读本文之前,请先了解 DRA 的工作原理以及相关术语,例如ResourceClaim 和ResourceClaimTemplate。更多信息参阅动态资源分配(DRA)。
关于使用 DRA 分配设备
作为工作负载运维人员,你可以通过创建 ResourceClaim 或 ResourceClaimTemplate来申领工作负载所需的设备。当你部署工作负载时,Kubernetes 和设备驱动会找到可用的设备,将其分配给 Pod,并将 Pod 调度到可访问这些设备的节点上。
准备开始
你必须拥有一个 Kubernetes 的集群,且必须配置 kubectl 命令行工具让其与你的集群通信。建议运行本教程的集群至少有两个节点,且这两个节点不能作为控制平面主机。如果你还没有集群,你可以通过 Minikube 构建一个你自己的集群,或者你可以使用下面的 Kubernetes 练习环境之一:
你的 Kubernetes 服务器版本必须不低于版本 v1.34.要获知版本信息,请输入 kubectl version.
- 请确保集群管理员已安装好 DRA,挂接了设备并安装了驱动程序。详情请参见在集群中安装 DRA。
寻找可申领的设备
你的集群管理员或设备驱动程序会创建定义设备类别的DeviceClass。你可以使用通用表达式语言(CEL) 表达式筛选特定的设备属性,从而申领设备。
获取集群中的 DeviceClass 列表:
kubectl get deviceclasses
输出类似如下:
NAME AGE
driver.example.com 16m
如果你遇到权限错误,你可能无权获取 DeviceClass。请与你的集群管理员或驱动提供商联系,了解可用的设备属性。
申领资源
你可以通过ResourceClaim请求某个 DeviceClass 的资源。要创建 ResourceClaim,可以采用以下方式之一:
- 手动创建 ResourceClaim,如果你希望多个 Pod 共享相同设备,或希望申领在 Pod 生命期结束后仍然存在。
- 使用ResourceClaimTemplate,让 Kubernetes 为每个 Pod 生成并管理 ResourceClaim。如果你希望每个 Pod访问独立的、具有类似配置的设备,你可以创建 ResourceClaimTemplate。例如,在使用并行执行的Job 中,你可能希望多个 Pod 同时访问设备。
如果你在 Pod 中直接引用了特定 ResourceClaim,该 ResourceClaim 必须已存在于集群中。否则,Pod 会保持在 Pending 状态,直到申领被创建。你可以在 Pod 中引用自动生成的 ResourceClaim,但不推荐这样做,因为自动生成的 ResourceClaim 的生命期被绑定到了触发生成它的 Pod。
要创建申领资源的工作负载,请选择以下选项之一:
查看以下示例清单:
apiVersion: resource.k8s.io/v1
kind: ResourceClaimTemplate
metadata:
name: example-resource-claim-template
spec:
spec:
devices:
requests:
- name: gpu-claim
exactly:
deviceClassName: example-device-class
selectors:
- cel:
expression: |-
device.attributes["driver.example.com"].type == "gpu" &&
device.capacity["driver.example.com"].memory == quantity("64Gi")
此清单会创建一个 ResourceClaimTemplate,它请求属于 example-device-class
DeviceClass、且同时满足以下两个参数的设备:
- 属性
driver.example.com/type的值为gpu - 容量为
64Gi
创建 ResourceClaimTemplate 的命令如下:
kubectl apply -f https://k8s.io/examples/dra/resourceclaimtemplate.yaml
查看以下示例清单:
apiVersion: resource.k8s.io/v1
kind: ResourceClaim
metadata:
name: example-resource-claim
spec:
devices:
requests:
- name: single-gpu-claim
exactly:
deviceClassName: example-device-class
allocationMode: All
selectors:
- cel:
expression: |-
device.attributes["driver.example.com"].type == "gpu" &&
device.capacity["driver.example.com"].memory == quantity("64Gi")
此清单会创建一个 ResourceClaim,请求属于 example-device-class
DeviceClass、且同时满足以下两个参数的设备:
- 属性
driver.example.com/type的值为gpu - 容量为
64Gi
创建 ResourceClaim 的命令如下:
kubectl apply -f https://k8s.io/examples/dra/resourceclaim.yaml
使用 DRA 在工作负载中请求设备
要请求设备分配,请在 Pod 规约的 resourceClaims 字段中指定 ResourceClaim或 ResourceClaimTemplate,然后在容器的 resources.claims 字段中按名称请求具体的资源申领。你可以在 resourceClaims 中列出多个条目,并在不同容器中使用特定的申领。
查看以下 Job 示例:
apiVersion: batch/v1 kind: Job metadata: name: example-dra-job spec: completions: 10 parallelism: 2 template: spec: restartPolicy: Never containers: - name: container0 image: ubuntu:24.04 command: ["sleep", "9999"] resources: claims: - name: separate-gpu-claim - name: container1 image: ubuntu:24.04 command: ["sleep", "9999"] resources: claims: - name: shared-gpu-claim - name: container2 image: ubuntu:24.04 command: ["sleep", "9999"] resources: claims: - name: shared-gpu-claim resourceClaims: - name: separate-gpu-claim resourceClaimTemplateName: example-resource-claim-template - name: shared-gpu-claim resourceClaimName: example-resource-claim此 Job 中的每个 Pod 具备以下属性:
提供名为
separate-gpu-claim的 ResourceClaimTemplate 和名为shared-gpu-claim的 ResourceClaim 给容器使用。运行以下容器:
container0请求separate-gpu-claimResourceClaimTemplate 中定义的设备。container1和container2共享对shared-gpu-claimResourceClaim 中设备的访问。
创建 Job:
kubectl apply -f https://k8s.io/examples/dra/dra-example-job.yaml
尝试以下故障排查步骤:
- 当工作负载未如预期启动时,从 Job 到 Pod 再到 ResourceClaim 逐步深入检查,并使用
kubectl describe检查每个层级的对象,查看是否有状态字段或事件可以解释工作负载为何没有启动。 - 当创建 Pod 失败并显示
must specify one of:resourceClaimName, resourceClaimTemplateName时,检查pod.spec.resourceClaims中的所有条目是否正好设置了这些字段之一。如果是这样,那么可能是集群安装了一个针对 Kubernetes < 1.32 的 API 构建的 Pod 变更 Webhook。请与你的集群管理员合作检查这个问题。
清理
要删除本任务中创建的 Kubernetes 对象,请按照以下步骤操作:
删除示例 Job:
kubectl delete -f https://k8s.io/examples/dra/dra-example-job.yaml
运行以下其中一条命令来删除你的资源申领:
删除 ResourceClaimTemplate:
kubectl delete -f https://k8s.io/examples/dra/resourceclaimtemplate.yaml
删除 ResourceClaim:
kubectl delete -f https://k8s.io/examples/dra/resourceclaim.yaml