NVIDIA GPU资源管理
针对容器模式的节点,提供了GPU的资源管理功能。具体包含GPU监控、资源分配和GPU共享。GPU监控支持NVIDIA GPU,包括amd64与arm64平台(jetson)。GPU资源分配支持jetson、比特大陆1684、昇腾310 GPU。GPU共享仅支持NVIDIA。
GPU监控
如果边缘节点是一个GPU设备,需要云端监控GPU资源情况,则在创建节点的时候,AI加速卡 选择 NVIDIA GPU或NVIDIA JETSON,如下图所示:

依赖条件
创建节点时如果选择了上述两种加速卡之一,云端会默认为其配置一个gpu-metrics系统应用,用于采集边缘gpu状态。gpu-metrics同时还依赖边缘GPU服务器的一些外部环境,主要包括:
- 边缘节点要求有NVIDIA GPU,可以是amd64架构的NVIDIA GPU,也可以是arm64架构的jetson gpu。
- 边缘节点安装了NVIDIA docker,具体安装方式参考官网。
- 边缘节点的docker runtime 设置为了NVIDIA。依赖NVIDIA docker 已安装。
- 边缘节点使用容器模式运行。
设置docker runtime为nvidia
设备Docker的默认runtime可能不是nvidia。可以通过执行 docker info | grep Runtime 查看docker的默认runtime。

如果不是nvidia,此时需要更改Docker的daemon.json配置文件,文件路径通常为/etc/docker/daemon.json,添加如下配置即可。
1{
2 "default-runtime": "nvidia",
3 "runtimes": {
4 "nvidia": {
5 "path": "/usr/bin/nvidia-container-runtime",
6 "runtimeArgs": []
7 }
8 }
9}
编辑完毕以后,重启docker,执行如下命令:
1sudo systemctl daemon-reload
2sudo systemctl restart docker
动态修改AI加速卡类型
如果创建节点时没有选择AI加速卡,后续可以在这里进行修改。

GPU资源分配device-plugin
GPU资源分配功能用于支持边缘应用使用节点的GPU资源。支持Jetson、比特大陆1684、昇腾310 GPU。针对这3种GPU,需要在创建节点时选择对应的加速卡。

也可以在创建节点后修改AI加速卡。
以Jetson为例,在创建节点时选择了NVIDIA Jetson加速卡,在节点的详情页,查看AI加速卡子菜单。

点击【配置】弹出弹出对话框,复制应用安装命令,在边缘节点上执行。

执行过程中会列出当前集群节点,需要输入节点确认。在这里只有一个节点jetson,输入jetson并回车即可。


安装完成后,可以执行kubectl get pod -n kube-system,查看资源分配组件已运行。

卸载资源分配组件是类似的流程。点击【配置】弹出对话框,复制应用卸载命令,在边缘节点上执行。


输入当前节点jetson回车即可完成应用卸载。
比特大陆1684和昇腾310的资源分配组件安装过程和jetson安装过程一致,针对昇腾或比特大陆设备选择加速卡后,点击AI加速卡子菜单的【配置】,弹出对话框后复制应用安装或卸载命令在边缘设备上执行。后续步骤和jetson资源分配组件完全一致。
比特大陆1684资源分配:

昇腾310资源分配:

安装好GPU资源分配组件后,在节点关联的应用中可以配置GPU资源。在应用服务配置中,选择高级配置:


点击添加资源限制:


分配GPU资源仅支持大于等于1的整数,且不能超过边缘节点的所有GPU数量。如配置了超过边缘节点的GPU数量,应用无法启动。比特大陆1684不支持配置数量,数值只可为1。配置完资源限制后,点击【确定】即可在边缘应用生效。
GPU显存共享功能
功能说明
GPU共享功能主要是为了支持多个边缘AI服务可以运行在多张GPU卡上这个特性。当边缘节点上运行多个AI服务的时候,默认情况下,多个AI服务都会运行在GPU卡1上。这样即使边缘节点有多张AI计算卡,也无法动态调用到GPU卡2。使用GPU共享功能,通过设置边缘AI服务的显存容量需求,实现边缘AI服务在多卡之间的动态调度。GPU共享功能仅支持NVIDIA GPU amd64架构。
安装GPU共享功能后,与节点关联的应用可以配置应用的GPU资源限制。如未安装GPU共享功能,应用即使设置GPU资源限制,也无法生效,并且应用也无法在设备上部署运行。
依赖条件
- GPU共享功能依赖于GPU监控功能,所以需要先完成前面的 GPU监控 配置。
- k3s环境,在安装完毕gpushare组件以后,需要重启一次k3s,可以使用命令
systemctl restart k3s。 - k8s环境,需要使用官网推荐的kubeadm方式创建集群,参考官网安装指南。使用这种方案安装的k8s集群,在master节点的
/etc/kubernetes/manifests目录下,会有kube-scheduler.yaml文件,这个是开启gpushare依赖的配置文件,如下图所示:

正常启动k8s,可以看到有kube-scheduler这个pod,如下图所示:
1kubectl get pod -n kube-system

配置步骤
1、进入节点详解页面,找到GPU应用,如下图所示:

2、点击【配置】弹出对话框,包括有安装和卸载GPU共享的命令,将命令复制并在设备上执行。以安装GPU共享为例,先复制对话框中的应用安装命令:

3、在设备上执行该命令。
4、然后会要求用户选择有GPU的子节点,并给相应节点添加标签。当前节点只有一个,输入提示的节点名即可。

5、随后等安装完成,设备即具备GPU共享功能。由于该功能安装应用的镜像较大,拉取镜像时间可能较长。需要等待镜像拉取完成并启动后才会完成安装。
6、查看kube-system命名空间下的pod,确认两个GPU共享服务都已经正常运行即表示安装成功。

7、卸载GPU共享的过程和安装时类似,复制GPU共享配置对话框中的应用卸载命令:

8、在设备上执行,输入具有GPU的子节点并确认。

9、查看kube-system命名空间下的pod,确认两个GPU共享服务都已经删除即表示成功卸载GPU共享功能。

分配应用gpu显存
在边缘节点上安装完毕GPU共享命令以后,我们进入到【应用管理】,找到一个测试的GPU应用,然后在服务配置当中,指定AI服务需要只用的显存容器,最小单位是256MiB,现在如下图所示,给测试AI服务分配了1G显存,限制量就是设置为4。

多卡分配逻辑
假定GPU服务器有2张AI加速卡,加速卡信息如下,卡1有4G显存,卡2也有4G显存。当前有ai-service-1和ai-server-2两个AI服务。根据对着2个ai-service的不同资源限制,可以控制2个ai-service具体调用的AI计算卡。
- 当ai-service-1和ai-service-2都分配2G显存时,ai-service-1和ai-service-2都将调用卡1的资源,因为卡1刚好能够支持2个ai-service。
- 当ai-service-1分配2G显存,ai-service-2分配3G显存时,这2个ai-service会分别运行在卡1和卡2上。因为没有一张卡的显存容量支持运行2个ai-service。
说明:GPU显存的单位是MiB,需要查看GPU卡具体的显存容量,有些显卡说有2G显存,但是具体的容量没有到2048MiB。
GPU显存共享调度实战
单机单卡
查看gpu服务属性,执行nvidia-smi,可以看到这个一台3090显卡的GPU服务器,显存24259MiB

-
云端创建3个以
nvidia/cuda:11.0-base作为容器镜像的服务,并分配不同gpu限制,具体如下:- 应用1:nvidia-cuda11-base-1,NVIDIA资源限制:50单位,每个单位256MiB
- 应用2:nvidia-cuda11-base-2,NVIDIA资源限制:40单位
- 应用3:nvidia-cuda11-base-3,NVIDIA资源限制:1单位
如下图所示:


- 容器镜像都是
nvidia/cuda:11.0-base启动参数如下,是为了让容器一直running
- /bin/sh
- -c
- while true; do echo $(date "+%Y-%m-%d %H:%M:%S"); sleep 1; done
- 将三个应用都部署到gpu服务器,查看pod状态,三个都是running状态,如下所示:

此时调度分配的GPU显存是91单位,即23296MiB,小于3090显卡的24259MiB。
- 修改应用3的NVIDIA资源限制单位为10,此时分配调度的资源是25600MiB,大于24259MiB,此时我们查看边缘pod运行状态。
首先nvidia-cuda11-base-3这个pod会处于Terminating状态:

然后会自动创建一个新的nvidia-cuda11-base-3 pod,处于Pending状态:

等Terminating状态的nvidia-cuda11-base-3清理掉以后,我们可以看到,剩下的那个nvidia-cuda11-base-3依然处于Pending状态:

查看这个pod
1kubectl describe pod nvidia-cuda11-base-3-dd84c5dd5-4ncpf -n baetyl-edge
我们发现提示资源不够。
1Events:
2 Type Reason Age From Message
3 ---- ------ ---- ---- -------
4 Warning FailedScheduling 59s default-scheduler 0/1 nodes are available: 1 Insufficient baidu.com/vcuda-memory.
5 Warning FailedScheduling 59s default-scheduler 0/1 nodes are available: 1 Insufficient baidu.com/vcuda-memory.
单机多卡
- 查看gpu服务器属性,这是一台2张P4卡的GPU服务器,每张卡的显存是7611MiB。对应每张卡最大29单位。

-
创建三个应用,应用现场分配情况如下:
- 应用1:edgekit-gpu-cuda10-2,NVIDIA资源限制:4单位
- 应用2:edgekit-gpu-cuda10-2-2,NVIDIA资源限制:20单位
- 应用3:edgekit-gpu-cuda10-2-3,NVIDIA资源限制:20单位
- 将上述三个应用部署部署到gpu服务器:

- 查看这3个pod对应的gpu:
1kubectl exec edgekit-gpu-cuda10-2-7c766fddd4-h2djd -n baetyl-edge -- nvidia-smi -L
2kubectl exec edgekit-gpu-cuda10-2-2-6c6cdd6885-v284t -n baetyl-edge -- nvidia-smi -L
3kubectl exec edgekit-gpu-cuda10-2-3-599dddc6d4-75c6b -n baetyl-edge -- nvidia-smi -L
4nvidia-smi -L

-
我们可以看到部署情况如下:
-
GPU 0: Tesla P4 (UUID: GPU-9f12f917-e458-4bb8-3d9d-8dc7fd6cddf7)
- edgekit-gpu-cuda10-2-2
-
GPU 1: Tesla P4 (UUID: GPU-7cf0b881-7598-8b1a-3270-94d6f5d2479a)
- edgekit-gpu-cuda10-2
- edgekit-gpu-cuda10-2-3
-
说明,kubectl exec命令输出的GPU卡,需要看UUID号,对应Pod来说,一个pod只有1个gpu,所以里面的GPU编号都是0,对应宿主机来说,GPU编号有0、1。
- 执行nvidia-smi,可以查看gpu的使用情况,如下图所示,总计有3个程序,运行在gpu当中,gpu1当中有2个程序。

总结
不论是单机单卡,还是单机多卡,当我们为一个应用分配一张显卡的大部分内存时(80%显存),我们可以做到让这个应用独占一张显卡,不会与其他应用分享。但是因为资源是抢占式的,如果重启k3s或者k8s,你不能保证还是上次的那个应用能够抢占到一张gpu显卡。不过在当gpu现在数量足够的情况下(比如gpu显卡有7张,当前规划的应用就3个),是可以做到应用按卡调度的。
