在 Kubernetes 中優化 AI 和機器學習工作負載
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 調度程序使用,以調度請求每個容器的資源的工作負載到節點上。
圖片
從工作負載請求 GPU
既然我們了解了 Kubernetes 如何知道 GPU,那么讓我們來討論容器如何請求一個 GPU。工作負載可以以類似請求 CPU 或內存的方式請求 GPU,但有些不同。與 Kubernetes 本身支持的 CPU 不同,GPU(和設備插件一般)僅支持限制(您可以提供請求,但如果這樣做,您也必須提供限制,并且兩個值必須相等)。限制還必須是整數(不允許使用小數限制)。
讓我們看一個示例 pod。在本例中,pod 正在請求 1 個 Nvidia gpu。調度程序將嘗試找到一個具有可用 Nvidia gpu 且尚未分配的節點,并繼續在該節點上放置 pod。
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 節點上運行。
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 工作負載?哪些方面效果好?遇到哪些問題?