物理机和容器环境使用NVDIA GPU设备的链路

0 阅读2分钟

物理机环境

物理机中要使用上 GPU 需要安装以下组件:

  • GPU Driver
  • CUDA Toolkit

二者的关系如 NVIDIA 官网 所示:

image.png

容器环境

Docker容器中的GPU调用流程图

image.png

从图中可以看到,CUDA Toolkit 跑到容器里了,因此宿主机上不需要再安装 CUDA Toolkit。

容器镜像里安装 CUDA Toolkit

容器启动到GPU挂载的完整链路

┌─────────────────────────────────────────────────────────────────┐
│  docker run --gpus all nvidia/cuda nvidia-smi                    │
└─────────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────────┐
│  Docker/containerd                                              │
│  ├── 读取:Image Spec(拉取 nvidia/cuda 镜像)                    │
│  ├── 生成:rootfs(解压合并 layers)                              │
│  ├── 生成:Runtime Spec(config.json)                            │
│  └── 输出:Runtime Bundle + OCI Hook 配置(调用 nvidia hook)      │
│      (或配置使用 nvidia-container-runtime 作为 runtime)         │
└─────────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────────┐
│  nvidia-container-runtime-hook(或 nvidia-container-runtime)     │
│  ├── 读取:Runtime Bundle(config.json + rootfs)                 │
│  ├── 检测:NVIDIA_VISIBLE_DEVICES 环境变量                         │
│  ├── 调用:libnvidia-container.so                                 │
│  │       └── 扫描 /dev/nvidia*,查找 libcuda.so 等                │
│  └── 修改:config.json(注入 mounts、devices、env)                │
│      输出:修改后的 Runtime Bundle(含 GPU 配置)                  │
└─────────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────────┐
│  runc                                                           │
│  ├── 读取:修改后的 Runtime Bundle                                │
│  ├── 创建:namespaces, cgroups                                   │
│  ├── 挂载:GPU 设备、驱动库到容器内                               │
│  └── 执行:nvidia-smi(容器进程)                                 │
└─────────────────────────────────────────────────────────────────┘

Bundle

Bundle 就是 OCI Runtime Spec 的物理实现。是 runc 等 OCI 运行时的唯一输入,

OCI 规范定义了两个核心标准:

OCI 规范定义内容实际产物
OCI Image Spec镜像格式标准(manifest、layers、config)镜像文件(可分发、存储)
OCI Runtime Spec容器运行时的标准配置Bundle(config.json + rootfs)
my-bundle/                    ← Bundle 根目录
├── config.json              ← Runtime Spec(容器配置)
└── rootfs/                  ← 根文件系统
    ├── bin/
    │   ├── sh
    │   ├── ls
    │   └── nvidia-smi       ← GPU 应用二进制
    ├── etc/
    │   ├── passwd
    │   └── hostname
    ├── usr/
    │   └── lib/
    │       └── x86_64-linux-gnu/
    │           ├── libcuda.so
    │           └── libcudart.so
    ├── dev/                 ← 运行时挂载
    ├── proc/                ← 运行时挂载
    └── sys/                 ← 运行时挂载

应用使用GPU的调用链路

Mermaid.jpg

  • libcudart.so 供 User-GPU-Application 侧的框架使用,封装成框架方法给用户调用

  • libcuda.so 承上启下,解释libcudart.so的接口,翻译给nvidia.ko去操作GPU硬件

CUDA Toolkit 可以由容器镜像内提供,而 libcuda.so 通常由宿主机通过挂载方式注入容器。 镜像中还可能包含 compat 目录下的兼容库 libcuda.so,它作为用户态的兼容桥接层,可在需要时优先于宿主机提供的默认 libcuda.so 被加载,并最终与内核态的 nvidia.ko 协同完成 GPU 访问。

该机制使得较新的 CUDA Runtime 在满足最低驱动要求的前提下,能够尽可能运行于较老的宿主驱动环境中;但它并不等价于对所有新特性的完整软件模拟,也不能保证老驱动不支持的能力都能被完全补齐。