nvidia-container-runtime 相关逻辑
相关配置和内容
/etc/containerd/config.toml 中配置:
1
2
3
4
5
6
7
|
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia]
privileged_without_host_devices = false
runtime_engine = ""
runtime_root = ""
runtime_type = "io.containerd.runc.v1"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia.options]
BinaryName = "/usr/bin/nvidia-container-runtime"
|
代码中读取配置文件路径:/etc/nvidia-container-runtime/config.toml,配置文件内容示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
#accept-nvidia-visible-devices-as-volume-mounts = false
#accept-nvidia-visible-devices-envvar-when-unprivileged = true
disable-require = false
supported-driver-capabilities = "compat32,compute,display,graphics,ngx,utility,video"
#swarm-resource = "DOCKER_RESOURCE_GPU"
[nvidia-container-cli]
#debug = "/var/log/nvidia-container-toolkit.log"
environment = []
#ldcache = "/etc/ld.so.cache"
ldconfig = "@/sbin/ldconfig"
load-kmods = true
#no-cgroups = false
#path = "/usr/bin/nvidia-container-cli"
#root = "/run/nvidia/driver"
#user = "root:video"
[nvidia-container-runtime]
debug = "/var/log/nvidia-container-runtime.log"
log-level = "trace"
mode = "auto"
runtimes = ["docker-runc", "runc", "crun"]
[nvidia-container-runtime.modes]
[nvidia-container-runtime.modes.cdi]
annotation-prefixes = ["cdi.k8s.io/"]
default-kind = "nvidia.com/gpu"
spec-dirs = ["/etc/cdi", "/var/run/cdi"]
[nvidia-container-runtime.modes.csv]
mount-spec-path = "/etc/nvidia-container-runtime/host-files-for-container.d"
[nvidia-container-runtime-hook]
path = "nvidia-container-runtime-hook"
skip-mode-detection = false
[nvidia-ctk]
path = "nvidia-ctk"
|
代码中打印的配置内容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
{
"DisableRequire": false,
"SwarmResource": "",
"AcceptEnvvarUnprivileged": true,
"AcceptDeviceListAsVolumeMounts": false,
"SupportedDriverCapabilities": "compat32,compute,display,graphics,ngx,utility,video",
"NVIDIAContainerCLIConfig": {
"Root": "",
"Path": "",
"Environment": [],
"Debug": "",
"Ldcache": "",
"LoadKmods": true,
"NoPivot": false,
"NoCgroups": false,
"User": "",
"Ldconfig": "@/sbin/ldconfig"
},
"NVIDIACTKConfig": {
"Path": "/usr/bin/nvidia-ctk"
},
"NVIDIAContainerRuntimeConfig": {
"DebugFilePath": "/var/log/nvidia-container-runtime.log",
"LogLevel": "trace",
"Runtimes": [
"docker-runc",
"runc",
"crun"
],
"Mode": "auto",
"Modes": {
"CSV": {
"MountSpecPath": "/etc/nvidia-container-runtime/host-files-for-container.d"
},
"CDI": {
"SpecDirs": [
"/etc/cdi",
"/var/run/cdi"
],
"DefaultKind": "nvidia.com/gpu",
"AnnotationPrefixes": [
"cdi.k8s.io/"
]
}
}
},
"NVIDIAContainerRuntimeHookConfig": {
"Path": "/usr/bin/nvidia-container-runtime-hook",
"SkipModeDetection": false
}
}
|
查看某个特定的容器的 containerd 日志信息:
1
2
3
4
5
|
# kubectl -ndemo get pods test-deploy0-6cdcc7659-66xlx -oyaml | grep containerID
# - containerID: containerd://4bd59051851d84523f4b16b27b32ef529ba399098fa80560e2818bdc4a2be4d7
cat /var/run/containerd/io.containerd.runtime.v2.task/k8s.io/4bd59051851d84523f4b16b27b32ef529ba399098fa80560e2818bdc4a2be4d7/log.json
# 查看其 OCI spec 信息
cat /var/run/containerd/io.containerd.runtime.v2.task/k8s.io/4bd59051851d84523f4b16b27b32ef529ba399098fa80560e2818bdc4a2be4d7/config.json
|
nvidia-container-runtime 逻辑
1、从命令行参数 bundle 获取 OCI 配置所在文件夹路径,并从文件 config.json 读取 OCI 配置。调用的命令示例如下:
1
|
/usr/bin/nvidia-container-runtime --root /run/containerd/runc/k8s.io --log /var/run/containerd/io.containerd.runtime.v2.task/k8s.io/4bd59051851d84523f4b16b27b32ef529ba399098fa80560e2818bdc4a2be4d7/log.json --log-format json create --bundle /var/run/containerd/io.containerd.runtime.v2.task/k8s.io/4bd59051851d84523f4b16b27b32ef529ba399098fa80560e2818bdc4a2be4d7 --pid-file /var/run/containerd/io.containerd.runtime.v2.task/k8s.io/4bd59051851d84523f4b16b27b32ef529ba399098fa80560e2818bdc4a2be4d7/init.pid 4bd59051851d84523f4b16b27b32ef529ba399098fa80560e2818bdc4a2be4d7
|
2、里面会从环境变量 NVIDIA_VISIBLE_DEVICES 或者挂载路径中获取信息,判断是否为 CDI 模式,如果是 CDI 模式则直接返回。否则使用 go-nvlib 和 go-nvml 库获取平台信息,如果平台为 nvml 或者 wsl 则返回,否则返回 legacy 模式,如果平台为 tegra,则返回 csv 模式。
3、nvidia-container-runtime:根据模式,返回对应的 Modifier,legacy 返回 NewStableRuntimeModifier,
里面会添加:nvidiaContainerRuntimeHookPath 配置路径,最后在 OCI 配置中添加 prestart hook 路径,然后转回到底层 runtime 执行。添加的 hook 配置如下:
1
2
3
4
5
6
|
"hooks": {
"prestart": [{
"path": "/usr/bin/nvidia-container-runtime-hook",
"args": ["nvidia-container-runtime-hook", "prestart"]
}]
},
|
4、runc:底层运行时 runc 执行时,根据 OCI 规范,执行 prestart hook。
5、nvidia-container-runtime-hook:执行 prestart 命令。里面是调用到/usr/bin/nvidia-container-cli(在 third_party/libnvidia-container 中,提供二进制文件给 hook 使用)来执行。
containerd 和 device plugin 逻辑
1、请求 Device Plugin 获取 GPU 设备:Kubelet 首先会与 Device Plugin 通信,以获取可用的 GPU 设备。Device Plugin 是一个守护进程,负责向 Kubelet 报告节点上的可用设备,并管理设备的分配。
2、请求 containerd 创建容器:在获取到可用的 GPU 设备后,Kubelet 会将这些设备信息包含在创建容器的请求中,并通过 CRI 向 containerd 发送请求,要求创建容器,将允许容器访问的特定设备节点设置到 OCI 配置文件的 device 字段中。
3、runc 创建容器:runc 会根据 OCI 配置文件中的设备信息,将这些设备节点挂载到容器内部。
modify 逻辑
graphicsModifier
NVIDIA_DRIVER_CAPABILITIES:控制哪些驱动库/二进制文件将被挂载到容器内部,值可为:
- compute,video 或 graphics,utility
- all
- 空或未设置
流程:
1、获取是否存在环境变量 NVIDIA_VISIBLE_DEVICES,否则不需要创建。
2、从环境变量 NVIDIA_DRIVER_CAPABILITIES,获取需要的驱动能力,并判断是否含有“graphics”和“display”能力,否则不需要创建。
3、获取nvidia-ctk 路径,然后挂载图形相关的so文件到容器内部。
featureGatedModifier
根据可选的特征创建modifier,目前支持的特征有:
- NVIDIA_GDS:GDS(GPUDirect Storage)是 NVIDIA 提供的一种技术,允许 GPU 直接访问存储设备,从而提高数据传输速度和效率。
- NVIDIA_MOFED:MOFED(Mellanox OpenFabrics Enterprise Distribution)是 Mellanox 提供的高性能网络驱动程序和库,通常用于高性能计算(HPC)和数据中心环境
- NVIDIA_NVSWITCH:NVSwitch 是 NVIDIA 提供的一种高带宽互连技术,用于连接多个 GPU,从而实现更高的计算性能和扩展性。
- NVIDIA_GDRCOPY:GDRCopy 是一种用于 GPU 直接内存访问(DMA)传输的库,通常用于高性能计算和数据传输场景。