GPU Operator 与 Kata Containers#
关于带有 Kata Containers 的 Operator#
注意
技术预览版功能在生产环境中不受支持,并且功能不完整。技术预览版功能提供对即将推出的产品功能的早期访问,使客户能够在开发过程中测试功能并提供反馈。这些版本可能没有任何文档,并且测试受到限制。
Kata Containers 与传统容器(如 Docker 容器)相似,但略有不同。
传统容器打包软件以实现与主机的用户空间隔离,但容器在主机上运行,并与主机共享操作系统内核。共享操作系统内核是一个潜在的漏洞。
Kata 容器在主机上的虚拟机中运行。虚拟机具有单独的操作系统和操作系统内核。与传统容器相比,硬件虚拟化和单独的内核提供了改进的工作负载隔离。
NVIDIA GPU Operator 与 Kata 容器运行时协同工作。Kata 使用虚拟机监控程序(如 QEMU)来提供轻量级虚拟机,该虚拟机具有单一用途——运行 Kubernetes Pod。
下图显示了 Kubernetes 用于运行 Kata 容器的软件组件。
带有 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
的输出包含0
、1
等,则您的主机已配置为支持 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 的步骤如下
标记要与 Kata Containers 一起使用的工作节点。
此步骤确保您可以在集群中的某些节点上继续运行带有 GPU 或 vGPU 工作负载的传统容器工作负载。或者,您可以将默认沙盒工作负载设置为
vm-passthrough
以在所有工作节点上运行保密容器。安装 Confidential Containers Operator。
此步骤安装 Operator 以及 NVIDIA 用于 Kata Containers 的 Kata Containers 运行时。
安装 NVIDIA GPU Operator。
您安装 Operator 并指定选项以部署 Kata Containers 所需的操作数。
安装完成后,您可以运行示例工作负载。
安装 Confidential Containers Operator#
执行以下步骤以安装和验证 Confidential Containers Operator
标记节点以在容器中运行虚拟机。仅标记要与 Kata Containers 一起运行的节点。
$ kubectl label node <node-name> nvidia.com/gpu.workload.config=vm-passthrough
在环境变量中设置 Operator 版本
$ export VERSION=v0.7.0
安装 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
可选:查看
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
通过创建清单,然后编辑节点选择器,使运行时仅安装在标记的节点上,来安装示例 Confidential Containers 运行时。
在名为
ccruntime.yaml
的文件中创建清单的本地副本$ kubectl apply --dry-run=client -o yaml \ -k "github.com/confidential-containers/operator/config/samples/ccruntime/default?ref=${VERSION}" > ccruntime.yaml
编辑
ccruntime.yaml
文件,并将节点选择器设置为如下所示apiVersion: confidentialcontainers.org/v1beta1 kind: CcRuntime metadata: annotations: ... spec: ccNodeSelector: matchLabels: nvidia.com/gpu.workload.config: "vm-passthrough" ...
应用修改后的清单
$ kubectl apply -f ccruntime.yaml
示例输出
ccruntime.confidentialcontainers.org/ccruntime-sample created
等待几分钟,让 Operator 创建基本运行时类。
可选:查看运行时类
$ 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 一起使用
添加和更新 NVIDIA Helm 存储库
$ helm repo add nvidia https://helm.ngc.nvidia.com/nvidia \ && helm repo update
安装 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
验证#
验证 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
验证
kata-qemu-nvidia-gpu
和kata-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
可选:如果您具有对工作节点的主机访问权限,则可以执行以下步骤
确认主机对 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
确认 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 资源。
确定直通 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" }
创建一个文件,例如
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。修改该值以适应您的工作负载。创建 Pod
$ kubectl apply -f cuda-vectoradd-kata.yaml
查看来自 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
删除 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=0
。pgpu
表示直通 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