容器使用GPU的主要需求有两个:
- 容器中可以查看GPU设备
- 容器应用可以操作GPU显卡
Nvidia GPU对容器的支持具体可见:Enabling GPUs in the Container Runtime Ecosystem
Nvidia-docker
Nvidia推出Nvidia-docker套件以支持容器对GPU的操作。安装完Nvidia-docker后,在/etc/docker/daemon.json
的rumtimes
中注册nvidia runtime,使用nvidia runtime运行的容器就可通过容器中的Nvidia驱动操作GPU显卡。
Nvidia-docker项目只是建立在容器层的设计,真正调用GPU的核心支持放在libnvidia-container。该库基于Linux内核原语,与更高的容器运行时层无关。这样就可以将GPU支持扩展到不同的容器环境中,例如Docker、LXC和CRI-O。该库包含一个cli工具并提供API以便继承到其他运行时环境中。Nvidia将容器使用GPU需要的运行时中的库、工具和层集成到Nvidia-container-runtime中。这个就是GPU容器在启动时指定的那个runtime。
Nvidia-container-runtime
是Nvidia维护的一个容器runtime,它对runc进行了二次修改(runc是一个根据OCI标准来创建和运行容器的轻量级工具),对所有指定nvidia runtime的容器注入一个自定义的pre-start hook,使容器支持GPU操作。
Nvidia-container-runtime
的构建关系如图:
Nvidia-container-runtime-hook
是一个二进制包,作用是将当前容器中的信息收集并处理,转换为参数调用libnvidia-container的nvidia-container-cli
工具。比如对环境变量NVIDIA_VISIBLE_DEVICES
的处理,如果未指定或是void,则认为是非GPU容器,不做任何处理;否则调用nvidia-container-cli
配置容器对GPU硬件的使用支持,将Nvidia 驱动库的so文件 和 GPU设备信息, 通过文件挂载的方式映射到容器中。环境变量中指定了哪几个GPU就挂载哪几个GPU。Nvidia-container-runtime-hook
还负责传入容器GPU应用进程的Pid。
nvidia-container-cli
的configure组件中负责挂载GPU的部分代码:
/* Mount the driver, visible devices, mig-configs and mig-monitors. */
if (perm_set_capabilities(&err, CAP_EFFECTIVE, ecaps[NVC_MOUNT], ecaps_size(NVC_MOUNT)) < 0) {
warnx("permission error: %s", err.msg);
goto fail;
}
if (nvc_driver_mount(nvc, cnt, drv) < 0) {
warnx("mount error: %s", nvc_error(nvc));
goto fail;
}
for (size_t i = 0; i < devices.ngpus; ++i) {
if (nvc_device_mount(nvc, cnt, devices.gpus[i]) < 0) {
warnx("mount error: %s", nvc_error(nvc));
goto fail;
}
}
在容器中使用mount命令可以看到挂载的GPU
使用nvidia-smi命令查看被映射的GPU卡