kubevirt源码分析之谁分配了gpu_device(3)

devtools/2025/3/6 10:29:20/

目标

当一个launcher pod被创建时,它会请求资源 ,如下

    Requests:cpu:                                16devices.kubevirt.io/kvm:            1devices.kubevirt.io/tun:            1devices.kubevirt.io/vhost-net:      1ephemeral-storage:                  50Mhugepages-2Mi:                      8Gimemory:                             1574961152nvidia.com/GA102_GEFORCE_RTX_3090:  2

并且会在pod的环境变量中写入请求的显卡的ID :

declare -x PCI_RESOURCE_NVIDIA_COM_GA102_GEFORCE_RTX_3090="0000:e1:00.0,0000:e1:00.1,0000:01:00.0,0000:01:00.1"

我们可以看到两个3090的显卡被请求了,那么这个调度就会进入到k8s的调度系统中,k8s要负责为这个pod分配两块3090出来。 那么现在问题来了:

  • k8s是如何知道的哪个节点有空闲显卡的。
  • 谁给pod的环境变量中写入了显卡的id
  • 为什么请求了两个显卡却有4个Id,很明显,第2、4个id应该是声卡的id

k8s是如何知道哪个节点有空闲显卡的

根据copilot的解释,k8s会有个device选择的过程,这个是由k8s来处理的。 这个我们暂时放下不表。

谁给Pod的环境变量写入了显卡的id

我们合理的猜想有应该有三个地方:
virt-controller的updateStatus
virt-handler
virt-launcher

virt-controller(不是)

根据流程,sync函数主要是进行pod的编辑、创建和启动:编辑初始化的yaml,创建pod,并且启动pod。 其中创建和启动可以理解为一个步骤。 这时候pod还没有根据k8s的调试到任一节点,所以我们认为updateStatus会去操作获取pod。

但这也有点不对,因为virt-controller是一个调度级别的程序,它没有办法获取到每个节点的pci信息。

virt-handler(不是)

我们到现在还没有了解到virt-handler最终的目标是什么,为什么要有virt-handler这个程序。

在这里插入图片描述
根据官方的流程图,我们可以看到virt-handler才是真正的主导启动的一个程序,难道不是virt-launcher?

经过研究源码后,至少virt-handler也不是。

virt-launcher(不是)

virt-launcher是最后的接受方,他并不处理这些东西

gpu-device-plugin(是)

最终,发现还是gpu-device-plugin这个程序在处理这些东西,在allocate时,会返回一个ContainerResponses,其中包含envs变量,应该是k8s会将它的返回交给pod

type ContainerAllocateResponse struct {// List of environment variable to be set in the container to access one of more devices.Envs map[string]string `protobuf:"bytes,1,rep,name=envs,proto3" json:"envs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`// Mounts for the container.Mounts []*Mount `protobuf:"bytes,2,rep,name=mounts,proto3" json:"mounts,omitempty"`// Devices for the container.Devices []*DeviceSpec `protobuf:"bytes,3,rep,name=devices,proto3" json:"devices,omitempty"`// Container annotations to pass to the container runtimeAnnotations map[string]string `protobuf:"bytes,4,rep,name=annotations,proto3" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`// CDI devices for the container.CDIDevices           []*CDIDevice `protobuf:"bytes,5,rep,name=cdi_devices,json=cdiDevices,proto3" json:"cdi_devices,omitempty"`XXX_NoUnkeyedLiteral struct{}     `json:"-"`XXX_sizecache        int32        `json:"-"`
}

那么最合理的流程就是:

  • 1、virt-controller负责生成pod,规定pod的各个属性。
  • 2、k8s接收到pod后,会根据pod的请求进行调度,比如去各个节点查看gpu的剩余,如果有剩余,则请求分配gpu。
  • 3、gpu-device-plugin接收到请求后,会返回一个带有env的response,其中env就是最后virt-launcher pod中有的环境变量。
  • 4、k8s接收到gpu-device-plugin的返回后,会将该信息加入到Pod的初始的环境变量中,最后再启动pod。
  • 5、virt-handler在发现pod创建信息后,会继续一系列的处理,而不是由virt-launcher直接进行创建了。 可以理解virt-handler+virt-launcher才是一整套的nova-compute。
  • 6、最后,由virt-launcher进行启动,是的,virt-launcher还是会进行启动的。 只不过是由virt-handler来触发启动这个程序。

virt-handler

大概有这么几个作用:
virt-handler遍历pods目录,看看哪个是有virt-launcher的socket的,如果有,就证明这是个主机的Pod。
从k8s中拿到vmi,判断vmi要做的事儿,比如开机、关机、迁移啥的,通过socket去通知virt-launcher,让它去执行要做的操作。

声卡id的问题

前面我们说过,vfio-manager在使用vfio驱动gpu的时候,实际上是会连同声卡也给驱动上的。

总结

gpu的分配是由gpu-device-plugin来分配的,在使用allocated


http://www.ppmy.cn/devtools/164973.html

相关文章

go语言因为前端跨域导致无法访问到后端解决方案

前端服务8080访问后端8081这端口显示跨域了 ERROR Network Error AxiosError: Network Error at XMLHttpRequest.handleError (webpack-internal:///./node_modules/axios/lib/adapters/xhr.js:116:14) at Axios.request (webpack-internal:///./node_modules/axios/lib/core/A…

贪心算法精品题

1.找钱问题 本题的贪心策略在于我们希望就可能的保留作用大的5元 class Solution { public:bool lemonadeChange(vector<int>& bills) {std::map<int ,int> _map;for(auto ch:bills){if(ch 5) _map[ch];else if(ch 10){if(_map[5] 0) return false;else{_m…

*pu相关概念介绍

1. TPU(张量处理单元)​ ​定义:TPU(Tensor Processing Unit)是谷歌开发的专用芯片,针对机器学习中的张量运算进行优化,尤其擅长加速神经网络训练和推理​核心特点: ​架构:采用脉动阵列(systolic array)设计,数据像“脉搏”一样流动,减少内存访问延迟,高效处理矩…

R语言基础| 基本统计分析

写在前面 R语言拥有丰富的数据处理、统计分析和机器学习工具包&#xff0c;涵盖了从简单的描述统计到复杂的模型建立的各个方面。再加上数据的处理可以完美的衔接后续的可视化&#xff0c;这使得它成为处理各种类型和规模的数据集的理想选择。 完整R语言教程和测试数据可见&a…

DeepSeek开源周第四弹!DeepSeek开源三剑客:训练效率的“时空魔术师”与“资源管家”全解析

开篇语 AI训练场的效率革命正在悄然爆发——当传统流水线还在“单向龟速”中挣扎&#xff0c;DeepSeek的三把利刃已划破算力困局&#xff1a;DualPipe像手术刀般精准切割时间空洞&#xff0c;将GPU利用率推至极限&#xff1b;EPLB化身智能指挥家&#xff0c;让MoE模型的算力交…

八、Redis 过期策略与淘汰机制:深入解析与优化实践

Redis 过期策略与淘汰机制:深入解析与优化实践 Redis 作为基于内存的高性能数据库,如何管理过期的键(key)和当内存不足时如何淘汰数据,是影响 Redis 性能和稳定性的关键因素。本篇文章将深入解析 Redis 的过期 key 处理方式和数据淘汰策略,并结合实际应用场景,帮助开发…

【Flink银行反欺诈系统设计方案】4.Flink CEP 规则表刷新方式

【Flink银行反欺诈系统设计方案】4.Flink CEP 规则表刷新方式 概要1. **实现思路**2. **代码实现**2.1 定义POJO2.2 规则加载与动态更新2.3 动态规则更新与CEP模式匹配 3. **规则更新的触发机制**3.1 定期加载规则3.2 监听规则变化 4. **总结** 概要 在Flink CEP中&#xff0c…

快速熟悉JavaScript

目录 1.js的基本认知 2.js的基本语法 2.1 变量的声明 三个关键字的区别 2.2数据类型 2.2.1 基本数据类型 2.2.2 复杂数据类型 2.3对象的属性和方法 2.3.1属性 2.3.2访问方式 2.4.3动态操作 2.4.4方法 2.4字符串的常用属性和方法 2.5运算符 2.6逻辑控制语句 2.7函…