Kubernetes 非常适合各种类型的容器化工作负载,从服务到作业再到有状态应用程序。但是 AI 和需要 GPU 的机器学习工作负载呢?是的,Kubernetes 也支持这些,但有很多细微差别。
译自Optimizing AI and Machine Learning Workloads in Kubernetes,作者 Eugene Burd 。
本文将介绍 Kubernetes 如何支持 GPU,包括调度、过度订阅和时间共享以及安全性/隔离。此外,我们将讨论三大公共云提供商如何支持这些功能,以及如何确保您的 GPU 节点仅由 GPU 工作负载使用。
设备插件
让我们首先看一下 Kubernetes 支持 GPU 的机制。Kubernetes 本身不知道任何关于 GPU 的信息。相反,它提供了一个扩展机制,称为设备插件。设备插件框架允许第三方广告节点上可用的其他功能,如 GPU、InfiniBand 适配器等。
设备插件,通常以守护进程集实现,向节点的 kubelet 注册自己,并向 kubelet 广告节点上可调度的资源。Kubelet 将此信息传递给 API 服务器,然后由 Kubernetes 调度程序使用,以调度请求每个容器的资源的工作负载到节点上。
![](https://file.jishuzhan.net/article/1758386952387694593/5789b4516ea3a50c2166d8bf4201339a.webp)
从工作负载请求 GPU
既然我们了解了 Kubernetes 如何知道 GPU,那么让我们来讨论容器如何请求一个 GPU。工作负载可以以类似请求 CPU 或内存的方式请求 GPU,但有些不同。与 Kubernetes 本身支持的 CPU 不同,GPU(和设备插件一般)仅支持限制(您可以提供请求,但如果这样做,您也必须提供限制,并且两个值必须相等)。限制还必须是整数(不允许使用小数限制)。
让我们看一个示例 pod。在本例中,pod 正在请求 1 个 Nvidia gpu。调度程序将尝试找到一个具有可用 Nvidia gpu 且尚未分配的节点,并继续在该节点上放置 pod。
yaml
apiVersion: v1
kind: Pod
metadata:
name: my-gpu-pod
spec:
containers:
- name: my-gpu-container
image: nvidia/cuda:11.0.3-runtime-ubuntu20.04
command: ["/bin/bash", "-c", "--"]
args: ["while true; do sleep 600; done;"]
resources:
requests:
cpu: 100m
memory: 500Mi
limits:
memory: 1000Mi
nvidia.com/gpu: 1
过度订阅和时间共享
CPU 时间共享由 CNI 使用 linuxcgroups本地处理。它受您的请求和限制的影响 - 请参阅有关如何设置 CPU 请求和限制的文章(以及为什么要避免限制)。
GPU 时间共享对于 Nvidia GPU 通过两种机制支持:
- 多实例 GPU(Nvidia A100、H100)支持多个计算和内存单元。在这种情况下,您可以配置要公开的分区数量。此配置驱动设备插件显示每个物理 GPU 的多个"虚拟 GPU"。这由AWS、Azure和GCP支持。
- 对于单实例 GPU,Nvidia 的 GPU 调度程序通过对 GPU 上的工作负载进行时间分片来支持时间共享。这只有AWS和GCP支持。
虽然这种方法意味着可以过度订阅 GPU,但您必须小心,因为您的工作负载可能会被饿死,与 CPU 不同,没有完全公平的调度程序(CFS),也没有 cgroup 优先级,因此时间只能由工作负载平等划分。
安全性/隔离
与 CPU 不同,当前 GPU 内没有进程或内存隔离。这意味着调度到 GPU 上的所有工作负载共享其内存,因此您只应在互相信任的工作负载之间共享 GPU。
创建 GPU 节点
既然我们已经知道如何请求 GPU,您可能想知道如何创建具有 GPU 的节点以及如何安装设备插件。这根据您使用的 kubernetes 提供商而有所不同,我们将在下面介绍 3 大提供商。
AWS
AWS 支持使用任何 EC2 GPU 实例类型创建节点组。您可以从两个选项中进行选择:
- 运行预装了 Nvidia 驱动程序的 EKS 加速的 Amazon Linux AMI 。在这种情况下,您需要自行单独安装Nvidia 设备插件。
- 在节点组上运行 Nvidia 的GPU Operator。在这种情况下,升级是手动的。
Azure
Azure 支持使用三种选项创建节点池:
- 创建 GPU 节点池,其中自动包括 GPU 驱动程序,但需要您自己安装 Nvidia 设备插件。
- 使用AKS GPU 镜像预览,其中包括 GPU 驱动程序和 Nvidia 设备插件。在这种情况下,升级是手动的。
- 在节点组上运行Nvidia 的 GPU Operator,它为您处理所有事项。
GCP
GKE 支持使用两种选项创建节点池。
- 让 google 管理 GPU 驱动程序安装以及设备插件。使用此选项还允许 GKE 自动升级节点。
- 自己管理 GPU 驱动程序和设备插件
保护 GPU 节点免受非 GPU 工作负载的影响
最后,既然您已经创建了 GPU 节点,您会希望这些节点免受集群上运行的任何非 GPU 工作负载的影响。您可以通过污点和容忍来实现这一点。在创建节点池和组时,您会想要应用污点。 如果集群具有非 GPU 节点池,GKE 会自动为您执行此操作。其他提供商不会,所以您需要确保这样做。
对于 pod,您会希望为污点提供容忍,以便它们可以调度到 GPU 节点上。下面的示例为名为"nvidia.com/gpu"的污点创建了一个容忍,这允许此 pod 在 nvidia GPU 节点上运行。
yaml
apiVersion: v1
kind: Pod
metadata:
name: my-gpu-pod
spec:
containers:
- name: my-gpu-container
image: nvidia/cuda:11.0.3-runtime-ubuntu20.04
command: ["/bin/bash", "-c", "--"]
args: ["while true; do sleep 600; done;"]
resources:
requests:
cpu: 100m
memory: 500Mi
limits:
memory: 1000Mi
nvidia.com/gpu: 1
tolerations:
- key: "nvidia.com/gpu"
operator: "Exists"
effect: "NoSchedule"
随着 AI 和机器学习工作负载的不断增长,希望您考虑在 Kubernetes 上运行它们,而不是更昂贵的云提供商专有选项。
您是否已经尝试在 Kubernetes 上运行 GPU 工作负载?哪些方面效果好?遇到哪些问题?
本文在云云众生(yylives.cc/)首发,欢迎大家访问。