首页 / 常见问题 / 为自建的业务集群配置 GPU 节点

为自建的业务集群配置 GPU 节点

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

本方案将集群中具备 GPU 计算能力的节点称为 GPU 节点。可以是安装了 GPU 显卡的物理机节点(pGPU),也可以是使用 GPU 虚拟化能力的虚拟机节点(vGPU)。

说明:若无特指,操作步骤将同时适用于两类节点。驱动安装相关问题可参考 NVIDIA 官网安装文档

适用场景

前提条件

操作节点上已准备好 GPU 资源,即属于本节所说的 GPU 节点。

操作系统支持情况

操作系统 运行时组件 创建集群 已有非 GPU 集群
CentOS 7.9 Containerd
  • 物理 GPU:✓
  • 虚拟 GPU:✓
  • 物理 GPU:✓
  • 虚拟 GPU:✓
  • Docker
  • 物理 GPU:✓
  • 虚拟 GPU:✓
  • 物理 GPU:✓
  • 虚拟 GPU:✓
  • 安装 GPU 驱动

    获取驱动下载地址

    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. 在官网首页的顶部导航栏中,单击 驱动程序

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

      3. 单击 搜索

      4. 单击 下载

      5. 右键单击 下载 > 复制链接地址,即可复制驱动的下载地址。

    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                                                 |
      +-----------------------------------------------------------------------------+

    (仅虚拟 GPU)修改配置

    确保即使重启虚拟 GPU 节点也可以正确加载相关模块。

    说明:对于新集群,结束前述步骤结束后您已经可以创建集群。待将虚拟 GPU 节点加入集群后,再参考以下步骤修改虚拟 GPU 节点配置。

    1. 修改文件 /etc/systemd/system/kubelet.service

      vi /etc/systemd/system/kubelet.service
    2. 在文件的 Unit 配置项中添加参数。

      [Unit]
      Description=kubelet: The Kubernetes Node Agent
      Documentation=https://kubernetes.io/docs/[Service]
      User=root
      ExecStart=/usr/bin/kubelet
      
      # 增加如下内容
      ExecStartPre=/bin/bash -c 'modprobe nvidia-uvm;nvidia-modprobe -u -c=0'
      Restart=always
      StartLimitInterval=0
      RestartSec=10
    3. 重启服务。

      systemctl daemon-reload
      systemctl restart kubelet
    4. 执行命令。

      modprobe nvidia-uvm;nvidia-modprobe -u -c=0

    物理 GPU 配置

    配置 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  #检查

    部署 nvidia-device-plugin

    1. 为 GPU 节点增加 Label,请修改 gpuNodes 为 GPU 节点名称,并执行以下命令:

      kubectl label node <gpuNodes> nvidia-device-enable=enable --overwrite
    2. 在 global 集群获取 nvidia-device-plugin 版本信息,执行命令:

      kubectl  get prdb base -o yaml | grep acp/chart-nvidia-device-plugin  -A 1

      获取输出的 version 字段值,输出示例:

      - name: acp/chart-nvidia-device-plugin
          version: v3.9.0-alpha.8
    3. 在 global 集群获取私有镜像仓库地址,执行命令:

      kubectl  get prdb base -o=jsonpath='{.spec.registry.address}'

      获取输出的地址信息,输出示例:

      192.168.130.240:11443
    4. 使用 Sentry 在业务集群控制节点部署 nvidia-device-plugin,使用获取到的私有镜像仓库地址和 nvidia-device-plugin 版本,分别修改下面示例中 export 命令中的 REGISTRY_ADDRESSPGPU_VERSION 字段值后,将全部内容粘贴至命令行中执行:

      export REGISTRY_ADDRESS="192.168.130.240:11443" 
      export PGPU_VERSION="v3.9.0-alpha.8"   
      cat << EOF |kubectl apply -f -
      apiVersion: operator.alauda.io/v1alpha1
      kind: AppRelease
      metadata:
        name: pgpu
        namespace: cpaas-system
        finalizers:
          - finalizers.apprelease
      spec:
        source:
          charts:
            - name: acp/chart-nvidia-device-plugin
              releaseName: pgpu
              targetRevision: ${PGPU_VERSION}
          repoURL: ${REGISTRY_ADDRESS}
        values:
          global:
            registry:
              address: ${REGISTRY_ADDRESS}
      EOF
    5. 检查 nvidia-device-plugin-daemonset Pod 状态,确保为 Running 状态。

      kubectl -n kube-system get pods   |grep nvidia
      nvidia-device-plugin-daemonset-9ebhj   1/1     Running   0          45m

    修改业务集群配置

    global 集群的控制节点 上,执行以下命令:

    kubectl patch cluster {业务集群名称}  -p '{"spec":{"features":{"gpuType": "Physical"}}}'

    虚拟 GPU 配置

    配置 kube-scheduler (kubernetes < 1.23)

    1. 业务集群控制节点 上,检查调度器(Scheduler)中是否正确引用调度策略。

      cat /etc/kubernetes/manifests/kube-scheduler.yaml
      检查项 期望结果
      参数 -policy-config-file
      /etc/kubernetes/scheduler-policy-config.json (即调度策略文件)

      说明:上述参数和值为平台默认配置,如果您已自行修改,请将其改回默认值。原自定义配置可复制到调度策略文件中。

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

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

        期望效果Endpoints:         192.168.130.240:6443
      2. 将所有 Master 节点的 /etc/kubernetes/scheduler-policy-config.json 这个文件内容替换成如下内容,其中 ${apiserver} 改为第一步的输出结果。

        {
           "apiVersion" : "v1",
           "extenders" : [
              {
                 "apiVersion" : "v1beta1",
                 "filterVerb" : "predicates",
                 "managedResources" : [
                    {
                       "ignoredByScheduler" : false,
                       "name" : "tencent.com/vcuda-core"
                    }
                 ],
                 "nodeCacheCapable" : false,
                 "urlPrefix" : "https://${apiserver}/api/v1/namespaces/kube-system/services/gpu-quota-admission/proxy/scheduler",
                 "enableHttps": true,
                 "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"
                 }
              }
           ],
           "kind" : "Policy"
        }
    3. 执行以下命令获取容器 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
    4. 使用上一步获取到的容器 ID 重启 Containerd/Docker 容器。

      • Containerd

        crictl stop <容器 ID>
      • Docker

        docker stop <容器 ID>
    5. 重启 Kubelet。

      systemctl restart kubelet

    配置 kube-scheduler (kubernetes >= 1.23)

    1. 业务集群控制节点 上,检查调度器(Scheduler)中是否正确引用调度策略。

      cat /etc/kubernetes/manifests/kube-scheduler.yaml
      检查项 期望结果
      参数 –config
      /etc/kubernetes/scheduler-config.yaml (即调度策略文件)

      说明:上述参数和值为平台默认配置,如果您已自行修改,请将其改回默认值。原自定义配置可复制到调度策略文件中。

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

      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
    3. 执行以下命令获取容器 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
    4. 使用上一步获取到的容器 ID 重启 Containerd/Docker 容器。

      • Containerd

        crictl stop <容器 ID>
      • Docker

        docker stop <容器 ID>
    5. 重启 Kubelet。

      systemctl restart kubelet

    部署 gpu-manager

    1. 为 GPU 节点增加 Label,请修改 gpuNodes 为 GPU 节点名称,并执行以下命令:

      kubectl label node <gpuNodes> nvidia-device-enable=enable --overwrite
    2. 在 global 集群获取 gpu-manager 版本信息,执行命令:

      kubectl  get prdb base -o yaml | grep acp/chart-gpu-manager  -A 1

      获取输出的 version 字段值,输出示例:

      - name: acp/chart-gpu-manager
        version: v3.9.0-alpha.26
    3. 在 global 集群获取私有镜像仓库地址,执行命令:

      kubectl  get prdb base -o=jsonpath='{.spec.registry.address}'

      获取输出的地址信息,输出示例:

      192.168.130.240:11443
    4. 使用 Sentry 在业务集群控制节点部署 gpu-manager,使用获取到的私有镜像仓库地址和 gpu-manager 版本,分别修改下面示例中 export 命令中的 REGISTRY_ADDRESSPGPU_VERSION 字段值后,将全部内容粘贴至命令行中执行:

      export REGISTRY_ADDRESS="192.168.130.240:11443"
      export GPU_MANAGER_VERSION=v3.9.0-alpha.26
      cat << EOF |kubectl apply -f -
      apiVersion: operator.alauda.io/v1alpha1
      kind: AppRelease
      metadata:
        name: vgpu
        namespace: cpaas-system
        finalizers:
          - finalizers.apprelease
      spec:
        source:
          charts:
            - name: acp/chart-gpu-manager
              releaseName: vgpu
              targetRevision: ${GPU_MANAGER_VERSION}
          repoURL: ${REGISTRY_ADDRESS}
        values:
          global:
            registry:
              address: ${REGISTRY_ADDRESS}
      EOF
    5. 检查 gpu-manager-daemonset 运行情况,执行以下命令:

      kubectl get pods -n kube-system |grep gpu

      确保所有容器为 Running 状态,效果如下:

      gpu-manager-daemonset-s5kch            1/1     Running   1          1h
      gpu-quota-admission-776b559bdd-q59nd   1/1     Running   1          1h

    修改业务集群配置

    global 集群的控制节点 上,执行以下操作。

    kubectl patch cluster {业务集群名称}  -p '{"spec":{"features":{"gpuType": "Virtual"}}}'

    结果验证

    方式一:在业务集群的控制节点检查 GPU 节点上是否有可分配的 GPU 资源,执行以下命令:

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

    方式二:部署一个 GPU 应用,检查是否有 GPU 相关的资源消耗,业务集群的 GPU 节点执行以下命令:

    nvidia-smi pmon -s u -d 1

    查得 smmem 均有数据时,说明 GPU 功能已就绪。您可在 GPU 节点上开始 GPU 应用开发。

    注意:部署 GPU 应用时,务必要配置以下必填参数。

    物理 GPU

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: gpu-test-nvidia
    spec:
        spec:
          containers:
            - image: <GPU 镜像>
              imagePullPolicy: IfNotPresent
              name: gpu
              resources:
                limits:
                  cpu: '2'
                  memory: 4Gi
                  nvidia.com/gpu: 1        # 必填

    虚拟 GPU

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: gpu-test-nvidia
    spec:
        spec:
          containers:
            - image: <GPU 镜像>
              imagePullPolicy: IfNotPresent
              name: gpu
              resources:
                limits:
                  cpu: '2'
                  memory: 4Gi
                  tencent.com/vcuda-core: '20'    # 必填
                  tencent.com/vcuda-memory: '20'  # 必填

    后续操作

    操作完毕后,如需添加其他 GPU 节点,在 为自建集群添加节点 时勾选该节点的 GPU 选项即可。