GPU Operator 与 Kata Containers#

关于带有 Kata Containers 的 Operator#

注意

技术预览版功能在生产环境中不受支持,并且功能不完整。技术预览版功能提供对即将推出的产品功能的早期访问,使客户能够在开发过程中测试功能并提供反馈。这些版本可能没有任何文档,并且测试受到限制。

Kata Containers 与传统容器(如 Docker 容器)相似,但略有不同。

传统容器打包软件以实现与主机的用户空间隔离,但容器在主机上运行,并与主机共享操作系统内核。共享操作系统内核是一个潜在的漏洞。

Kata 容器在主机上的虚拟机中运行。虚拟机具有单独的操作系统和操作系统内核。与传统容器相比,硬件虚拟化和单独的内核提供了改进的工作负载隔离。

NVIDIA GPU Operator 与 Kata 容器运行时协同工作。Kata 使用虚拟机监控程序(如 QEMU)来提供轻量级虚拟机,该虚拟机具有单一用途——运行 Kubernetes Pod。

下图显示了 Kubernetes 用于运行 Kata 容器的软件组件。

flowchart LR a[Kubelet] --> b[CRI] --> c[Kata\nRuntime] --> d[Lightweight\nQEMU VM] --> e[Lightweight\nGuest OS] --> f[Pod] --> g[Container]

带有 Kata 容器运行时的软件组件#

NVIDIA 通过使用 Confidential Containers Operator 来安装 Kata 运行时和 QEMU,从而支持 Kata Containers。即使在此配置中 Operator 不用于机密计算,Operator 也简化了 Kata 运行时的安装。

关于 NVIDIA Kata Manager#

当您为 Kata Containers 配置 GPU Operator 时,Operator 会部署 NVIDIA Kata Manager 作为操作数。

管理器下载 NVIDIA 优化的 Linux 内核镜像和初始 RAM 磁盘,这些镜像和磁盘为在 QEMU 中运行的虚拟机提供轻量级操作系统。这些工件从每个工作节点的 NVIDIA 容器注册表 nvcr.io 下载。

管理器还为每个工作节点配置运行时类 kata-qemu-nvidia-gpu,并为运行时类配置 containerd。

NVIDIA Kata Manager 配置#

集群策略的以下部分显示了与管理器相关的字段

kataManager:
  enabled: true
  config:
    artifactsDir: /opt/nvidia-gpu-operator/artifacts/runtimeclasses
    runtimeClasses:
    - artifacts:
        pullSecret: ""
        url: nvcr.io/nvidia/cloud-native/kata-gpu-artifacts:ubuntu22.04-525
      name: kata-qemu-nvidia-gpu
      nodeSelector: {}
    - artifacts:
        pullSecret: ""
        url: nvcr.io/nvidia/cloud-native/kata-gpu-artifacts:ubuntu22.04-535-snp
      name: kata-qemu-nvidia-gpu-snp
      nodeSelector: {}
  repository: nvcr.io/nvidia/cloud-native
  image: k8s-kata-manager
  version: v0.1.0
  imagePullPolicy: IfNotPresent
  imagePullSecrets: []
  env: []
  resources: {}

kata-qemu-nvidia-gpu 运行时类与 Kata Containers 一起使用。

kata-qemu-nvidia-gpu-snp 运行时类与保密容器一起使用,并且默认安装,即使在此配置中未使用。

使用 Kata Containers 的优势#

Kata Containers 的主要优势如下

  • 在容器中运行不受信任的工作负载。虚拟机提供了一层防御不受信任代码的屏障。

  • 限制对硬件设备(如 NVIDIA GPU)的访问。虚拟机被授予对特定设备的访问权限。此方法确保工作负载无法访问其他设备。

  • 透明部署未修改的容器。

限制和约束#

  • GPU 仅以直通模式作为单个 GPU 提供给容器。不支持多 GPU 直通和 vGPU。

  • 支持仅限于初始安装和配置。不支持为 Kata Containers 升级和配置现有集群。

  • 对 Kata Containers 的支持仅限于本页描述的实现。Operator 不支持 Red Hat OpenShift 沙盒容器。

  • 卸载 GPU Operator 或 NVIDIA Kata Manager 不会删除管理器在工作节点上的 /opt/nvidia-gpu-operator/artifacts/runtimeclasses/kata-qemu-nvidia-gpu/ 目录中下载和安装的文件。

  • NVIDIA 仅在 containerd 运行时中支持 Operator 和 Kata Containers。

集群拓扑注意事项#

您可以将集群中的所有工作节点配置为 Kata Containers,也可以将某些节点配置为 Kata Containers,而其他节点配置为传统容器。考虑以下示例。

节点 A 配置为运行传统容器。

节点 B 配置为运行 Kata Containers。

节点 A 接收以下软件组件

  • NVIDIA Driver Manager for Kubernetes – 用于安装数据中心驱动程序。

  • NVIDIA Container Toolkit – 用于确保容器可以访问 GPU。

  • NVIDIA Device Plugin for Kubernetes – 用于发现和向 kubelet 公告 GPU 资源。

  • NVIDIA DCGM and DCGM Exporter – 用于监控 GPU。

  • NVIDIA MIG Manager for Kubernetes – 用于管理支持 MIG 的 GPU。

  • Node Feature Discovery – 用于检测 CPU、内核和主机功能并标记工作节点。

  • NVIDIA GPU Feature Discovery – 用于检测 NVIDIA GPU 并标记工作节点。

节点 B 接收以下软件组件

  • NVIDIA Kata Manager for Kubernetes – 用于管理 NVIDIA 工件,例如 NVIDIA 优化的 Linux 内核镜像和初始 RAM 磁盘。

  • NVIDIA Sandbox Device Plugin – 用于发现和向 kubelet 公告直通 GPU。

  • NVIDIA VFIO Manager – 用于加载 vfio-pci 设备驱动程序并将其绑定到节点上的所有 GPU。

  • Node Feature Discovery – 用于检测 CPU 安全功能、NVIDIA GPU 和标记工作节点。

先决条件#

  • 您的主机配置为启用硬件虚拟化和访问控制服务 (ACS)。对于某些 AMD CPU 和 BIOS,ACS 可能归类于高级错误报告 (AER) 下。启用这些功能通常通过配置主机 BIOS 来完成。

  • 您的主机配置为支持 IOMMU。

    如果运行 ls /sys/kernel/iommu_groups 的输出包含 01 等,则您的主机已配置为支持 IOMMU。

    如果主机未配置或您不确定,请添加 intel_iommu=on Linux 内核命令行参数。对于大多数 Linux 发行版,您将参数添加到 /etc/default/grub 文件

    ...
    GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on modprobe.blacklist=nouveau"
    ...
    

    在 Ubuntu 系统上,在更改后运行 sudo update-grub 以配置引导加载程序。在其他系统上,您可能需要在更改后运行 sudo dracut。请参阅您的操作系统的文档。配置引导加载程序后,重新启动主机。

  • 您拥有 Kubernetes 集群,并且拥有集群管理员权限。

安装和配置概述#

安装和配置集群以支持带有 Kata Containers 的 NVIDIA GPU Operator 的步骤如下

  1. 标记要与 Kata Containers 一起使用的工作节点。

    此步骤确保您可以在集群中的某些节点上继续运行带有 GPU 或 vGPU 工作负载的传统容器工作负载。或者,您可以将默认沙盒工作负载设置为 vm-passthrough 以在所有工作节点上运行保密容器。

  2. 安装 Confidential Containers Operator。

    此步骤安装 Operator 以及 NVIDIA 用于 Kata Containers 的 Kata Containers 运行时。

  3. 安装 NVIDIA GPU Operator。

    您安装 Operator 并指定选项以部署 Kata Containers 所需的操作数。

安装完成后,您可以运行示例工作负载。

安装 Confidential Containers Operator#

执行以下步骤以安装和验证 Confidential Containers Operator

  1. 标记节点以在容器中运行虚拟机。仅标记要与 Kata Containers 一起运行的节点。

    $ kubectl label node <node-name> nvidia.com/gpu.workload.config=vm-passthrough
    
  2. 在环境变量中设置 Operator 版本

    $ export VERSION=v0.7.0
    
  3. 安装 Operator

    $ kubectl apply -k "github.com/confidential-containers/operator/config/release?ref=${VERSION}"
    

    示例输出

    namespace/confidential-containers-system created
    customresourcedefinition.apiextensions.k8s.io/ccruntimes.confidentialcontainers.org created
    serviceaccount/cc-operator-controller-manager created
    role.rbac.authorization.k8s.io/cc-operator-leader-election-role created
    clusterrole.rbac.authorization.k8s.io/cc-operator-manager-role created
    clusterrole.rbac.authorization.k8s.io/cc-operator-metrics-reader created
    clusterrole.rbac.authorization.k8s.io/cc-operator-proxy-role created
    rolebinding.rbac.authorization.k8s.io/cc-operator-leader-election-rolebinding created
    clusterrolebinding.rbac.authorization.k8s.io/cc-operator-manager-rolebinding created
    clusterrolebinding.rbac.authorization.k8s.io/cc-operator-proxy-rolebinding created
    configmap/cc-operator-manager-config created
    service/cc-operator-controller-manager-metrics-service created
    deployment.apps/cc-operator-controller-manager create
    
  4. 可选:查看 confidential-containers-system 命名空间中的 Pod 和服务

    $ kubectl get pod,svc -n confidential-containers-system
    

    示例输出

    NAME                                                 READY   STATUS    RESTARTS   AGE
    pod/cc-operator-controller-manager-c98c4ff74-ksb4q   2/2     Running   0          2m59s
    
    NAME                                                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
    service/cc-operator-controller-manager-metrics-service   ClusterIP   10.98.221.141   <none>        8443/TCP   2m59s
    
  5. 通过创建清单,然后编辑节点选择器,使运行时仅安装在标记的节点上,来安装示例 Confidential Containers 运行时。

    1. 在名为 ccruntime.yaml 的文件中创建清单的本地副本

      $ kubectl apply --dry-run=client -o yaml \
          -k "github.com/confidential-containers/operator/config/samples/ccruntime/default?ref=${VERSION}" > ccruntime.yaml
      
    2. 编辑 ccruntime.yaml 文件,并将节点选择器设置为如下所示

      apiVersion: confidentialcontainers.org/v1beta1
      kind: CcRuntime
      metadata:
        annotations:
      ...
      spec:
        ccNodeSelector:
          matchLabels:
            nvidia.com/gpu.workload.config: "vm-passthrough"
      ...
      
    3. 应用修改后的清单

      $ kubectl apply -f ccruntime.yaml
      

      示例输出

      ccruntime.confidentialcontainers.org/ccruntime-sample created
      

    等待几分钟,让 Operator 创建基本运行时类。

  6. 可选:查看运行时类

    $ kubectl get runtimeclass
    

    示例输出

    NAME            HANDLER         AGE
    kata            kata            13m
    kata-clh        kata-clh        13m
    kata-clh-tdx    kata-clh-tdx    13m
    kata-qemu       kata-qemu       13m
    kata-qemu-sev   kata-qemu-sev   13m
    kata-qemu-snp   kata-qemu-snp   13m
    kata-qemu-tdx   kata-qemu-tdx   13m
    

安装 NVIDIA GPU Operator#

步骤#

执行以下步骤以安装 Operator 以与 Kata Containers 一起使用

  1. 添加和更新 NVIDIA Helm 存储库

    $ helm repo add nvidia https://helm.ngc.nvidia.com/nvidia \
       && helm repo update
    
  2. 安装 Operator 时,至少指定以下选项。如果要在所有工作节点上默认运行 Kata Containers,还要指定 --set sandboxWorkloads.defaultWorkload=vm-passthough

    $ helm install --wait --generate-name \
       -n gpu-operator --create-namespace \
       nvidia/gpu-operator \
       --version=v24.9.2 \
       --set sandboxWorkloads.enabled=true \
       --set kataManager.enabled=true
    

    示例输出

    NAME: gpu-operator
    LAST DEPLOYED: Tue Jul 25 19:19:07 2023
    NAMESPACE: gpu-operator
    STATUS: deployed
    REVISION: 1
    TEST SUITE: None
    

验证#

  1. 验证 Kata Manager 和 VFIO Manager 操作数是否正在运行

    $ kubectl get pods -n gpu-operator
    

    示例输出

    NAME                                                         READY   STATUS      RESTARTS   AGE
    gpu-operator-57bf5d5769-nb98z                                1/1     Running     0          6m21s
    gpu-operator-node-feature-discovery-master-b44f595bf-5sjxg   1/1     Running     0          6m21s
    gpu-operator-node-feature-discovery-worker-lwhdr             1/1     Running     0          6m21s
    nvidia-kata-manager-bw5mb                                    1/1     Running     0          3m36s
    nvidia-sandbox-device-plugin-daemonset-cr4s6                 1/1     Running     0          2m37s
    nvidia-sandbox-validator-9wjm4                               1/1     Running     0          2m37s
    nvidia-vfio-manager-vg4wp                                    1/1     Running     0          3m36s
    
  2. 验证 kata-qemu-nvidia-gpukata-qemu-nvidia-gpu-snp 运行时类是否可用

    $ kubectl get runtimeclass
    

    示例输出

    NAME                       HANDLER                    AGE
    kata                       kata                       37m
    kata-clh                   kata-clh                   37m
    kata-clh-tdx               kata-clh-tdx               37m
    kata-qemu                  kata-qemu                  37m
    kata-qemu-nvidia-gpu       kata-qemu-nvidia-gpu       96s
    kata-qemu-nvidia-gpu-snp   kata-qemu-nvidia-gpu-snp   96s
    kata-qemu-sev              kata-qemu-sev              37m
    kata-qemu-snp              kata-qemu-snp              37m
    kata-qemu-tdx              kata-qemu-tdx              37m
    nvidia                     nvidia                     97s
    
  3. 可选:如果您具有对工作节点的主机访问权限,则可以执行以下步骤

    1. 确认主机对 GPU 使用 vfio-pci 设备驱动程序

      $ lspci -nnk -d 10de:
      

      示例输出

      65:00.0 3D controller [0302]: NVIDIA Corporation GA102GL [A10] [10de:2236] (rev a1)
              Subsystem: NVIDIA Corporation GA102GL [A10] [10de:1482]
              Kernel driver in use: vfio-pci
              Kernel modules: nvidiafb, nouveau
      
    2. 确认 NVIDIA Kata Manager 安装了 kata-qemu-nvidia-gpu 运行时类文件

      $ ls -1 /opt/nvidia-gpu-operator/artifacts/runtimeclasses/kata-qemu-nvidia-gpu/
      

      示例输出

      configuration-nvidia-gpu-qemu.toml
      kata-ubuntu-jammy-nvidia-gpu.initrd
      vmlinuz-5.xx.x-xxx-nvidia-gpu
      ...
      

运行示例工作负载#

Kata 容器的 Pod 规范需要以下内容

  • 指定 Kata 运行时类。

  • 指定直通 GPU 资源。

  1. 确定直通 GPU 资源名称

    kubectl get nodes -l nvidia.com/gpu.present -o json | \
      jq '.items[0].status.allocatable |
        with_entries(select(.key | startswith("nvidia.com/"))) |
        with_entries(select(.value != "0"))'
    

    示例输出

    {
       "nvidia.com/GA102GL_A10": "1"
    }
    
  2. 创建一个文件,例如 cuda-vectoradd-kata.yaml,如下例所示

    apiVersion: v1
    kind: Pod
    metadata:
      name: cuda-vectoradd-kata
      annotations:
        cdi.k8s.io/gpu: "nvidia.com/pgpu=0"
        io.katacontainers.config.hypervisor.default_memory: "16384"
    spec:
      runtimeClassName: kata-qemu-nvidia-gpu
      restartPolicy: OnFailure
      containers:
      - name: cuda-vectoradd
        image: "nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda11.7.1-ubuntu20.04"
        resources:
          limits:
            "nvidia.com/GA102GL_A10": 1
    

    io.katacontainers.config.hypervisor.default_memory 注解使用 16 GB 内存启动 VM。修改该值以适应您的工作负载。

  3. 创建 Pod

    $ kubectl apply -f cuda-vectoradd-kata.yaml
    
  4. 查看来自 Pod 的日志

    $ kubectl logs -n default cuda-vectoradd-kata
    

    示例输出

    [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

    $ kubectl delete -f cuda-vectoradd-kata.yaml
    

工作负载故障排除#

如果示例工作负载未运行,请确认您已标记节点以在容器中运行虚拟机

$ kubectl get nodes -l nvidia.com/gpu.workload.config=vm-passthrough

示例输出

NAME               STATUS   ROLES    AGE   VERSION
kata-worker-1      Ready    <none>   10d   v1.27.3
kata-worker-2      Ready    <none>   10d   v1.27.3
kata-worker-3      Ready    <none>   10d   v1.27.3

关于 Pod 注解#

创建 Pod 沙箱时,将使用 cdi.k8s.io/gpu: "nvidia.com/pgpu=0" 注解。此注解确保由 Kata 运行时创建的虚拟机以正确的 PCIe 拓扑创建,以便 GPU 直通成功。

此注解引用容器设备接口 (CDI) 设备 nvidia.com/pgpu=0pgpu 表示直通 GPU,0 表示设备索引。索引由 GPU 在 PCI 总线上枚举的顺序定义。该索引与 CUDA 索引不相关。

NVIDIA Kata Manager 在 GPU 节点上创建 CDI 规范。该文件包含每个直通设备的设备条目。

在以下示例 /var/run/cdi/nvidia.com-pgpu.yaml 文件中,显示了一个绑定到 VFIO PCI 驱动程序的 GPU

cdiVersion: 0.5.0
containerEdits: {}
devices:
- containerEdits:
    deviceNodes:
    - path: /dev/vfio/10
name: "0"
kind: nvidia.com/pgpu