动态资源分配

功能状态: Kubernetes v1.32 [beta](默认情况下禁用)

动态资源分配是一个用于请求和共享 Pod 和 Pod 内容器之间资源的 API。 它是用于通用资源的持久卷 API 的泛化。 通常这些资源是像 GPU 这样的设备。

第三方资源驱动程序负责跟踪和准备资源,资源的分配由 Kubernetes 通过结构化参数(在 Kubernetes 1.30 中引入)处理。 不同类型的资源支持用于定义需求和初始化的任意参数。

Kubernetes v1.26 到 v1.31 包括 经典 DRA 的(alpha)实现,该实现不再受支持。 本文档适用于 Kubernetes v1.32,解释了 Kubernetes 中动态资源分配的当前方法。

开始之前

Kubernetes v1.32 包括对动态资源分配的集群级 API 支持,但它需要显式启用。 你还必须为要使用此 API 管理的特定资源安装资源驱动程序。 如果你没有运行 Kubernetes v1.32,请查看该 Kubernetes 版本的文档。

API

resource.k8s.io/v1beta1 API 组提供了以下类型

ResourceClaim
描述了对集群中资源的访问请求,供工作负载使用。 例如,如果工作负载需要具有特定属性的加速器设备,则这是表达该请求的方式。 status stanza 跟踪此声明是否已满足以及已分配的特定资源。
ResourceClaimTemplate
定义了用于创建 ResourceClaims 的规范和一些元数据。 由用户在部署工作负载时创建。 然后 Kubernetes 会自动创建和删除每个 Pod 的 ResourceClaims。
DeviceClass
包含某些设备的预定义选择条件和它们的配置。 DeviceClasses 由集群管理员在安装资源驱动程序时创建。 分配 ResourceClaim 中设备的每个请求都必须引用一个 DeviceClass。
ResourceSlice
被 DRA 驱动程序用于发布有关集群中可用资源的信息。

选择设备的所有参数都在 ResourceClaim 和 DeviceClass 中使用内部类型定义。 配置参数可以嵌入在那里。哪些配置参数有效取决于 DRA 驱动程序 - Kubernetes 仅传递它们而不解释它们。

core/v1 PodSpec 定义了 Pod 在 resourceClaims 字段中需要的 ResourceClaims。 该列表中的条目引用 ResourceClaim 或 ResourceClaimTemplate。 当引用 ResourceClaim 时,使用此 PodSpec 的所有 Pod(例如,在 Deployment 或 StatefulSet 中)共享同一个 ResourceClaim 实例。 当引用 ResourceClaimTemplate 时,每个 Pod 都会获得自己的实例。

容器资源的 resources.claims 列表定义了一个容器是否可以访问这些资源实例,这使得在一个或多个容器之间共享资源成为可能。

这是一个虚构资源驱动程序的示例。 将为该 Pod 创建两个 ResourceClaim 对象,并且每个容器都可以访问其中一个对象。

apiVersion: resource.k8s.io/v1beta1
kind: DeviceClass
name: resource.example.com
spec:
  selectors:
  - cel:
      expression: device.driver == "resource-driver.example.com"
---
apiVersion: resource.k8s.io/v1beta1
kind: ResourceClaimTemplate
metadata:
  name: large-black-cat-claim-template
spec:
  spec:
    devices:
      requests:
      - name: req-0
        deviceClassName: resource.example.com
        selectors:
        - cel:
           expression: |-
              device.attributes["resource-driver.example.com"].color == "black" &&
              device.attributes["resource-driver.example.com"].size == "large"              
–--
apiVersion: v1
kind: Pod
metadata:
  name: pod-with-cats
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
    resourceClaimTemplateName: large-black-cat-claim-template

调度

调度器负责在 pod 需要资源时将资源分配给 ResourceClaim。 它通过从 ResourceSlice 对象检索可用资源的完整列表,跟踪哪些资源已被分配给现有的 ResourceClaims,然后从剩余的资源中进行选择来实现此目的。

目前唯一支持的资源类型是设备。 设备实例具有名称以及多个属性和容量。 设备通过检查这些属性和容量的 CEL 表达式进行选择。 此外,所选设备的集合也可以限制为满足某些约束的集合。

所选资源与任何特定于供应商的配置一起记录在 ResourceClaim 状态中,因此当 pod 即将在节点上启动时,节点上的资源驱动程序具有准备资源所需的所有信息。

通过使用结构化参数,调度器无需与任何 DRA 资源驱动程序通信即可做出决定。 它还可以通过将有关 ResourceClaim 分配的信息保存在内存中,并在后台将此信息写入 ResourceClaim 对象,同时将 pod 绑定到节点来快速调度多个 pod。

监控资源

kubelet 提供 gRPC 服务以启用正在运行的 Pod 的动态资源的发现。 有关 gRPC 端点的更多信息,请参阅资源分配报告

预先调度的 Pod

当你 - 或其他 API 客户端 - 创建一个 spec.nodeName 已设置的 Pod 时,调度器将被绕过。 如果该 Pod 需要的某些 ResourceClaim 尚不存在,未分配或未为 Pod 保留,则 kubelet 将无法运行 Pod 并定期重新检查,因为这些要求可能仍然会在以后得到满足。

当在调度 Pod 时调度程序中未启用对动态资源分配的支持时(版本偏差、配置、特性门控等),也可能出现这种情况。 kube-controller-manager 检测到这一点,并尝试通过保留所需的 ResourceClaims 使 Pod 可运行。 但是,这仅在这些 ResourceClaims 由调度器为其他 pod 分配时才有效。

最好避免绕过调度程序,因为分配给节点的 Pod 会阻止正常的资源(RAM、CPU),而这些资源在 Pod 被卡住时无法用于其他 Pod。 要使 Pod 在仍然经过正常调度流程的情况下在特定节点上运行,请使用完全匹配所需节点的节点选择器创建 Pod

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-cats
spec:
  nodeSelector:
    kubernetes.io/hostname: name-of-the-intended-node
  ...

你也可以在准入时更改传入的 Pod,以取消设置 .spec.nodeName 字段并使用节点选择器。

管理访问

功能状态: Kubernetes v1.32 [alpha](默认情况下禁用)

你可以将 ResourceClaim 或 ResourceClaimTemplate 中的请求标记为具有特权功能。 具有管理员访问权限的请求授予对正在使用的设备的访问权限,并可以在容器中提供设备时启用其他权限

apiVersion: resource.k8s.io/v1beta1
kind: ResourceClaimTemplate
metadata:
  name: large-black-cat-claim-template
spec:
  spec:
    devices:
      requests:
      - name: req-0
        deviceClassName: resource.example.com
        adminAccess: true

如果禁用此功能,则在创建此类 ResourceClaim 时,将自动删除 adminAccess 字段。

管理访问是一种特权模式,不应在多租户集群中提供给普通用户。 集群管理员可以通过安装类似于以下示例的验证准入策略来限制此功能的使用。 集群管理员至少需要调整名称并替换 “dra.example.com”。

# Permission to use admin access is granted only in namespaces which have the
# "admin-access.dra.example.com" label. Other ways of making that decision are
# also possible.

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: resourceclaim-policy.dra.example.com
spec:
  failurePolicy: Fail
  matchConstraints:
    resourceRules:
    - apiGroups:   ["resource.k8s.io"]
      apiVersions: ["v1alpha3", "v1beta1"]
      operations:  ["CREATE", "UPDATE"]
      resources:   ["resourceclaims"]
  validations:
    - expression: '! object.spec.devices.requests.exists(e, has(e.adminAccess) && e.adminAccess)'
      reason: Forbidden
      messageExpression: '"admin access to devices not enabled"'
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
  name: resourceclaim-binding.dra.example.com
spec:
  policyName:  resourceclaim-policy.dra.example.com
  validationActions: [Deny]
  matchResources:
    namespaceSelector:
      matchExpressions:
      - key: admin-access.dra.example.com
        operator: DoesNotExist
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: resourceclaimtemplate-policy.dra.example.com
spec:
  failurePolicy: Fail
  matchConstraints:
    resourceRules:
    - apiGroups:   ["resource.k8s.io"]
      apiVersions: ["v1alpha3", "v1beta1"]
      operations:  ["CREATE", "UPDATE"]
      resources:   ["resourceclaimtemplates"]
  validations:
    - expression: '! object.spec.spec.devices.requests.exists(e, has(e.adminAccess) && e.adminAccess)'
      reason: Forbidden
      messageExpression: '"admin access to devices not enabled"'
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
  name: resourceclaimtemplate-binding.dra.example.com
spec:
  policyName:  resourceclaimtemplate-policy.dra.example.com
  validationActions: [Deny]
  matchResources:
    namespaceSelector:
      matchExpressions:
      - key: admin-access.dra.example.com
        operator: DoesNotExist

ResourceClaim 设备状态

功能状态: Kubernetes v1.32 [alpha](默认情况下禁用)

驱动程序可以报告资源声明中每个已分配设备的特定于驱动程序的设备状态数据。 例如,分配给网络接口设备的 IP 可以在 ResourceClaim 状态中报告。

驱动程序设置状态时,信息的准确性取决于这些 DRA 驱动程序的实现。 因此,所报告的设备状态可能并不总是反映设备的实时状态变化。

禁用该功能时,存储 ResourceClaim 时会自动清除该字段。

当可以从 DRA 驱动程序更新 status.devices 字段已设置的现有 ResourceClaim 时,支持 ResourceClaim 设备状态。

启用动态资源分配

动态资源分配是一个beta 功能,默认情况下处于关闭状态,仅当启用 DynamicResourceAllocation 特性门控resource.k8s.io/v1beta1 API 组时才启用。 有关详细信息,请参阅 --feature-gates--runtime-config kube-apiserver 参数。 kube-scheduler、kube-controller-manager 和 kubelet 也需要特性门控。

当资源驱动程序报告设备状态时,除了 DynamicResourceAllocation 之外,还必须启用 DRAResourceClaimDeviceStatus 特性门控。

快速检查 Kubernetes 集群是否支持该功能的方法是使用以下命令列出 DeviceClass 对象

kubectl get deviceclasses

如果你的集群支持动态资源分配,则响应是 DeviceClass 对象列表,否则

No resources found

如果不支持,则会打印此错误

error: the server doesn't have a resource type "deviceclasses"

kube-scheduler 的默认配置仅当启用特性门控并且使用 v1 配置 API 时才启用 “DynamicResources” 插件。 可能需要修改自定义配置以包含它。

除了在集群中启用该功能外,还必须安装资源驱动程序。 有关详细信息,请参阅驱动程序的文档。

启用管理访问

管理员访问 是一个alpha 功能,只有在 kube-apiserver 和 kube-scheduler 中启用了 DRAAdminAccess 特性门控 时才会被启用。

启用设备状态

ResourceClaim 设备状态 是一个alpha 功能,只有在 kube-apiserver 中启用了 DRAResourceClaimDeviceStatus 特性门控 时才会被启用。

下一步是什么

最后修改时间:2024 年 11 月 19 日上午 11:15 PST:DRA:包含 v1beta1 API 参考 (26b5da0885)