在 GPU 节点上配置硬件加速器

随着业务数据的增加,尤其是在人工智能和数据分析等场景中,您可能希望在自建业务集群中利用 GPU 功能来加速数据处理。除了为集群节点准备 GPU 资源外,还需进行 GPU 配置。

本解决方案将集群中具有GPU计算能力的节点称为 GPU 节点

注意:除非另有说明,操作步骤适用于两种类型的节点。有关驱动程序安装相关问题,请参考 NVIDIA 官方安装文档

目录

前提条件

在操作节点上已准备好 GPU 资源,该节点属于本节提到的 GPU 节点。

安装 GPU 驱动

注意:如果 GPU 节点使用 NVIDIA MPS 插件,请确保该节点的 GPU 架构为 Volta 或更新版本(Volta/Turing/Ampere/Hopper 等),且驱动程序支持 CUDA 版本 11.5 或更高版本。

获取驱动下载地址

  1. 登录到 GPU 节点,并运行命令 lspci |grep -i NVIDIA 检查该节点的 GPU 型号。

    在以下示例中,GPU 型号为 Tesla T4。

    lspci | grep NVIDIA
    00:08.0 3D controller: NVIDIA Corporation TU104GL [Tesla T4] (rev a1)
  2. 访问 NVIDIA 官方网站 获取驱动下载链接。

    1. 点击首页顶部导航栏中的 Drivers

    2. 根据 GPU 节点型号填写下载驱动所需的信息。

    3. 点击 Search

    4. 点击 Download

    5. 右键点击 Download > Copy Link Address 复制驱动的下载链接。

  3. 在 GPU 节点上执行以下命令,创建 /home/gpu 目录,并将驱动文件下载并保存到该目录。

    # 创建 /home/gpu 目录
    mkdir -p /home/gpu
    cd /home/gpu/
    # 将驱动文件下载到 /home/gpu 目录,示例:wget https://cn.download.nvidia.com/tesla/515.65.01/NVIDIA-Linux-x86_64-515.65.01.run
    wget <驱动下载地址>
    # 验证驱动文件是否成功下载,如果返回驱动文件名(例如:NVIDIA-Linux-x86_64-515.65.01.run)则表示下载成功
    ls <驱动文件名>

安装驱动

  1. 在 GPU 节点上执行以下命令,以安装与当前操作系统对应的 gcc 和 kernel-devel 包。

    sudo yum install dkms gcc kernel-devel-$(uname -r) -y
  2. 执行以下命令以安装 GPU 驱动。

    chmod a+x /home/gpu/<驱动文件名>
    /home/gpu/<驱动文件名> --dkms
  3. 安装完成后,执行 nvidia-smi 命令。如果返回类似以下示例的 GPU 信息,则表示驱动安装成功。

    # nvidia-smi
    Tue Sep 13 01:31:33 2022     
    +-----------------------------------------------------------------------------+
    | NVIDIA-SMI 515.65.01    Driver Version: 515.65.01    CUDA Version: 11.7     |
    +-------------------------------+-----------------------+---------------------+
    | GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
    | Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
    |                               |                      |               MIG M. |
    |===============================+======================+======================|
    |   0  Tesla T4            Off  | 00000000:00:08.0 Off |                    0 |
    | N/A   55C    P0    28W /  70W |      2MiB / 15360MiB |      5%      Default |
    |                               |                      |                  N/A |
    +-------------------------------+-----------------------+---------------------+
                                                                                    
    +-----------------------------------------------------------------------------+
    | Processes:                                                                  |
    |  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
    |        ID   ID                                                   Usage      |
    |=============================================================================|
    |  No running processes found                                                 |
    +-----------------------------------------------------------------------------+

安装 NVIDIA 容器运行时

  1. GPU 节点 上添加 NVIDIA yum 仓库。

    distribution=$(. /etc/os-release;echo $ID$VERSION_ID) && curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.repo | sudo tee /etc/yum.repos.d/nvidia-container-toolkit.repo
    yum makecache -y

    当提示 "Metadata cache created." 出现时,表示添加成功。

  2. 安装 NVIDIA 容器运行时。

    yum install nvidia-container-toolkit -y

    当提示 Complete! 出现时,表示安装成功。

  3. 配置默认运行时。
    将以下配置添加到文件中。

    • Containerd: 修改 /etc/containerd/config.toml 文件。

      [plugins]
       [plugins."io.containerd.grpc.v1.cri"]
         [plugins."io.containerd.grpc.v1.cri".containerd]
      ...
            default_runtime_name = "nvidia"
      ...
              [plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
      ...
                [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
                  runtime_type = "io.containerd.runc.v2"
                  runtime_engine = ""
                  runtime_root = ""
                  privileged_without_host_devices = false
                  base_runtime_spec = ""
                  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
                    SystemdCgroup = true
                [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"
                    SystemdCgroup = true
      ...
    • Docker: 修改 /etc/docker/daemon.json 文件。

       {
       ...
           "default-runtime": "nvidia",
           "runtimes": {
           "nvidia": {
               "path": "/usr/bin/nvidia-container-runtime"
               }
           },
       ...
       }
  4. 重启 Containerd / Docker。

    • Containerd

      systemctl restart containerd   #重启
      
      crictl info |grep Runtime  #检查
    • Docker

      systemctl restart docker   #重启
      
      docker info |grep Runtime  #检查

物理 GPU 配置

在 GPU 业务集群上部署物理 GPU 插件

在 GPU 集群的管理界面上执行以下操作:

  1. 在目录左侧栏中,选择 "集群插件" 子栏,单击部署 "ACP GPU 设备插件" 并打开 "pGPU" 选项;

  2. 在 "节点" 选项卡中,选择需要部署物理 GPU 的节点,然后单击 "标签和污点管理器",添加 "设备标签" 并选择 "pGPU",然后单击 OK;

  3. 在 "Pods" 选项卡中,检查与 nvidia-device-plugin-ds 对应的容器组运行状态,查看是否有异常,并确保它在指定节点上运行。

NVIDIA MPS 配置(驱动支持 CUDA 版本必须 >= 11.5)

在 GPU 业务集群上部署 NVIDIA MPS 插件

在 GPU 集群的管理界面上执行以下操作:

  1. 在目录左侧栏中,选择 "集群插件" 子栏,单击部署 "ACP GPU 设备插件" 并打开 "MPS" 选项;

  2. 在 "节点" 选项卡中,选择需要部署物理 GPU 的节点,然后单击 "标签和污点管理器",添加 "设备标签" 并选择 "MPS",然后单击 OK;

  3. 在 "Pods" 选项卡中,检查与 nvidia-mps-device-plugin-daemonset 对应的容器组运行状态,查看是否有异常,并确保它在指定节点上运行。

配置 kube-scheduler(kubernetes >= 1.23)

  1. 业务集群控制节点 上,检查调度程序是否正确引用调度策略。

    cat /etc/kubernetes/manifests/kube-scheduler.yaml

    检查是否有 –config 选项,并且值为 /etc/kubernetes/scheduler-config.yaml,如下

    apiVersion: v1
    kind: Pod
    metadata:
      creationTimestamp: null
      labels:
        component: kube-scheduler
        tier: control-plane
      name: kube-scheduler
      namespace: kube-system
    spec:
      containers:
      - command:
        - kube-scheduler
        - --config=/etc/kubernetes/scheduler-config.yaml

注意:上述参数和配置为平台的默认配置。如果您已修改它们,请改回默认值。可以将原始自定义配置复制到调度策略文件中。

  1. 检查调度策略文件的配置。

    1. 执行命令: kubectl describe service kubernetes -n default |grep Endpoints

      期望效果 Endpoints:         192.168.130.240:6443
    2. 将所有 Master 节点上/etc/kubernetes/scheduler-config.yaml文件的内容替换为以下内容,其中${kube-apiserver}应该替换为第一步的输出。

      apiVersion: kubescheduler.config.k8s.io/v1beta2
      kind: KubeSchedulerConfiguration
      clientConnection:
        kubeconfig: /etc/kubernetes/scheduler.conf
      extenders:
      - enableHTTPS: true
        filterVerb: predicates
        managedResources:
        - ignoredByScheduler: false
          name: nvidia.com/mps-core
        nodeCacheCapable: false
        urlPrefix: https://${kube-apiserver}/api/v1/namespaces/kube-system/services/nvidia-mps-scheduler-plugin/proxy/scheduler
        tlsConfig:
          insecure: false
          certFile: /etc/kubernetes/pki/apiserver-kubelet-client.crt
          keyFile: /etc/kubernetes/pki/apiserver-kubelet-client.key
          caFile: /etc/kubernetes/pki/ca.crt

      如果 schedule-config.yaml文件中已存在 extenders,则将 yaml 附加到末尾

      - enableHTTPS: true
        filterVerb: predicates
        managedResources:
        - ignoredByScheduler: false
          name: nvidia.com/mps-core
        nodeCacheCapable: false
        urlPrefix: https://${kube-apiserver}/api/v1/namespaces/kube-system/services/nvidia-mps-scheduler-plugin/proxy/scheduler
        tlsConfig:
          insecure: false
          certFile: /etc/kubernetes/pki/apiserver-kubelet-client.crt
          keyFile: /etc/kubernetes/pki/apiserver-kubelet-client.key
          caFile: /etc/kubernetes/pki/ca.crt
  2. 运行以下命令以获取容器 ID:

    • Containerd:执行 crictl ps |grep kube-scheduler,输出如下,第一列为容器 ID。

      1d113ccf1c1a9       03c72176d0f15       2 seconds ago       Running             kube-scheduler              3                   ecd054bbdd465       kube-scheduler-192.168.176.47
    • Docker:运行 docker ps |grep kube-scheduler,输出如下,第一列为容器 ID。

      30528a45a118   d8a9fef7349c    "kube-scheduler --au..."   37 minutes ago   Up 37 minutes     k8s_kube-scheduler_kube-scheduler-192.168.130.240_kube-system_3e9f7007b38f4deb6ffd1c7587621009_28
  3. 使用上一步获得的容器 ID 重启 Containerd/Docker 容器。

    • Containerd

      crictl stop <容器 ID>
  4. 重启 Kubelet。

    systemctl restart kubelet

GPU 管理器配置

配置 kube-scheduler(kubernetes >= 1.23)

  1. 业务集群控制节点 上,检查调度程序是否正确引用调度策略。

    cat /etc/kubernetes/manifests/kube-scheduler.yaml

    检查是否有 –config 选项,并且值为 /etc/kubernetes/scheduler-config.yaml,如下所示

    apiVersion: v1
    kind: Pod
    metadata:
      creationTimestamp: null
      labels:
        component: kube-scheduler
        tier: control-plane
      name: kube-scheduler
      namespace: kube-system
    spec:
      containers:
      - command:
        - kube-scheduler
        - --config=/etc/kubernetes/scheduler-config.yaml

注意:上述参数和配置为平台的默认配置。如果您已修改它们,请改回默认值。可以将原始自定义配置复制到调度策略文件中。

  1. 检查调度策略文件的配置。

    1. 执行命令: kubectl describe service kubernetes -n default |grep Endpoints

      期望效果 Endpoints:         192.168.130.240:6443
    2. 将所有 Master 节点上/etc/kubernetes/scheduler-config.yaml文件的内容替换为以下内容,其中${kube-apiserver}应该替换为第一步的输出。

      apiVersion: kubescheduler.config.k8s.io/v1beta2
      kind: KubeSchedulerConfiguration
      clientConnection:
        kubeconfig: /etc/kubernetes/scheduler.conf
      extenders:
      - enableHTTPS: true
        filterVerb: predicates
        managedResources:
        - ignoredByScheduler: false
          name: tencent.com/vcuda-core
        nodeCacheCapable: false
        urlPrefix: https://${kube-apiserver}/api/v1/namespaces/kube-system/services/gpu-quota-admission/proxy/scheduler
        tlsConfig:
          insecure: false
          certFile: /etc/kubernetes/pki/apiserver-kubelet-client.crt
          keyFile: /etc/kubernetes/pki/apiserver-kubelet-client.key
          caFile: /etc/kubernetes/pki/ca.crt
  2. 运行以下命令以获取容器 ID:

    • Containerd:执行 crictl ps |grep kube-scheduler,输出如下,第一列为容器 ID。

      1d113ccf1c1a9       03c72176d0f15       2 seconds ago       Running             kube-scheduler              3                   ecd054bbdd465       kube-scheduler-192.168.176.47
    • Docker:运行 docker ps |grep kube-scheduler,输出如下,第一列为容器 ID。

      30528a45a118   d8a9fef7349c    "kube-scheduler --au..."   37 minutes ago   Up 37 minutes     k8s_kube-scheduler_kube-scheduler-192.168.130.240_kube-system_3e9f7007b38f4deb6ffd1c7587621009_28
  3. 使用上一步获得的容器 ID 重启 Containerd/Docker 容器。

    • Containerd

      crictl stop <容器 ID>
  4. 重启 Kubelet。

    systemctl restart kubelet

在 GPU 业务集群上部署 GPU 管理器插件

在 GPU 集群的管理界面上执行以下操作:

  1. 在目录左侧栏中,选择 "集群插件" 子栏,单击部署 "ACP GPU 设备插件" 并打开 "GPU-管理器" 选项;

  2. 在 "节点" 选项卡中,选择需要部署物理 GPU 的节点,然后单击 "标签和污点管理器",添加 "设备标签" 并选择 "vGPU",然后单击 OK;

  3. 在 "Pods" 选项卡中,检查与 gpu-manager-daemonset 对应的容器组运行状态,查看是否有异常,并确保它在指定节点上运行。

结果验证

方法 1:在业务集群的控制节点上运行以下命令检查 GPU 节点上是否有可用的 GPU 资源:

kubectl get node  ${nodeName} -o=jsonpath='{.status.allocatable}' 

方法 2:在平台上通过指定所需的 GPU 资源量来部署 GPU 应用程序。部署后,进入 Pod 并执行以下命令:

# nvidia-smi
Tue Sep 13 01:31:33 2022     
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 515.65.01    Driver Version: 515.65.01    CUDA Version: 11.7     |
+-------------------------------+-----------------------+---------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  Tesla T4            Off  | 00000000:00:08.0 Off |                    0 |
| N/A   55C    P0    28W /  70W |      2MiB / 15360MiB |      5%      Default |
|                               |                      |                  N/A |
+-------------------------------+-----------------------+---------------------+
                                                                                
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

检查是否正确检索到 GPU 信息。