【云原生】动态资源分配(DRA)深度洞察报告

news2025/3/16 0:24:06

1. DRA 的发展与设计灵感

Kubernetes 早期通过 Device Plugin(设备插件)机制支持 GPU、NIC 等特殊硬件,将节点上可用设备数量上报给 kubelet 和调度器。但设备插件模式存在局限:调度器只能根据节点标签等属性粗粒度筛选,无法精准指定某型号/属性的设备;此外调度器与设备插件缺乏联动,可能把 Pod 调度到尚未准备好相应设备的节点上。结果就是难以满足复杂场景下对特定硬件的精细化需求。

为解决上述问题,Kubernetes 引入了 动态资源分配(Dynamic Resource Allocation, DRA) 新机制。DRA 借鉴了持久卷(Persistent Volume)动态供应的理念,将其泛化用于通用资源。它定义了一套类似 PVC/PV 的声明式接口,让外部第三方驱动负责实际资源管理,由 Kubernetes 根据资源声明自动协调调度和分配。通过 DRA,用户可以:在不同 Pod 或容器间共享同一个资源实例,根据自定义约束精确匹配所需资源,并在运行前按需初始化资源——这些都是传统设备插件难以实现的功能。

DRA 的演进历程体现了社区在探索通用设备管理方面的逐步改进。最初的 DRA 提案在 Kubernetes 1.26 引入(Alpha 特性),采用了PodScheduling(或称 PodSchedulingContext)中介对象让调度器和驱动通过 API 反复协调来选定资源。这种“驱动参与调度决策”的方案提供了高度灵活性(驱动可以定义任意参数决定如何选资源),但带来了复杂的多轮交互,并使集群自动扩缩容难以预测资源需求。因此社区在后续版本引入了“结构化参数”模型,对 DRA 设计进行重构。在 Kubernetes 1.30 起增加结构化参数支持,1.32 将其提升为默认实现,并移除了早期 Alpha 实现(即所谓“经典 DRA”)相关代码。新的 DRA 模型让资源参数对调度器透明,由调度器直接基于参数匹配分配资源,提高了调度效率和可预见性。这一演进过程体现了 DRA 设计在灵活性与系统协调性之间寻找平衡的发展思路。


2. DRA 的设计哲学

  • 统一抽象:
    DRA 将各种类型的可配置硬件资源抽象为统一的资源声明(ResourceClaim)来请求和使用。无论是 GPU、NPU、FPGA 还是特殊网卡,都通过类似的声明方式提出请求,由 Kubernetes 按照声明去满足。正如官方所述,DRA “是持久卷 API 在通用资源上的泛化”。这种统一模型意味着不同硬件资源不再需要各自定制核心调度逻辑,而是在相同框架下处理。通过在声明中附加结构化参数,用户可以细粒度指定资源要求(例如 GPU 型号、性能指标),Kubernetes 调度器则能够识别并据此筛选资源。相比设备插件时代只能通过节点标签挑选节点,DRA 提供了标准化的接口描述资源需求和属性,实现“一次设计,通用适配”不同设备类型。更重要的是,DRA 支持资源实例的共享和复用:例如多个 Pod 可以共享同一加速器实例,或同一 Pod 的多个容器共同使用由一个 ResourceClaim 提供的设备。这一切都在统一的抽象下完成,极大提高了灵活性。

  • 资源分层解耦:
    DRA 延续了 CSI 等架构的分层理念,将资源管理职责清晰地划分给调度器、控制器和节点插件三个层次。首先,调度器负责全局的资源调配决策:它根据集群中公布的可用资源信息,决定 Pod 应该落在哪个节点以及使用哪个具体资源。调度器本身并不直接了解硬件细节,而是利用结构化的资源描述(如属性、容量等)进行匹配过滤,然后预留所选资源供该 Pod 使用。其次,控制平面控制器(运行在 kube-controller-manager 中或作为独立运营商)处理资源声明的生命周期:当用户部署工作负载时,控制器会根据 Pod 模板自动创建相应的 ResourceClaim,对接管理员预先配置的资源类(DeviceClass),并在适当的时候删除不再使用的声明对象。最后,节点插件(Node Plugin) 聚焦单节点上的实际操作:由第三方驱动提供的守护进程运行在每个节点上,负责发现本节点上的可用设备,向控制平面报告这些资源(例如创建/更新 ResourceSlice 对象),并在收到调度决定后执行设备的准备和清理。这种分层解耦确保了 Kubernetes 核心调度逻辑与具体硬件实现解耦:调度器专注于“在哪个节点用哪些资源”,节点插件专注于“如何在该节点实现资源供给”,中间通过声明和对象状态协作,而 PodSchedulingContext 这类中介对象在新模型中已不再需要。总的来说,各层各司其职,使系统更加模块化和易于扩展维护。

  • 可插拔架构与可扩展性:
    DRA 设计的另一个核心理念是通过可插拔驱动实现对各种专用资源的支持,类似于 CSI 驱动之于存储。Kubernetes 本身并不内置 GPU、FPGA 等具体资源的管理逻辑,而是定义好了通用 API 和调度流程,将“发现、分配、初始化”这些资源特定的工作下放给第三方 资源驱动(Resource Driver)。每种类型的特殊硬件只需由供应商或社区提供相应的 DRA 驱动,即可接入 Kubernetes。例如,集群管理员安装某 GPU 厂商的 DRA 驱动后,创建对应的 DeviceClass 来定义这种设备的类别和选择参数。之后用户的工作负载就能通过引用该 DeviceClass 的 ResourceClaim 来申请该厂商的 GPU,加之必要的参数(比如显存大小、计算能力等)。由于驱动的存在,Kubernetes 调度器和 kubelet 无需了解显卡的内部细节,只需与驱动交互即可完成资源的分配与使用。这种架构极大增强了系统的可扩展性:新增硬件支持不需要修改 Kubernetes 本身,只需开发并部署一个符合 DRA 接口的驱动即可。值得一提的是,在最初的 Alpha 实现中,驱动拥有更大的自主权(可以通过自定义参数和 PodSchedulingContext 参与调度协商),而结构化参数模型则在一定程度上规范了接口形式。虽然这意味着未来若出现全新类型的硬件需求,可能需要先扩展 Kubernetes 对参数的支持,但在大多数场景下,这一可插拔框架已经能灵活满足当前和未来的资源类型接入需求。


3. DRA 在 Kubernetes 框架侧的实现

  1. 调度器中的 DRA 插件:
    DRA 引入了一款调度器插件(默认名为 DynamicResources)来扩展 kube-scheduler,使其具备感知和分配动态资源的能力。在调度流程中,该插件会在多个阶段介入以确保 Pod 获取所需的特殊资源:

    • 预过滤阶段(PreFilter):调度器检查待调度的 Pod 是否声明了 ResourceClaim,以及这些声明是否已绑定具体资源。如果声明尚未分配且策略要求延迟绑定,调度器将进入动态资源处理流程。
    • 过滤阶段(Filter):DRA 插件会根据每个候选节点上可用资源的情况,快速排除不满足要求的节点。例如,若某 Pod 需要一块具备特定属性(如型号、显存)的 GPU,插件将查询集群中记录可用设备的对象(即各节点的 ResourceSlice),判断某节点是否有空闲设备匹配 ResourceClaim 中的选择表达式。只有拥有满足条件设备的节点才能通过此过滤。
    • 预留阶段(Reserve):调度器从通过筛选的节点中选择出一个最优节点(同时考虑常规资源要求,如 CPU/Mem),并在内部暂时锁定该节点上的目标设备,以防止并发调度的其他 Pod 再次占用。
    • 预绑定阶段(PreBind):调度器把挑选出的设备信息和任何供应商相关的配置写入 ResourceClaim 的 .status 字段。例如,Claim 的状态会注明分配到哪个节点、选中的设备标识符,以及驱动要求的配置参数数据。更新完成后,调度器正式将 Pod 绑定到目标节点(设置 Pod 的 nodeName),使调度决定生效。

    与早期 Alpha 方案不同,调度器在整个过程中无需与驱动直接通信;它依赖预先由驱动公布的结构化资源数据即可做出决策。这不仅减少了调度过程的往返,提高了效率,也让调度器可以并行处理多个 Pod 的调度而不被外部请求阻塞。如果在最终绑定阶段出现竞争条件(例如另一个 Pod 抢先占用了设备导致当前预留的设备不可用),调度器还会回滚相应的 ResourceClaim 分配并重新尝试调度。总之,DRA 调度插件通过 Filter/Reserve/PreBind 等扩展点实现了特殊资源的感知与分配,把具体设备选择融入了调度决策过程,实现 Pod 调度和资源分配的一体化。

  2. 控制平面 Controller 与资源声明对象:
    为配合调度器完成上述流程,Kubernetes 在 API 层面引入了一组专门的资源对象来描述和跟踪动态资源的请求与供给。主要包括:DeviceClass(设备类)、ResourceClaim(资源声明)、ResourceClaimTemplate(资源声明模板)和 ResourceSlice(资源片段)。

    • DeviceClass 类似于存储中的 StorageClass,由集群管理员在安装某个资源驱动时预先创建,定义了这类设备的选择规则和默认配置。管理员可以创建一个 DeviceClass gpu.nvidia.com 来代表 NVIDIA GPU 设备,其内含的选择器指定由哪个驱动器提供(如 device.driver == "nvidia.com")。
    • ResourceClaim 则类似于 PVC,是用户或控制器发起的对某种资源的具体请求,包含了期望获取的资源类型和数量,以及选择/配置参数。
    • ResourceClaimTemplate 用于在工作负载(如 Deployment)的 PodSpec 中声明需要某类资源时自动产生 ResourceClaim。例如用户在 Pod 模板中引用某个 ResourceClaimTemplate,Kubernetes 控制器就会为每个 Pod 创建一个独立的 ResourceClaim 来满足其需求。
    • ResourceSlice(资源片段)由驱动在每个节点上发布,用于记录节点上可用的具体设备信息,包括设备名称、属性、容量等,供调度器在分配时参考。

    当调度发生前,ResourceClaim 处于未分配状态(status.allocation 为空)。调度器为 Pod 选定节点和设备后,会将设备信息写入 ResourceClaim 的 status,标记该 Claim 已分配预留给相应的 Pod。此时 kube-controller-manager 内的一个控制器也会关注这些变化,承担一些收尾工作,例如在 Pod 成功绑定节点后将 ResourceClaim 标记为“已预留”(Binding),或在 Pod 终止后删除不再使用的 ResourceClaim。
    在当前的结构化参数模型下,不再使用 PodSchedulingContext 对象进行调度协调。但为了兼容或处理某些边缘情况(例如 Pod 被静态指定到节点而绕过了调度器),kube-controller-manager 仍包含逻辑检查 Pod 对应的 ResourceClaim 是否已被正确分配和预留,必要时补偿分配,以避免 Pod 永久处于无法运行的状态。总体而言,控制平面的各个组件确保了 ResourceClaim 从创建、分配到释放的完整生命周期闭环。通过 ResourceClaim 和 DeviceClass 等对象,Kubernetes 将复杂的资源请求参数、分配决定记录在 API 对象中,这不仅让调度器和 kubelet 等组件可以协同工作,也为管理员和用户提供了观察和管理资源分配状态的窗口。

  3. Kubelet 中的 DRA Manager:
    当 Pod 经过调度器绑定到节点后,节点上的 kubelet 接过接力棒,负责最终将特殊资源交给 Pod 使用。Kubelet 启动了一个 DRA 管理器 来处理与资源驱动的交互。每种第三方资源驱动的节点插件通常通过 kubelet 的插件注册机制进行注册(类似 CSI 驱动的注册过程),注册时会使用 DeviceClass 对应的驱动名称。这样 kubelet 才能识别并调用该驱动的 gRPC 服务。

    对于一个即将在本节点运行的 Pod,kubelet 会检查其规范中的 resourceClaims 列表,找到对应的 ResourceClaim 对象。一旦发现这些 ResourceClaim 已由调度器分配了具体设备(即 ResourceClaim.status 中有了分配信息),kubelet 就会调用驱动的 NodePrepareResources gRPC 接口,请求驱动在节点上为这些资源做好准备。这个调用会将 Pod 需要的一个或多个 ResourceClaim 传递给驱动,并包含调度器记录的设备标识及相关参数。节点插件驱动据此执行实际操作,包括但不限于:检查设备是否空闲、为即将运行的容器做好设备初始化或配置工作,以及将设备暴露给容器使用。对于 GPU 设备,NodePrepareResources 可能无需太多配置即可返回成功;但对于 FPGA,驱动或许需要在这里下发比特流将 FPGA 配置成特定逻辑;又比如对于支持 SR-IOV 的智能网卡,驱动需要在这里为即将运行的 Pod 分配一个虚拟功能(VF)并挂载到容器网络命名空间。由于各种资源的准备操作是高度设备相关的,因此由厂商驱动在此实现自定义逻辑。准备完成后,驱动会通过 gRPC 响应返回设备引用给 kubelet。Kubernetes 使用了一套行业标准的设备接口 —— CDI(Container Device Interface) 来描述容器可用的设备。驱动通常返回一个或多个 CDI 设备字符串(例如形如 "vendor.com/device=name" 的标识),kubelet 据此将设备分配写入 Pod 的运行时配置。当 kubelet 调用容器运行时(如 containerd、CRI-O)启动容器时,这些 CDI 设备会被挂载/注入容器,使其拥有对硬件的访问权限。需要注意容器运行时需开启对 CDI 的支持。

    在 Pod 终止后,kubelet 会再次通过 gRPC 调用驱动的 NodeUnprepareResources 接口,让驱动执行清理操作。驱动应释放该 Pod 占用的设备,例如解除对设备的占用锁定、回收设备的临时配置或断开 VF 连接等,恢复设备到空闲状态以便后续 Pod 使用。如果 ResourceClaim 是一次性使用的(比如由模板创建且 Pod 已完成),kubelet 和驱动还会协调移除与该资源相关的临时文件或状态,然后 kube-controller-manager 会删除对应的 ResourceClaim 对象。通过 NodePrepare/NodeUnprepare 这一对接口,Kubernetes 完成了从调度到运行的最后闭环,确保设备的正确交接和善后。整个节点侧流程对上层而言是可插拔的 —— 新硬件只需提供对应实现即可挂接到 kubelet。而 kubelet 提供的 gRPC 服务也允许查询当前运行 Pod 的动态资源使用情况(例如外部监控系统可以通过 kubelet 提供的接口了解某 Pod 使用了哪块设备,这对于资源审计和监控很有价值)。


4. DRA 驱动层面的实现

  1. 驱动接口要点与 gRPC:
    开发一个 DRA 驱动与编写 CSI 存储驱动有异曲同工之处,需要实现规定的 gRPC 接口以与 kubelet 和 Kubernetes 协作。对于 DRA,驱动主要关心节点服务(Node Service) 接口,包括前述的 NodePrepareResources 和 NodeUnprepareResources。这些接口在 Kubernetes 源码中的 proto 定义明确了调用契约:NodePrepareResources 接受一组 ResourceClaim 请求,返回对应每个请求的处理结果;NodeUnprepareResources 则用于释放。驱动在启动时需要监听一个 Unix 域套接字,并使用约定的插件注册机制向 kubelet 注册自己的存在(通常在 /var/lib/kubelet/plugins_registry/ 下创建一个带有驱动名的注册文件)。注册过程中,驱动会表明自己的名称(必须与 DeviceClass.spec.driver 字段匹配)和所支持的接口版本,kubelet 据此建立起与驱动的 gRPC 通道。之后,当有 Pod 需要该驱动管理的资源时,kubelet 就会调用相应接口完成准备/清理。

    对于实现者来说,确保线程安全和幂等非常重要:kubelet 可能会因网络或系统原因重试 NodePrepare,因此驱动实现需能识别重复请求并保证不产生冲突。另外,NodeListAndWatchResources 是另一个接口,用于让驱动向 kubelet 报告节点上可用资源变化,其作用类似于传统设备插件的 ListAndWatch。当驱动在节点上监测到新设备接入或设备失效时,可以通过这个流式接口通知 kubelet 更新资源状态。不过在 DRA 结构化模型下,集群总体的资源可用信息主要通过 ResourceSlice 在控制平面反映,NodeListAndWatch 在当前实现中更多用于驱动内部同步和调试用途。

  2. 节点插件示例代码解析:
    一个完整的 DRA 驱动通常由集中控制器节点插件两部分组成,但在结构化参数模型下,其控制器逻辑相对简化,而节点插件是核心。我们以一个支持 GPU 的示例驱动来说明实现细节:

    • 资源发现(Discovery):
      节点插件启动时首先扫描本节点的硬件资源。例如,通过读取 /dev 或系统接口列出所有 GPU 设备,以及它们的属性(型号、显存大小、GPU UUID 等)。然后,节点插件需要将这些信息报告给 Kubernetes 控制平面。通常的做法是由驱动在集群中定义并维护对应的 ResourceSlice 对象。ResourceSlice 的设计允许驱动将一个节点上的多个设备信息打包发布。驱动会创建(或更新)属于本节点的 ResourceSlice,其中列出每个设备的名称(一个惟一标识符,如 PCI 地址或序列号)和属性、容量等元数据。ResourceSlice 还包含 nodeName 字段指向所属节点,以及一个 pool 信息用于分片管理。节点插件定期或在资源变动时更新 ResourceSlice,使调度器始终能获取最新的可用资源清单。

    • 调度适配(Allocation):
      当集群中有 Pod 提出资源请求(ResourceClaim)后,调度器会据此在 ResourceSlice 中寻找匹配的设备。如果某请求包含对 GPU 型号和显存的要求(通过 DeviceClass 的 selectors 或 ResourceClaim.spec.devices.selectors 表达),调度器将筛选出 ResourceSlice 中满足条件的设备列表,并挑选其中一个将其分配。调度结果写入 ResourceClaim.status,包括设备标识符和驱动配置数据。此时,从驱动的角度看,它并未直接参与上述调度决策过程,而是通过之前提供的 ResourceSlice 信息间接地影响了调度结果——这是结构化参数模型的特点。

      对于驱动开发者来说,需要确保 ResourceSlice 中公布的信息足够全面,能表达各种调度所需的筛选条件(比如添加恰当的 device.attributes)。同时驱动可以利用 DeviceClass 预先设定一些通用筛选规则,减少每次声明需要重复提供的参数。例如 DeviceClass 本身也支持 selectors,Pod 的 ResourceClaim 若引用某 DeviceClass,则自动继承其中定义的筛选条件。总之,调度适配阶段驱动的主要工作是在调度前提供准确的资源视图和筛选机制,使调度器能够正确地匹配请求到具体设备。

    • 设备准备与挂载(Preparation & Mounting):
      当 Pod 被调度到本节点后,节点插件正式介入执行 NodePrepareResources 调用。以 ResourceClaim 已分配具体 GPU 为例:kubelet 会将该 ResourceClaim(包含设备 ID)传给驱动的 NodePrepareResources 方法。示例驱动在收到请求后,会在其维护的设备列表中找到这个设备。如果设备当前空闲且状态正常,驱动即可着手为容器准备它。对于 GPU,一般准备工作可能包括检查驱动模块已加载、为容器创建设备文件和访问控制等。假设设备无需特殊初始化,则直接生成对应的 CDI 设备条目,比如 "vendor.com/gpu=0000:03:00.0-0x56a0" 并通过 NodePrepareResourcesResponse 返回给 kubelet。kubelet 随后将其加入容器的 CDI 设备清单,使容器启动时自动获得对该 GPU 设备的访问权限。如果驱动需要执行较复杂的初始化(如 FPGA 下发比特流),也可在此处完成。
      值得一提的是,CDI 提供了抽象设备标识的方法,驱动需要在节点预先安装相应的 CDI 规格文件,将实际设备路径与一个 CDI 名称关联。NodePrepareResources 返回的就是这个映射名,容器运行时据此查找并挂载实际的 /dev 设备进去,实现了对容器透明且标准的设备接入。

    • 资源回收(Unprepare):
      当 Pod 使用完毕(容器退出或 Pod 删除)时,kubelet 将调用 NodeUnprepareResources。示例驱动接收到该请求后,会执行和准备阶段相对应的清理操作。对于 GPU 场景下,可能需要释放设备的独占锁、移除临时的 CDI 设备文件等;在其他硬件场景下,还可能涉及撤销之前的配置(例如将 FPGA 恢复为空闲位流,或释放 SR-IOV 分配的 VF)。驱动在完成清理后向 kubelet 确认。随后 kubelet 就会卸载容器,移除设备访问。对于通过 ResourceClaimTemplate 创建的临时 ResourceClaim,对应的对象也会被删除,驱动应确保自身对该 Claim 的任何引用也一并清除。如果驱动需要在 ResourceClaim 删除前执行自定义清理,可以在 ResourceClaim 上添加自己的 finalizer,实现定制的删除处理顺序。总之,正确实现 NodeUnprepareResources 可确保设备状态良好地返回池中,不会因为上一个 Pod 的遗留设置而影响下一个 Pod。

值得注意的是,Kubernetes 提供了一些辅助库来简化 DRA 驱动的开发。例如,在最初 alpha 实现中,社区提供了样板代码用于集中控制器与调度器的交互,使驱动开发者只需关注具体的资源分配逻辑。随着新模型的采用,驱动控制器主要负责 ResourceSlice 等 CR 的维护,这部分可以直接使用 Kubernetes 客户端库来实现 watch/update 循环;节点插件部分则可以参考 Kubernetes 项目中的示例实现(如 test/e2e/dra 路径下的 ExamplePlugin)。在实际场景中,不同类型设备的驱动可能还需要和厂商提供的底层库或内核接口交互,如调用英伟达的管理库获取 GPU 拓扑信息,或调用专用 CLI 来控制 FPGA。这些都属于驱动的业务逻辑范畴,可以自由发挥,而 Kubernetes 只要求驱动遵守接口契约和使用定义的 CRD 来与系统集成。通过阅读和参考社区提供的 KEP 文档和示例代码,新硬件资源的接入成本已大大降低。


5. 完整 DRA 工作流回顾

综合以上组件,我们以一个实际流程梳理 DRA 从请求到分配再到释放的全过程:

  1. 用户提交 Pod
    开发人员在 Pod 模板中声明需要特殊资源。例如,在 PodSpec 的 resourceClaims 字段中引用一个 ResourceClaimTemplate,描述需要“一块 NVIDIA A100 GPU,加上20GB显存和特定驱动配置”。集群管理员事先已创建对应的 DeviceClass(如 nvidia.com/gpu)供该模板引用。用户提交 Deployment 或 Pod 后,控制器检测到其中的资源声明模板,于是自动创建了一个 ResourceClaim 对象表示该 Pod 所需的 GPU。该 ResourceClaim 指定了 deviceClassName 为 nvidia.com/gpu,以及选择器表达了对“A100型号且显存≥20Gi”的要求。此时 ResourceClaim 处于未分配状态。

  2. 调度器分配资源并选定节点
    当该 Pod 排入调度队列准备调度时,DRA 调度插件介入。它从集群中获取所有 GPU 资源的可用情况——这些信息由 NVIDIA 驱动通过 ResourceSlice 事先发布,例如节点 node1 上有4块不同的 GPU(包含若干A100),node2 上有2块等。调度器首先筛选出有满足请求条件(A100且空闲)的节点集合,然后调度器结合其它调度条件(CPU/Mem 空闲情况、拓扑约束等)选择了其中一个最合适的节点,比如 node1。随后,DRA 插件在调度决策中为该 Pod 预留 node1 上的一块具体 GPU(假设序列号为 GPU-1234)给这个 ResourceClaim,并将此分配结果写入 ResourceClaim.status。状态中记录了 nodeName=node1,deviceName=GPU-1234,以及相关的驱动参数(如显存分区模式等,如有)。完成资源分配标记后,调度器将 Pod 绑定到 node1 节点。

  3. 节点驱动准备资源
    node1 上运行的 kubelet 收到新 Pod 要求启动的通知。它看到 Pod 需要一个 GPU,并且对应的 ResourceClaim (status)已经指明应使用本节点的 GPU-1234。于是 kubelet 调用本地 NVIDIA 驱动的 NodePrepareResources gRPC 接口,传入该 ResourceClaim 的信息。NVIDIA 驱动的节点插件查找本机设备列表确认 GPU-1234 空闲可用,然后执行准备操作:加载必要的驱动内核模块、为容器创建设备节点以及设置访问控制等。如果该 GPU 支持 MIG 分区且请求指定了划分(假设 Pod 只需一半 GPU 算力),驱动还会在此刻将 GPU 划分出一个实例。准备完成后,驱动返回一个描述这个 GPU 实例的 CDI 设备名称,例如 "nvidia.com/gpu=GPU-1234-idx0"。kubelet 收到成功响应,便将该 CDI 设备加入容器配置,并开始创建容器。容器运行时(如 containerd)解析 CDI 名称,在 GPU 驱动预先提供的 CDI 规格文件中找到对应的实际设备(例如 /dev/nvidia0),将其挂载到容器的 /dev 中。最终,Pod 中的应用进程启动并拥有对所请求 GPU 资源的访问权。至此,从用户声明到实际获得硬件资源,DRA 的主要流程全部走通。

  4. 运行期监控(可选)
    Pod 运行过程中,Kubernetes 并不干涉已分配资源的使用,但提供了监控接口。kubelet 上的资源报告服务可允许管理员或监控系统查询当前节点上哪些 Pod 占用了哪些动态资源。这对于审计和性能分析很有帮助,例如运维人员可以通过该接口确定某 GPU 正在被哪个 Pod 使用,并结合 GPU 温度、功耗指标定位问题。DRA 驱动本身也可以上报更细粒度的状态信息,如利用率等(未来版本中ResourceClaim Device Status特性可能允许驱动直接更新 ResourceClaim.status.devices 字段来反映设备运行状态)。这些机制进一步完善了资源使用的可见性。

  5. Pod 结束和资源回收
    当用户的工作负载结束,Pod 删除或终止时,kubelet 会着手清理分配的 GPU。它调用 NVIDIA 驱动的 NodeUnprepareResources,传入此前的 ResourceClaim 标识 GPU-1234(以及 MIG 分区信息)。驱动收到请求后,撤销对该 GPU 的分配:如果划分了 MIG 实例则销毁该实例,恢复 GPU 为完整资源;清除容器环境中为该 Pod 配置的任何临时状态(例如释放显存、重置功率限制等)。完成后驱动确认释放成功。随后,kubelet 将容器停止并卸载。对于通过 ResourceClaimTemplate 创建的临时 ResourceClaim,kube-controller-manager 在确认对应 Pod 已删除后,会自动删掉这个 ResourceClaim 对象。GPU-1234 现在重新回到资源池中,ResourceSlice 会更新显示其空闲可用状态,调度器即可将它分配给后续的 Pod 请求使用。通过上述工作流可以看到,DRA 将 Kubernetes 现有的调度机制、声明式 API 与底层驱动的硬件操作有机结合,实现了从 Pod 提交到硬件就绪的全自动管理,大幅减少了人工介入和配置错误的可能。


6. 总结与展望

动态资源分配(DRA)的引入,标志着 Kubernetes 在管理通用硬件资源方面迈出了重要一步。通过借鉴持久卷的模式并结合结构化参数,DRA 实现了对 GPU、FPGA、专用网卡等设备资源的通用化、声明式管理,不仅解决了传统设备插件无法精细选取和缺乏调度协同的问题,还带来了资源共享、延迟绑定、初始化配置等能力。在当前(v1.32)实现中,DRA 已作为 Beta 特性提供,用户可开启 DynamicResourceAllocation 特性后体验其功能。得益于结构化参数模型,Kubernetes 调度器能够更好地预测和掌控资源分配,这对集群自动扩容等上层决策尤为关键——调度器透明地了解资源供需,Cluster Autoscaler 也就能基于 ResourceClaim 的需求判断是否需要增减节点,而不像早期方案那样因逻辑隐藏在驱动中而无法判断。可以预见,随着 DRA 走向 GA,更多的云厂商和硬件供应商会提供与之兼容的驱动,将各式各样的新硬件纳入 Kubernetes 的调度管理范畴。

事实上,目前社区已经在讨论将 DRA 扩展到管理网络和拓扑资源、实现组合型资源调度等更复杂的场景。例如,有提案探讨通过“代理”驱动将网络拓扑信息引入调度决策,同时仍利用原厂设备驱动的初始化能力;又比如,未来可能支持可分割设备(Partitionable Device)的动态分配,当单块加速器可按比例划分给多个 Pod 时,如何通过 DRA 接口控制和汇报(目前 v1.31 尚未完全支持动态划分,如 GPU SR-IOV)。这些都是 DRA 潜在的发展方向。

随着容器运行时对 CDI 等标准的支持逐渐完善,以及 Kubernetes 对硬件异构资源需求的不断提升,DRA 有望成为连接云原生调度和底层硬件的新干线。在不久的将来,我们或许会看到基于 DRA 的更丰富应用场景:例如 AI/ML 作业通过 DRA 精确选择具备特定算力的 GPU,电信网络工作负载使用 DRA 来调度专用加速卡,甚至用户通过 Kubernetes API 就能完成对裸机设备的动态配置和调度。总之,DRA 正将 Kubernetes 的调度疆界从传统的 CPU/内存扩展到整个数据中心的各种特殊硬件资源。在保持 Kubernetes 一贯的声明式和自动化优势的同时,DRA 仍有持续优化的空间,但其设计理念和框架已为未来打下坚实基础。从设备插件到 DRA,我们见证了 Kubernetes 资源管理的演进;展望未来,DRA 将在社区的推动下不断成熟,进一步释放云原生对异构硬件的潜力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2315717.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【论文笔记】Contrastive Learning for Compact Single Image Dehazing(AECR-Net)

文章目录 问题创新网络主要贡献Autoencoder-like Dehazing NetworkAdaptive Mixup for Feature PreservingDynamic Feature Enhancement1. 可变形卷积的使用2. 扩展感受野3. 减少网格伪影4. 融合空间结构信息 Contrastive Regularization1. 核心思想2. 正样本对和负样本对的构建…

vue项目如何实现条件查询?

目录 1.前端 2.后端 3.mybatis的sql语句 结语 1.前端 说白了就是,无论该参数是否是空字符串,都会传递到后端。(反正不是null就行)。 2.后端 在controller层中,使用RequestParam注解接收名为registerName的参数&…

在Linux中安装Nginx

上传nginx安装包 Nginx的安装包,从官方下载下来的是c语言的源码包,我们需要自己编译安装。具体操作步骤如下: 安装nginx 安装nginx运行时需要的依赖 yum install -y pcre pcre-devel zlib zlib-devel openssl openssl-devel 解压源码包到当…

【每日学点HarmonyOS Next知识】状态栏字体、生命周期、自定义对话框屏幕中间、透明度、tab居中

1、HarmonyOS 单页面如何控制状态栏字体颜色? 状态栏字体颜色可通过设置statusBarContentColor修改,参考文档如下: https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-window-V5 参考代码: import…

外贸企业可以申请网络专线吗?

在对外业务不断扩大的情况下,外贸企业对网络的需求愈发迫切。稳定、快速的网络连接不仅是企业开展国际业务的基础,更是提升竞争力的关键。外贸企业是否可以申请网络专线?如何选择适合的外贸网络专线服务?本文将为您详细解答。 网络…

阿里巴巴发布 R1-Omni:首个基于 RLVR 的全模态大语言模型,用于情感识别

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

QuickAPI 和 DBAPI 谁更香?SQL生成API工具的硬核对比(一)

最近低代码开发火得不行,尤其是能把数据库秒变API的工具,简直是开发者的救星。今天咱就聊聊两款国内玩家:QuickAPI(麦聪软件搞出来的低代码神器)和 DBAPI(开源社区的硬核作品)。这两货都能靠SQL…

Git使用(一)--如何在 Windows 上安装 Git:详细步骤指南

如果你想在 Windows 机器上安装 Git,可以按照以下详细指南进行操作。 第一步:下载 Git 可通过官网下载 适用于 Windows 的 Git 最新版本。 如果下载速度较慢,可以通过下面提供的百度网盘 链接下载安装包, https://git-scm.com/d…

C#-使用VisualStudio编译C#工程

一.创建csproj文件 二.创建源cs文件 三.生成解决方案 四.运行解决方案 五.VisualStudio功能列表 <1.代码格式化: CtrlKD完成代码整体格式化 <2.窗口布局 窗口->重置窗口布局 <3.引用查找&关联 <4.包管理 <5.日志输出级别 工具->选项->项目解决方案…

Qt常见面试题合集

零、基本概念 什么是信号槽? 信号槽类似于软件设计模式中的观察者模式&#xff0c;&#xff08;观察者模式是一种对象行为模式。它定义对象间的一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都得到通知并被自动更新。&#xf…

vscode编译器的一些使用问题

目录 解决pip不可用问题 检查VSCode的终端配置 解决pip不可用问题 eg&#xff1a; C:\Users\student>pip pip 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。 先找到系统环境变量 高级->环境变量 系统属性->Path 变量名随意&#xff0c;自己后续知道…

Docker 》》Docker Compose 》》network 网络 compose

docker 默认的网络 三种模式 # 列出所有当前主机上或Swarm集群上的网络 docker network ls#查看网络详情 docker network inspect network名称# 清除未使用的docker网络 docker network prune -f# 创建网络 ocker network create -d bridge 网络名称 docker network create –s…

【SpringMVC】深入解析使用 Postman 和浏览器模拟将单个与多个参数传递到后端的原理和后端接收参数的过程

SpringMVC—请求(Request) 访问不同的路径&#xff0c;就是发送不同的请求&#xff1b;在发送请求时&#xff0c;可能会带一些参数&#xff0c;所以学习Spring的请求&#xff0c;主要是学习如何传递参数到后端以及后端如何接收&#xff1b; 我们主要是使用 浏览器 和 Postman …

VSTO(C#)Excel开发10:启动和卸载顺序 事件处理 监视变化

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 源码指引&#xff1a;github源…

vue 仿deepseek前端开发一个对话界面

后端&#xff1a;调用deepseek的api&#xff0c;所以返回数据格式和deepseek相同 {"model": "DeepSeek-R1-Distill-Qwen-1.5B", "choices": [{"index": 0, "delta": {"role": "assistant", "cont…

UE5以插件的形式加载第三方库

之前在UE中加载第三方库的形式是以静态或者动态链接的形式加载但是不太容易复用。就想着能不能以插件的形式加载第三方库&#xff0c;这样直接把插件打包发行就可以复用了&#xff0c;之前也找过相应的教程但是很难找到比较简单易懂的教程&#xff0c;要么是比较复杂&#xff0…

Vue3全局化配置(ConfigProvider)

效果如下图&#xff1a; 在线预览 APIs ConfigProvider 参数说明类型默认值theme主题对象Theme{}abstractboolean是否不存在 DOM 包裹元素truetagstringConfigProvider 被渲染成的元素&#xff0c;abstract 为 true 时有效‘div’ Theme Type 名称说明类型默认值common?全…

Centos7系统基于docker下载ollama部署Deepseek-r1(GPU版不踩坑)

目录 一、Docker下载安装 二、Ollama安装 三、部署Deepseek-R1 一、Docker下载安装 1、更新源 sudo yum update -y 2、下载依赖包 yum install -y yum-utils device-mapper-persistent-data lvm2 3、添加docker远程仓库地址 yum-config-manager --add-repo http://down…

【工具】C#游戏防沉迷小工具

背景介绍 嘿&#xff0c;各位小伙伴&#xff01;今天想跟大家唠唠我为啥要搞这么个防沉迷小工具。 咱都清楚&#xff0c;现在这游戏啊&#xff0c;玩起来那叫一个带劲&#xff0c;但时间一长&#xff0c;不仅眼睛累&#xff0c;心也跟着累。有些游戏&#xff0c;规则定得挺有意…

深圳南柯电子|净水器EMC测试整改:水质安全与电磁兼容性的双赢

在当今注重健康生活的时代&#xff0c;净水器作为家庭用水安全的第一道防线&#xff0c;其性能与安全性备受关注。其中&#xff0c;电磁兼容性&#xff08;EMC&#xff09;测试是净水器产品上市前不可或缺的一环&#xff0c;它直接关系到产品在复杂电磁环境中的稳定运行及不对其…