GPU 并不是什么新鲜事。无数年来,我们在服务器中看到它们从事与繁重图形相关的各种工作。摄影、视频编辑、CAD 和加密货币只是需要强大 GPU 的几个类别。
另一个巨大的类别(很可能是目前最大的类别)是对机器学习和人工智能的 GPU 支持。目前,处理数据和训练模型的目标是大多数组织的首要任务,为此,GPU 支持是必要的
在这篇博文中,您将了解为什么 Kubernetes 上的 GPU 很重要,以及如何让 Kubernetes 集群为 GPU 做好准备。
为什么 Kubernetes 上的 GPU 支持很重要
就目前而言,Kubernetes 不仅是编排容器的事实标准,而且是编排整个工作流程的事实上的标准。无论您想要一种简单的方法来管理 Kubernetes 之外的服务(Azure vNet、AWS S3 存储桶等)、容器,还是运行虚拟机,您都可以在 Kubernetes 中完成这一切。这对于 Kubernetes 来说是必要的增长,因为它成为了首选的底层平台。
运行 ML 和 AI 工作负载的需求变得越来越重要,由于这种重要性,k8s 也需要一种方法来编排这些工作负载。
到目前为止,社区在使用 Kubeflow 和各种其他工具让 ML 在 Kubernetes 中正常工作方面做得非常出色。现在,是时候考虑如何更大规模地运行 ML 和 AI 工作负载了。是的,像 Kubeflow 这样的工具很重要且必要,但您还需要考虑底层组件。 GPU 是机器学习和人工智能最重要的底层组件之一。
随着法学硕士的规模越来越大,工程师们越来越多地听到有关 GPU 的信息。 ChatGPT 和整个 GenAI 并不需要适当的 GPU 支持,它只是增强了意识水平(有点像 Docker 对容器所做的那样)。现在的目标是了解如何在适当的 GPU 支持下正确运行解耦的应用程序和微服务(这是目前我们拥有的最小的外形尺寸)。
现在您已经了解了其背后的"原因",让我们来看看一些 GPU 选项。
GPU 代表图形处理单元
GPU选项
Kubernetes 集群有两种主要类型的选项:
- 本地部署
- 云中的托管 Kubernetes 服务
两者都能够支持 GPU,但使用和获取 GPU 的方式会有所不同。让我们从本地开始。
与所有本地/自托管 Kubernetes 集群一样,它们在您和/或您的组织管理的物理(希望是)虚拟服务器上运行。从技术角度来看,它可以是任何东西,从真正的服务器到桌面再到英特尔 NUC 或 Rasberry Pi。当今世界有很多运行 Kubernetes 的好方法。
在服务器、台式机或英特尔 NUC(支持外部 GPU)中,您可以拥有 GPU。例如,下面是我家里的桌面图片。我里面有一个 Nvidia GPU。
GPU 是您必须购买并添加到计算机/服务器中的硬件。
另一方面,在云中使用 GPU 则有些不同。
当您在云中使用基于 GPU 的工作节点/节点池时,您使用的是 GPU 的"一块"。物理 GPU 可以在其他云客户之间共享,就像其他基础设施资源(CPU、内存、存储等)一样。
每个主要云(甚至包括 Digital Ocean 在内的一些较小的云)都有 GPU 支持。
例如,在 Azure 中,N 系列 VM 以 GPU 为中心
在GCP中,您可以根据Nvidia型号进行选择。
只需每月 142K 美元的小价格,您也可以拥有自己的基于云的 GPU!
开玩笑吧,基于云的 GPU 非常昂贵。
旁注:Azure 的定价似乎更好一些。
就像任何其他基于云的环境一样,这一切都取决于您想要"租用"什么与您想要"拥有"什么。
最便宜/最快的选择是 GCP。有一个 Nvidia Tesla T4 选项,每小时费用为 2.95 美元,因此您可以以较低的成本使用几个小时。请记住将其删除,因为如果不删除,每月的费用将超过 2,000 美元。 Digital Ocean 可能有一个更便宜的选择,但出于本博客文章的目的,它没有经过测试。
英伟达安装
安装有两个步骤:
- Nvidia 驱动程序。这就像任何其他计算机驱动程序一样。 GPU 需要与操作系统兼容/绑定。
- 操作员。与任何其他 Kubernetes Operator 非常相似,Nvidia Operator 允许您扩展 Kubernetes API 以使用(在本例中)Nvidia 硬件。
让我们看看两者是如何完成的。
Kubernetes Operator 是 CRD(用于扩展 k8s API)和 Controller(提供 Kubernetes 中资源的自我修复功能)的组合。
司机
对于驱动程序,您有两种选择:
- 自行安装驱动并手动管理。
- 让云端为您管理驱动程序。
如果您选择第 1 种,则可以配置如下所示的 DaemonSet。
yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nvidia-device-plugin-daemonset
namespace: kube-system
spec:
selector:
matchLabels:
name: nvidia-device-plugin-ds
updateStrategy:
type: RollingUpdate
template:
metadata:
labels:
name: nvidia-device-plugin-ds
spec:
tolerations:
- key: "sku"
operator: "Equal"
value: "gpu"
effect: "NoSchedule"
priorityClassName: "system-node-critical"
containers:
- image: nvcr.io/nvidia/k8s-device-plugin:v0.15.0
name: nvidia-device-plugin-ctr
env:
- name: FAIL_ON_INIT_ERROR
value: "false"
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
volumeMounts:
- name: device-plugin
mountPath: /var/lib/kubelet/device-plugins
volumes:
- name: device-plugin
hostPath:
path: /var/lib/kubelet/device-plugins
如果选择第 2 个选项,则可以将集群设置为使用驱动程序自动部署。请注意下面的屏幕截图中 AKS 实现如何实际安装驱动程序和 Operator。
然而,GCP 只进行驱动程序安装。
就我个人而言,我觉得如果你无论如何都使用云提供商,你不妨让他们来处理这件事。云提供商在后台执行与 DaemonSet 相同的操作,因此您不妨让他们为您处理这些事情。
操作员
如果您没有使用 Azure 实施,则需要安装和管理 Operator。幸运的是,有 Helm Chart 可用。
首先,添加 Nvidia Helm Chart。
csharp
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
接下来,确保 Helm Chart 是最新的。
sql
helm repo update
最后但并非最不重要的一点是,安装 Helm Chart。资源将进入名为 的命名空间。
arduino
helm install gpuoperator --wait \
-n gpu-operator --create-namespace \
nvidia/gpu-operator
旁注:我在 EKS 上遇到了驱动程序问题。它一直在尝试下载亚马逊的特定驱动程序,但它一直说找不到容器映像。为了解决这个问题,我只是在 Helm 配置中使用了 driver.enabled=false
并安装了驱动程序,如您在上一节中看到的那样。
现在 Operator 已安装,您可以开始在 Pod 部署中使用它。
工作负载部署
当您在 Kubernetes 中使用 GPU 时,启用它们时需要考虑两个地方:
- 在资源>限制下。
- 在节点选择器内。
就像您可以设置 CPU 和内存限制一样,您也可以设置 GPU 限制。默认情况下,当您使用启用了 GPU 的工作节点时,GPU 就在那里,但您的资源可能无法充分利用它们。您可以确保设置希望可用于工作流程的 GPU 数量。
您还可以通过节点选择器设置特定的 GPU。这允许您选择要在部署中使用的确切 GPU。
让我们看几个例子。
Ubuntu 示例
下面的示例显示了所使用的一个 GPU 的限制。
yaml
apiVersion: v1
kind: Pod
metadata:
name: gpu-operator-test
spec:
restartPolicy: OnFailure
containers:
- name: cuda-vector-add
image: "nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda11.7.1-ubuntu20.04"
resources:
limits:
nvidia.com/gpu: 1
此示例使用来自 Nvidia 的 GPU 就绪示例容器映像。这是一个 Ubuntu 20.04 自定义映像。
奥拉马示例
下面是一个示例:
resources
地图下使用了一个 GPU。nodeSelector
下的特定 GPU。
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ollama
namespace: ollama
spec:
selector:
matchLabels:
name: ollama
replicas: 2
template:
metadata:
labels:
name: ollama
spec:
containers:
- name: ollama
image: ollama/ollama:latest
resources:
limits:
nvidia.com/gpu: 1
ports:
- name: http
containerPort: 11434
protocol: TCP
nodeSelector:
nvidia.com/gpu.product: H100-PCIE-80GB
这是一种很好的方法,不仅可以指定 Pod 需要使用的 GPU 数量,还可以指定特定的 GPU 来处理 Pod 的潜在负载。如果您在 Kubernetes 中运行以 GPU 为中心的应用程序堆栈,那么与其他应用程序相比,您的应用程序很可能需要更多的 GPU 能力。