通过 Red Hat Device Edge 和 NVIDIA GPU 加速工作负载#

简介#

注意

开发者预览功能不受 Red Hat 生产服务级别协议 (SLA) 的支持,并且功能尚未完全完成。Red Hat 不建议在生产环境中使用它们。开发者预览功能提供对即将推出的产品功能的早期访问,使客户能够在开发过程中测试功能并提供反馈。这些版本可能没有任何文档,并且测试是有限的。Red Hat 可能会提供在没有相关 SLA 的情况下提交有关开发者预览版本反馈的方式。

Red Hat 发布了 Red Hat Device Edge,它提供了对 MicroShift 的访问。MicroShift 提供了单节点部署的简易性,以及在资源受限的位置进行计算所需的功能和服务。您可以在不同的主机上进行多次部署,为您的每个应用程序创建特定的系统镜像。在难以维护的位置,在您托管的 RHEL 设备之上安装 MicroShift 还可以实现简化的无线更新。

Red Hat Device Edge 将使用 MicroShift 的轻量级 Kubernetes 与边缘的 Red Hat Enterprise Linux 相结合。MicroShift 是一个从 OpenShift 派生的 Kubernetes 实现,专注于最小的占用空间。Red Hat Device Edge 满足部署到资源受限环境的裸机、虚拟、容器化或 kubernetes 工作负载的需求。

执行此页面上的步骤,以使工作负载能够在运行 Red Hat Device Edge 的 x86 系统上使用 NVIDIA GPU。

先决条件#

  • 在 Red Hat Enterprise Linux 8.7 机器上,从 RPM 包安装MicroShift

  • 验证机器上是否安装了 NVIDIA GPU

    $ lspci -nnv | grep -i nvidia
    

    示例输出

    17:00.0 3D controller [0302]: NVIDIA Corporation GA100GL [A30 PCIe] [10de:20b7] (rev a1)
            Subsystem: NVIDIA Corporation Device [10de:1532]
    

安装 NVIDIA GPU 驱动程序#

NVIDIA 在 RPM 存储库中提供了一个预编译的驱动程序,该驱动程序实现了模块化机制。有关更多信息,请参阅使用模块化流简化 RHEL 8 上的 NVIDIA 驱动程序部署

  1. 在此阶段,您应该已经订阅了您的机器并启用了 rhel-9-for-x86_64-baseos-rpmsrhel-9-for-x86_64-appstream-rpms 存储库。添加 NVIDIA CUDA 存储库

    $ sudo dnf config-manager --add-repo=https://developer.download.nvidia.com/compute/cuda/repos/rhel9/x86_64/cuda-rhel9.repo
    
  2. NVIDIA 提供了不同分支的驱动程序,它们具有不同的生命周期,这些驱动程序在NVIDIA 数据中心驱动程序文档中进行了描述。使用生产分支的最新版本,例如,版本 R525。安装驱动程序、fabric-manager 和 NSCQ

    $ sudo dnf module install nvidia-driver:525
    $ sudo dnf install nvidia-fabric-manager libnvidia-nscq-525
    
  3. 安装驱动程序后,禁用 nouveau 驱动程序,因为它与 NVIDIA 驱动程序冲突

    $ echo 'blacklist nouveau' | sudo tee /etc/modprobe.d/nouveau-blacklist.conf
    
  4. 更新 initramfs

    $ sudo dracut --force
    
  5. 启用 nvidia-fabricmanagernvidia-persistenced 服务

    $ sudo systemctl enable nvidia-fabricmanager.service
    $ sudo systemctl enable nvidia-persistenced.service
    
  6. 重启机器

    $ sudo systemctl reboot
    
  7. 机器启动后,验证 NVIDIA 驱动程序是否已正确安装

    $ nvidia-smi
    

    示例输出

    Thu Jun 22 14:29:53 2023
    +-----------------------------------------------------------------------------+
    | NVIDIA-SMI 525.105.17   Driver Version: 525.105.17   CUDA Version: 12.0     |
    |-------------------------------+----------------------+----------------------+
    | 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  NVIDIA A30          Off  | 00000000:17:00.0 Off |                    0 |
    | N/A   29C    P0    35W / 165W |      0MiB / 24576MiB |     25%      Default |
    |                               |                      |             Disabled |
    +-------------------------------+----------------------+----------------------+
    
    +-----------------------------------------------------------------------------+
    | Processes:                                                                  |
    |  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
    |        ID   ID                                                   Usage      |
    |=============================================================================|
    |  No running processes found                                                 |
    +-----------------------------------------------------------------------------+
    

安装 NVIDIA Container Toolkit#

NVIDIA Container Toolkit 使户能够构建和运行 GPU 加速的容器。该工具包包括一个容器运行时库和实用程序,用于自动配置容器以利用 NVIDIA GPU。您必须安装它以使容器运行时能够透明地为 MicroShift 中部署的 pod 配置 NVIDIA GPU。

NVIDIA Container Toolkit 支持 NVIDIA Container Toolkit 存储库中列出的发行版。

  1. 添加 libnvidia-container 存储库

    $ curl -s -L https://nvidia.github.io/libnvidia-container/rhel8.7/libnvidia-container.repo | sudo tee /etc/yum.repos.d/libnvidia-container.repo
    
  2. 安装适用于 RHEL 的 NVIDIA Container Toolkit

    $ sudo dnf install nvidia-container-toolkit -y
    
  3. NVIDIA Container Toolkit 需要一些 SELinux 权限才能正常工作。这些权限分三个步骤设置。

    1. 使用 DNF 安装 container-selinux.noarch

      $ sudo dnf install container-selinux.noarch
      
    2. container_use_devices 的 SELinux 配置标志设置为 on

      $ sudo setsebool -P container_use_devices on
      
    3. 仍然缺少一个权限,因此创建一个策略文件

      $ cat <<EOF > nvidia-container-microshift.te
      module nvidia-container-microshift 1.0;
      
      require {
                    type xserver_misc_device_t;
                    type container_t;
                    class chr_file { map read write };
      }
      
      #============= container_t ==============
      allow container_t xserver_misc_device_t:chr_file map;
      EOF
      
    4. 编译策略

      $ checkmodule -m -M -o nvidia-container-microshift.mod nvidia-container-microshift.te
      
    5. 创建 semodule

      $ semodule_package --outfile nvidia-container-microshift.pp --module nvidia-container-microshift.mod
      
  1. 应用策略

    $ sudo semodule -i nvidia-container-microshift.pp
    

安装 NVIDIA Device Plugin#

为了使 MicroShift 能够将 GPU 资源分配给 pod,请部署 NVIDIA Device Plugin。该插件作为守护程序集运行,提供以下功能

  • 公开集群中每个节点上的 GPU 数量。

  • 跟踪 GPU 的健康状况。

  • 在您的 Kubernetes 集群中运行启用 GPU 的容器。

部署包括将清单和 kustomize 配置添加到 /etc/microshift/manifests 文件夹,MicroShift 在启动时检查该文件夹以创建清单。这在 MicroShift 文档的配置部分中进行了解释。

  1. 创建 manifests 文件夹

    $ sudo mkdir -p /etc/microshift/manifests
    
  2. 设备插件在特权模式下运行,因此您需要将其与其他工作负载隔离,方法是在其自己的命名空间 nvidia-device-plugin 中运行它。要将插件添加到 MicroShift 在启动时部署的清单中,请下载配置文件并将其保存在 /etc/microshift/manifests/nvidia-device-plugin.yml

    $ curl -s -L https://gitlab.com/nvidia/kubernetes/device-plugin/-/raw/main/deployments/static/nvidia-device-plugin-privileged-with-service-account.yml | sudo tee /etc/microshift/manifests/nvidia-device-plugin.yml
    
  3. 即使文件存在,资源也不会自动创建。您需要将它们添加到 kustomize 配置中。通过在 manifests 文件夹中添加一个 kustomization.yaml 文件来完成此操作,该文件引用您要创建的所有资源。

    $ cat <<EOF | sudo tee /etc/microshift/manifests/kustomization.yaml
    ---
    apiVersion: kustomize.config.k8s.io/v1beta1
    kind: Kustomization
    resources:
      - nvidia-device-plugin.yml
    EOF
    
  4. 重启 MicroShift 服务,以便它创建资源

    $ sudo systemctl restart microshift
    
  5. MicroShift 重启后,验证 pod 是否在 nvidia-device-plugin 命名空间中运行

    $ oc get pod -n nvidia-device-plugin
    

    示例输出

    NAMESPACE                  NAME                                   READY   STATUS        RESTARTS     AGE
    nvidia-device-plugin       nvidia-device-plugin-daemonset-jx8s8   1/1     Running       0            1m
    
  6. 在日志中验证它是否已将自身注册为 nvidia.com/gpu 资源的设备插件

    $ oc logs -n nvidia-device-plugin nvidia-device-plugin-jx8s8
    

    示例输出

    [...]
    2023/06/22 14:25:38 Retreiving plugins.
    2023/06/22 14:25:38 Detected NVML platform: found NVML library
    2023/06/22 14:25:38 Detected non-Tegra platform: /sys/devices/soc0/family file not found
    2023/06/22 14:25:38 Starting GRPC server for 'nvidia.com/gpu'
    2023/06/22 14:25:38 Starting to serve 'nvidia.com/gpu' on /var/lib/kubelet/device-plugins/nvidia-gpu.sock
    2023/06/22 14:25:38 Registered device plugin for 'nvidia.com/gpu' with Kubelet
    
  7. 您还可以验证节点是否在其容量中公开了 nvidia.com/gpu 资源

    $ oc get node -o json | jq -r '.items[0].status.capacity'
    

    示例输出

    {
      "cpu": "48",
      "ephemeral-storage": "142063152Ki",
      "hugepages-1Gi": "0",
      "hugepages-2Mi": "0",
      "memory": "196686216Ki",
      "nvidia.com/gpu": "1",
      "pods": "250"
    }
    

在 Red Hat Device Edge 上运行 GPU 加速的工作负载#

您可以运行一个测试工作负载来验证配置是否正确。一个简单的工作负载是 NVIDIA 在容器镜像中提供的 CUDA vectorAdd 程序。

  1. 创建 test 命名空间

    $ oc create namespace test
    
  2. 创建一个文件,例如 pod-cuda-vector-add.yaml,其中包含 pod 规范。请注意 spec.containers[0].resources.limits 字段,其中 nvidia.com/gpu 资源指定的值为 1

    $ cat << EOF > pod-cuda-vector-add.yaml
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: test-cuda-vector-add
      namespace: test
    spec:
      restartPolicy: OnFailure
      containers:
      - name: cuda-vector-add
        image: "nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda11.7.1-ubi8"
        resources:
          limits:
            nvidia.com/gpu: 1
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
          runAsNonRoot: true
          seccompProfile:
            type: "RuntimeDefault"
    EOF
    
  3. 创建 pod

    $ oc apply -f pod-cuda-vector-add.yaml
    
  4. 验证 pod 日志是否已找到 CUDA 设备

    $ oc logs -n test test-cuda-vector-add
    

    示例输出

    [Vector addition of 50000 elements]
    Copy input data from the host memory to the CUDA device
    CUDA kernel launch with 196 blocks of 256 threads
    Copy output data from the CUDA device to the host memory
    Test PASSED
    Done
    
  5. 取消部署 pod-cuda-vector-add.yaml 文件中的 pod

    $ oc delete -f pod-cuda-vector-add.yaml
    
  6. 删除 test 命名空间

    $ oc delete ns test