Please enable Javascript to view the contents

Kubernetes 下开源的 GPU 虚拟化项目

 ·  ☕ 4 分钟

1. k8s-device-plugin

https://github.com/NVIDIA/k8s-device-plugin 是 NVIDIA 官方提供的 Kubernetes 设备插件,用于在 Kubernetes 集群中管理和分配 NVIDIA GPU 资源。

k8s-device-plugin 通过与 kubelet 的交互,自动发现和注册 GPU 设备,并将其作为资源提供给 Kubernetes 调度器。它支持多种 GPU 型号,并能够处理 GPU 的分片和共享。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
apiVersion: v1
kind: Pod
metadata:
  name: gpu-pod
spec:
  restartPolicy: Never
  containers:
    - name: cuda-container
      image: nvidia/cuda:11.8.0-base
      resources:
        limits:
          nvidia.com/gpu: 1 # 使用一个 GPU
  tolerations:
    - key: nvidia.com/gpu
      operator: Exists
      effect: NoSchedule

2. gpu-operator

https://github.com/NVIDIA/gpu-operator 是 NVIDIA 官方提供的组件,提供了驱动管理、容器运行集成、设备发现、节点特征发现等 GPU 全生命周期管理功能。

gpu-operator 不仅集成了 k8s-device-plugin,还提供了一下几种 GPU 资源分配方式:

2.1 MIG

Multi-Instance GPU,简称 MIG,是 NVIDIA 提供的一种技术。

MIG 可以将 Blackwell、Hopper、Ampere 架构的一张 GPU 划分为多个独立的实例,每个实例的计算、显存、带宽相互独立。具体型号可以参考 https://docs.nvidia.com/datacenter/tesla/mig-user-guide/

值得注意的是 MIG 是硬件级别的分片技术,只有支持 MIG 的 GPU 才能使用。

在 Kubernetes 上使用时,需要先安装 k8s-device-plugin 和 gpu-feature-discovery 组件。

首先配置 MIG:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
apiVersion: v1
kind: ConfigMap
metadata:
  name: custom-mig-config
  namespace: nvidia-device-plugin
data:
  config.json: |
    {
      "mig-configs": [
        {
          "devices": ["all"],
          "mig-enabled": true,
          "mig-devices": [
            {"profile": "1g.5gb", "count": 7}
          ]
        }
      ]
    }    

1g.5gb 是 MIG 的配置文件,表示每个实例有 1 个 GPU slice(一张卡分为若干 slice)和 5GB 显存。

在 Pod 中这样使用 MIG 资源:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
apiVersion: v1
kind: Pod
metadata:
  name: mig-demo
spec:
  restartPolicy: Never
  containers:
    - name: demo
      image: nvidia/cuda:11.8.0-base
      command: ["nvidia-smi"]
      resources:
        limits:
          nvidia.com/mig-1g.5gb: 1 # 使用一个 MIG 实例

2.2 Time-Slicing

几乎所有的 NVIDIA GPU 都支持 Time-Slicing 技术。Time-Slicing 允许将物理 GPU 切分为多个虚拟设备,每个虚拟设备可以分配给不同的 Pod 使用。每个虚拟设备在时间上共享物理 GPU 的计算资源。

Time-Slicing 仅仅只是调度层面的 GPU 共享,并没有进行资源层级的隔离,因此存在资源的竞争问题。

首先配置 Time-Slicing:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
apiVersion: v1
kind: ConfigMap
metadata:
  name: time-slicing-config
data:
  default: |-
    version: v1
    sharing:
      timeSlicing:
        resources:
        - name: nvidia.com/gpu  # 资源名称
          replicas: 4           # 每块物理GPU切分为4个虚拟设备    

在 Pod 中这样使用 Time-Slicing 资源:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
apiVersion: v1
kind: Pod
metadata:
  name: gpu-timeslicing-demo
spec:
  containers:
    - name: cuda-container
      image: nvidia/cuda:11.8.0-base
      command: ["bash", "-c", "nvidia-smi && sleep 3600"]
      resources:
        limits:
          nvidia.com/gpu: 1 # 使用一个 GPU,实际可能和另外三个 Pod 共享同一块物理 GPU

2.3 MPS

MPS(Multi-Process Service)是 NVIDIA 提供的一种技术,用于在同一物理 GPU 上运行多个 CUDA 应用程序。MPS 允许多个进程共享同一个 GPU 上的计算资源,从而提高 GPU 的利用率。

相较于 Time-Slicing,MPS 提供了更好的资源隔离和性能优化。MPS 通过创建一个 MPS Server 进程来管理多个 CUDA 应用程序的执行。

首先配置 MPS:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
apiVersion: nvidia.com/v1
kind: ClusterPolicy
metadata:
  name: mps-policy
spec:
  devicePlugin:
    enabled: true
    env:
      - name: NVIDIA_MPS_ENABLE
        value: "1"

在 Pod 中使用 MPS 资源:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
apiVersion: v1
kind: Pod
metadata:
  name: mps-demo
spec:
  containers:
    - name: mps-container
      image: nvidia/cuda:11.8.0-base
      env:
        - name: NVIDIA_MPS_ENABLE
          value: "1"
      command: ["/bin/bash", "-c", "nvidia-smi && sleep 3600"]
      resources:
        limits:
          nvidia.com/gpu: 1

3. gpu-manager

https://github.com/tkestack/gpu-manager 采用的是 vCUDA 技术。vCUDA(virtual CUDA)技术是 API Forwarding/Remoting vGPU 实现。

vCUDA 在用户层拦截和重定向 CUDA API 的方法,在 VM 中建立 pGPU 的逻辑映像,即:vGPU,以此来实现 GPU 资源的细粒度划分、重组和再利用,支持多机并发、挂起恢复等 VM 的高级特性。

如果是整数倍卡,gpu-manager 会通过环境变 NVIDIA_VISIBLE_DEVICES 控制容器内应用可见的 GPU,同时仅将可见的设备挂载到容器内。

如果是少于 1 张卡,gpu-manager 会注入 LD_LIBRARY_PATH 借助 https://github.com/tkestack/vcuda-controller 项目劫持 CUDA 和 NVML 的库函数调用,修改返回值,实现对 GPU 资源的分片。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: v1
kind: Pod
metadata:
  name: vcuda
spec:
  restartPolicy: Never
  containers:
    - image: nvidia/cuda:11.8.0-base
      name: nvidia
      command:
        - /usr/local/nvidia/bin/nvidia-smi
        - pmon
        - -d
        - 10
      resources:
        requests:
          tencent.com/vcuda-core: 50
          tencent.com/vcuda-memory: 30
        limits:
          tencent.com/vcuda-core: 50
          tencent.com/vcuda-memory: 30

这里分配 7680 MiB GPU memory 和 0.5 GPU 的资源。tencent.com/vcuda-core 的单位是 0.01 GPU core,tencent.com/vcuda-memory 的单位是 256 MiB 显存。

4. HAMi

https://github.com/Project-HAMi/HAMi 采用的是 vCUDA 方案,通过劫持 CUDA API 调用来实现 GPU 资源的分片和共享。

由于同属于 vCUDA 技术栈,HAMi 与 gpu-manager 的使用方式类似。不同的是 gpu-manager 项目不再维护,而 HAMi 仍在持续更新。

HAMi 不仅集成了 Nvidia 的 MIG、Time-Slicing,还可以管理 NPU、MLU、DCU 等其他 AI 加速卡,同时在调度层面也进行了优化,能够根据自定义策略进行资源分配。

下面是一个使用 HAMi 的示例 Pod 配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
apiVersion: v1
kind: Pod
metadata:
  name: mps-demo
spec:
  containers:
    - name: mps-container
      image: nvidia/cuda:11.8.0-base
      env:
        - name: NVIDIA_MPS_ENABLE
          value: "1"
      command: ["/bin/bash", "-c", "nvidia-smi && sleep 3600"]
      resources:
        limits:
          nvidia.com/gpu: 1 # 使用 1 个 GPU
          nvidia.com/gpucores: 30 # 使用每个 GPU 的 30% 核心
          nvidia.com/gpumem: 3000 # 申请 3G 显存

微信公众号
作者
微信公众号