HAMi 异构设备虚拟化之海光 DCU 实战:K8s 下的 VDCU 资源调度与纳管
之前通过一系列文章分析了 HAMI vGPU 部署使用以及背后的实现原理,本文则是分析海光 DCU 设备如何通过 HAMi 完成虚拟化,实现统一纳管与调度。
HAMi 系列文章推荐阅读~:
1. vDCU 相关命令
在这之前简单过一下海光 DCU 自带的 vDCU 功能如何使用。
1.1 查看物理 DCU 资源
|
|
1.2 拆分 vDCU
拆分 DCU 为 4 份,分别包含 5,15,20,20 个计算单元以及 4096,8192,8192,8192MiB 的显存
|
|
1.3 查看 vdcu 信息
|
|
1.4 销毁 vDCU
|
|
1.5 Docker 使用 vDCU
在容器启动的时候执行以下命令将 vDCU 挂载至容器内。以下命令表示用户在启动容器时,挂载第 0 号 vDCU 实例。
|
|
可以看到除了通过 –device 方式挂载 kfd、dri、mkfd 等设备文件之外,还额外挂载了一个 /etc/vdev/vdev0.conf
文件到容器里。
实际上这个文件就是 vDCU 的配置文件,内部记录了该 vDCU 的详细信息。
虽然看不到相关源码,不过可以肯定的是,驱动程序肯定会查看该文件是否存在,如果存在则说明当前使用的是 vDCU,然后根据该文件中的信息来找到对应的物理 DCU,以及 core、mem 等信息以完成限制。
接下来看下 HAMi 中如何使用 vDCU。
2.部署 HAMi
前提条件:
- dtk 驱动程序 >= 24.04
2.1 部署
使用 Helm 部署
|
|
ps:可以通过调整 HAMi 部署配置来自定义你的安装。
如果当前环境无法拉取在线镜像,可以指定镜像仓库
|
|
2.2 检查 Pod 运行情况
|
|
如果 hami-scheduler
Running 说明安装成功。
ps:对于 DCU 环境只会启动 hami-scheduler 一个 Pod。
3. 部署 hami-vdcu-device-plugin
对应的 DevicePlugin 也是用 HAMi 社区提供的版本。
先给 DCU 节点打上 label dcu=on
|
|
3.1 准备工作
然后做以下准备工作
创建 vdev 目录
|
|
将 dtk 复制到 /opt/dtk 目录
因为容器会统一挂载 /opt/dtk ,因此将其从部署目录 cp 到指定目录
|
|
注意:/opt/dtk-xx.xx.x
这个位置取决于之前部署 DTK 时指定的目录
3.2 部署
然后就可以开始部署了
从 https://github.com/Project-HAMi/dcu-vgpu-device-plugin 项目获取相关 yaml:
|
|
然后部署 device-plugin
|
|
3.3 检查 Pod 运行情况
确认相关组件都正常运行:
|
|
可以看到,几个 DCU 节点上的 dcu-vdcu-device-plugin 都运行正常。
至此,相关组件部署完成,接下来验证下 vDCU 能否正常使用了。
4. 验证 vdcu
4.1 查看 Node 资源
接下来就是查看节点资源情况,vdcu 是否正常注册。
|
|
这里的 hygon.com/dcunum: 32
就是 vdcu 数量,单节点 8 DCU,这里是做了 4 倍切分。
ps: 因为当前一块海光物理 DCU 只支持切分为 4 个 vDCU。
4.2 启动 Pod 使用 vdcu
完整 yaml 如下:
|
|
和 vGPU 类似,支持单独指定卡数、core、mem 等资源。
进入 Pod 后先 source 下环境变量
|
|
然后使用以下命令验证
|
|
正常输出如下:
|
|
Compute units
和 Global memory
就是我们前面指定的 core 和 mem。
至此,说明 HAMi vdcu 已经生效了。
4.3 注意事项
一些注意事项:
如果您的镜像不是 ‘dtk-embedded-image’,则需要在任务运行后安装
pciutiils
、libelf-dev
、kmod
,否则,像hy-smi
或hy-virtual
这样的 dcu 工具可能无法正常工作。不支持在 init 容器中共享 DCU,init 容器中带有 “hygon.com/dcumem” 的 pod 将永远不会被调度。
每个容器只能获取一个 vdcu。如果您想挂载多个 dcu 设备,则不应设置
hygon.com/dcumem
或hygon.com/dcucores
。
5. 实现分析
简单分析一下 vdcu-device-plugin,根据第一章中使用 vDCU 的步骤可知,vdcu-device-plugin
除了正常的上报设备信息,分配设备之外,还需要处理以下事情:
- 1)vDCU 配置文件维护
- 创建 Pod 时根据 yaml 中申请的 core、mem 生成对应的 vdcu 配置文件
- Pod 删除后也需要删除对应的配置文件
- 2)挂载 vDCU 配置文件到 Pod 中
- 只有这样驱动程序才知道将该 vDCU 限制在多少 core、mem
5.1 Register
首先是要将 DevicePlugin 注册到 Kubelet,这里用的是 device-plugin-manager
因此没有单独注册的代码,不过也可以看下在启动的时候做了哪些工作。
|
|
启动时通过dcgm.DeviceInfos()
获取 DCU 信息
|
|
DeviceInfos
具体实现
|
|
这块用的 CGO 调用 C 库实现的,大家感兴趣可以自行查看~
|
|
WatchAndRegister
该方法主要调用两个方法:
- RefreshContainerDevices:维护 vdcu 配置信息,Pod 删除后移除对应文件
- RegistrInAnnotation:将节点上的物理 DCU 信息记录到节点的 Annoation 上。
|
|
RefreshContainerDevices
根据 /usr/local/vgpu/dcu
目录下的文件和 Kubernetes 中的 Pod 信息,更新 vdcu 使用情况,并清理不再使用的 vdcu 配置文件,以确保设备状态信息与实际使用情况保持一致。
|
|
RegistrInAnnotation
将 Device 信息记录到 Node Annoation 上,这样 hami-scheduler 可以从 Annoation 中拿到每个节点上 DCU 的详细信息。
|
|
ListAndWatch
ListAndWatch 检测节点上的 DCU 并上报给 Kubelet,由 Kubelet 提交 kube-apiserver,最终更新到 Node 的 Resource 上。
ListAndWatch 方法内容如下:
|
|
看了下有部分无效代码,有用的下面这部分:
|
|
apiDevices
根据前面 Start
方法中获取到的 device 信息生成 fakeDevice 提交给 kubelet。
|
|
其中 Count 固定为 4,即每个 DCU 可以切分为 4 个 vdcu。
ps:因为目前海光 DCU 虚拟化功能在一张物理卡上支持最多 4 个 vDCU。
generateFakeDevs
|
|
然后在 generateFakeDevs
中在根据 Count 信息复制出足够数量的 fakedev,至此对 Kubelet 来说感知到的 dcu 数量将是 物理 dcu 数量的 4 倍。
Allocate
Allocate 则是包含了真正将 vDCU 分配给 Pod 的逻辑。
ps:因为没有单独的 container runtime,因此在 Allocate 中需要额外做一些工作,比如把
kfd、mkfd、dri、hygondriver、hyhal 等等设备或者目录挂载到 Pod 中。
|
|
和 hami-nvidia-device-plugin 一样的逻辑,在 hami-scheduler 的时候就已经把要分配的 device 选好了。
DecodePodDevices
device-plugin 这边只需要从 Annoation 中解析出来即可。
|
|
createvdevFiles
最后会创建一个 vdev 配置文件并挂载到 Pod 里
|
|
之前的 RefreshContainerDevices
方法维护的就是这里创建的 vdev 配置文件,当 Pod 删除后需要清理对应的目录。
|
|
createvdevFile 内容如下:
|
|
就是简单创建了一个文件,但是把相关信息都写到文件里了,后续驱动程序根据该配置文件就知道该 Pod 可以使用多少 core 多少 mem 了。
ps:和 vGPU 通过 env 传递信息的方式不同,但是作用都是一样的。
这部分逻辑和以下命令一致,都是用于创建 vDCU 配置文件。
|
|