GPU 資源調(diào)度:k8s-device-plugin 知多少 ?
Hello folks,我是 Luga,今天我們來(lái)聊一下人工智能應(yīng)用場(chǎng)景 - 基于 k8s-device-plugin 機(jī)制所實(shí)現(xiàn)的 GPU 資源動(dòng)態(tài)調(diào)度。
近幾年,隨著大數(shù)據(jù)和人工智能技術(shù)的迅猛發(fā)展,AI 應(yīng)用場(chǎng)景日益豐富,成為推動(dòng)產(chǎn)業(yè)升級(jí)的重要驅(qū)動(dòng)力。云計(jì)算作為 AI 發(fā)展的堅(jiān)實(shí)基礎(chǔ),提供了強(qiáng)大的計(jì)算資源和靈活的部署環(huán)境。
而 Kubernetes 作為云原生領(lǐng)域的旗艦項(xiàng)目,憑借其出色的可擴(kuò)展性、高可用性和自動(dòng)化能力,成為了管理云原生應(yīng)用的事實(shí)標(biāo)準(zhǔn)。
而在 AI 領(lǐng)域,GPU 作為加速計(jì)算的利器,其重要性不言而喻。云原生編排系統(tǒng) Kubernetes 憑借其強(qiáng)大的資源調(diào)度能力,為 GPU 資源的管理提供了高效可靠的解決方案。
一、如何理解 Kubernetes Device Plugin ?
Kubernetes Device Plugin 是 Kubernetes 中的一種標(biāo)準(zhǔn)化資源擴(kuò)展機(jī)制,旨在將特殊硬件(如 GPU、FPGA)作為可調(diào)度資源集成到 Kubernetes 的資源管理框架中。
對(duì)于 NVIDIA GPU,Device Plugin 充當(dāng)了連接 Kubernetes 調(diào)度器與底層 GPU 硬件的橋梁,負(fù)責(zé)發(fā)現(xiàn)、注冊(cè)和管理 GPU 資源,使工作負(fù)載能夠無(wú)縫利用 GPU 提供的計(jì)算能力。
apiVersion: v1
kind: Pod
metadata:
name: gpu-pod
spec:
restartPolicy: Never
containers:
- name: cuda-container
image: nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda10.2
resources:
limits:
nvidia.com/gpu: 1
tolerations:
- key: nvidia.com/gpu
operator: Exists
effect: NoSchedule
從本質(zhì)上來(lái)講,Kubernetes Device Plugin 設(shè)計(jì)目標(biāo)是提供一個(gè)通用的接口,使硬件供應(yīng)商能夠開(kāi)發(fā)自定義插件來(lái)支持其設(shè)備,同時(shí)確保與 Kubernetes 調(diào)度系統(tǒng)的良好兼容性。
眾所周知,Kubernetes 本身通過(guò) Linux 的 namespace 和 cgroups 實(shí)現(xiàn)資源隔離與限制,將 CPU 和內(nèi)存等資源按需分配給各個(gè) Pod。例如,Kubernetes 可以根據(jù)節(jié)點(diǎn)的資源狀況,將需要計(jì)算和存儲(chǔ)的 Pod 調(diào)度到具有相應(yīng)空閑資源的節(jié)點(diǎn)上,并為容器中的進(jìn)程設(shè)置 CPU 和內(nèi)存的配額。然而,當(dāng)前 Kubernetes 內(nèi)部尚不支持對(duì) GPU 資源的直接調(diào)度和隔離,而是依賴于設(shè)備插件(Device Plugin) 和調(diào)度器擴(kuò)展,通過(guò)第三方工具來(lái)完成這項(xiàng)功能。
NVIDIA Kubernetes 設(shè)備插件 是 Kubernetes 中最常用的 GPU 設(shè)備插件之一,專門為 NVIDIA GPU 的資源分配與調(diào)度提供支持。其核心功能包括如下:
(1) 自動(dòng)發(fā)現(xiàn) GPU 設(shè)備
Device Plugin 能夠自動(dòng)檢測(cè)節(jié)點(diǎn)中的 GPU 硬件,并將其作為資源注冊(cè)到 Kubernetes API 中,使調(diào)度器能夠識(shí)別和分配 GPU。
(2) 資源暴露與分配
Device Plugin 通過(guò)標(biāo)準(zhǔn)的 Kubernetes API,將 GPU 資源暴露給 Pods,使其能夠根據(jù)配置請(qǐng)求 GPU 加速計(jì)算資源。
(3) 硬件抽象
通過(guò)屏蔽底層 GPU 設(shè)備的復(fù)雜性,Device Plugin 提供了一個(gè)高層次的抽象接口,讓開(kāi)發(fā)者專注于工作負(fù)載的邏輯,而無(wú)需關(guān)心硬件的具體細(xì)節(jié)。
(4) 熱插拔支持
Device Plugin 支持動(dòng)態(tài)設(shè)備注冊(cè),使得在集群運(yùn)行時(shí)新增或移除 GPU 等硬件資源成為可能,大大增強(qiáng)了系統(tǒng)的靈活性。
(5) 與調(diào)度器的無(wú)縫集成
Device Plugin 能夠與 Kubernetes 調(diào)度器協(xié)同工作,根據(jù) Pod 的資源需求高效調(diào)度 GPU 資源,避免資源爭(zhēng)搶或浪費(fèi)。
二、Kubernetes Device Plugin 實(shí)現(xiàn)原理解析
當(dāng)使用 Kubernetes 時(shí),用戶通常希望能夠在 Pod 對(duì)象中直接聲明所需的 GPU 資源,并通過(guò) Kubernetes 的調(diào)度器(kube-scheduler)自動(dòng)完成所需 GPU 的分配。例如,以下 Pod 清單中使用了 limits 字段來(lái)指定對(duì) NVIDIA GPU 的資源需求:
apiVersion: v1
kind: Pod
metadata:
name: cuda-vector-add
spec:
restartPolicy: OnFailure
containers:
- name: cuda-vector-add
image: "k8s.gcr.io/cuda-vector-add:v0.1"
resources:
limits:
nvidia.com/gpu: 1
在上述配置中,nvidia.com/gpu 是聲明 GPU 需求的一種特殊字段,稱為 Extended Resource(擴(kuò)展資源),其值為 1,表示該 Pod 請(qǐng)求一個(gè) NVIDIA 類型的 GPU。通過(guò)這種方式,用戶能夠在 Pod 級(jí)別直觀地表達(dá)對(duì) GPU 資源的需求,極大地簡(jiǎn)化了對(duì)高性能計(jì)算資源的使用和管理。
為了使 Kubernetes 能夠正確地調(diào)度 GPU 資源,調(diào)度器需要了解每個(gè)節(jié)點(diǎn)上的 GPU 可用情況。GPU 資源的可用量通常通過(guò) Node 對(duì)象 的 Status 字段報(bào)告。例如,一個(gè)節(jié)點(diǎn)對(duì)象可以包含以下?tīng)顟B(tài)信息:
apiVersion: v1
kind: Node
...
Status:
Capacity:
cpu: 2
memory: 2049008Ki
nvidia.com/gpu: 1
在上述狀態(tài)中,nvidia.com/gpu: 1 表示該節(jié)點(diǎn)擁有 1 個(gè)可用的 NVIDIA GPU。調(diào)度器根據(jù)這些信息,將 GPU 請(qǐng)求的 Pod 調(diào)度到滿足條件的節(jié)點(diǎn)上。
通常,在實(shí)際的業(yè)務(wù)場(chǎng)景中,為節(jié)點(diǎn)添加 GPU 資源的可用量信息,可以通過(guò)以下兩種方式實(shí)現(xiàn):
1.手動(dòng)更新 Extended Resource
Extended Resource 是一種基于節(jié)點(diǎn)級(jí)別(Node-level)的 API,允許用戶直接更新節(jié)點(diǎn)的 Status 字段以報(bào)告 GPU 的可用資源。例如,使用 PATCH 請(qǐng)求更新某節(jié)點(diǎn)的 GPU 資源。
$ curl --header "Content-Type: application/json-patch+json" \
--request PATCH \
--data '[{"op": "add", "path": "/status/capacity/nvidia.com/gpu", "value": "1"}]' \
http://localhost:8001/api/v1/nodes/<your-node-name>/status
這種方式適用于簡(jiǎn)單場(chǎng)景,可以獨(dú)立于設(shè)備插件(Device Plugin)使用。通過(guò)手動(dòng)更新節(jié)點(diǎn)的狀態(tài)信息,調(diào)度器便可記錄 GPU 類型及其可用數(shù)量。然而,這種方法需要額外的腳本化管理,維護(hù)成本較高,且不具備動(dòng)態(tài)檢測(cè)硬件變化的能力。
2.使用 Device Plugin 自動(dòng)維護(hù)
更常見(jiàn)和推薦的方式是通過(guò) Device Plugin 來(lái)完成 GPU 資源的自動(dòng)管理。在 Kubernetes 中,所有硬件資源(如 GPU、NIC、TPU 等)的發(fā)現(xiàn)、報(bào)告和分配通常由 Device Plugin 統(tǒng)一管理。
Device Plugin 會(huì)運(yùn)行在每個(gè)節(jié)點(diǎn)上,自動(dòng)檢測(cè)硬件資源的類型和數(shù)量,并通過(guò) Kubernetes API 動(dòng)態(tài)更新節(jié)點(diǎn)的狀態(tài)信息。
在 Kubernetes 中,所有專用硬件資源的管理都依賴于 Device Plugin(設(shè)備插件) 框架進(jìn)行擴(kuò)展和實(shí)現(xiàn)。Device Plugin 提供了一種標(biāo)準(zhǔn)化的機(jī)制,用于發(fā)現(xiàn)、注冊(cè)和管理節(jié)點(diǎn)上的專用硬件設(shè)備(例如 GPU、FPGA、NIC 等)。通過(guò)這一框架,Kubernetes 可以將這些硬件資源統(tǒng)一抽象為節(jié)點(diǎn)資源的一部分,從而納入標(biāo)準(zhǔn)的調(diào)度和管理流程。
不僅如此,Device Plugin 還負(fù)責(zé)匯報(bào)和維護(hù) Extended Resources(擴(kuò)展資源) 的狀態(tài),這些擴(kuò)展資源是 Kubernetes 用于表示專用硬件資源的一種邏輯抽象形式。在擴(kuò)展資源匯報(bào)的過(guò)程中,設(shè)備插件會(huì)基于節(jié)點(diǎn)上的硬件狀態(tài),動(dòng)態(tài)更新資源的可用性和健康狀況,確保調(diào)度器能夠準(zhǔn)確了解節(jié)點(diǎn)的資源分布情況。
如下圖所示,Device Plugin 在 Kubernetes 的資源管理體系中承擔(dān)了關(guān)鍵角色,通過(guò)與 Kubelet 的緊密協(xié)作,將專用硬件資源的發(fā)現(xiàn)與分配無(wú)縫集成到 Kubernetes 的調(diào)度框架中,為分布式環(huán)境中的硬件資源調(diào)配提供了標(biāo)準(zhǔn)化的支持。這一機(jī)制不僅提升了資源管理的靈活性,還極大擴(kuò)展了 Kubernetes 的硬件適配能力,使其能夠支持各種復(fù)雜的異構(gòu)計(jì)算場(chǎng)景,如 AI 訓(xùn)練、數(shù)據(jù)分析和高性能網(wǎng)絡(luò)通信等。
通常而言,Kubernetes Device Plugin 的工作流程包括以下幾個(gè)關(guān)鍵步驟,具體可參考:
(1) 設(shè)備發(fā)現(xiàn)
Device Plugin 會(huì)掃描工作節(jié)點(diǎn)上的 GPU 設(shè)備,并通過(guò) gRPC 接口向 kubelet 報(bào)告設(shè)備列表,包括每個(gè)設(shè)備的標(biāo)識(shí)符和狀態(tài)信息。
(2) 設(shè)備注冊(cè)
Device Plugin 向 kubelet 注冊(cè)后,這些設(shè)備會(huì)被 Kubernetes API 服務(wù)器識(shí)別并記錄,成為 Kubernetes 資源調(diào)度的一部分。例如,GPU 資源可能被標(biāo)記為 nvidia.com/gpu。
(3) 資源分配
當(dāng)一個(gè) Pod 請(qǐng)求 GPU 時(shí),調(diào)度器根據(jù)請(qǐng)求的資源規(guī)格將任務(wù)分配到具有可用 GPU 的節(jié)點(diǎn)上。kubelet 與 Device Plugin 協(xié)作,為 Pod 分配所需的 GPU 設(shè)備,并將設(shè)備信息掛載到容器中。
(4) 生命周期管理
Device Plugin 負(fù)責(zé)監(jiān)控 GPU 的狀態(tài),確保其健康運(yùn)行。當(dāng)設(shè)備狀態(tài)發(fā)生變化(如故障或移除)時(shí),Device Plugin 會(huì)通知 kubelet,觸發(fā)資源更新。
三、Kubernetes Device Plugin 優(yōu)劣勢(shì)分析
隨著 Kubernetes 在異構(gòu)計(jì)算場(chǎng)景(如 GPU、FPGA、NIC 等專用硬件資源)中的廣泛應(yīng)用,Device Plugin(設(shè)備插件)機(jī)制成為 Kubernetes 內(nèi)部管理專用硬件資源的標(biāo)準(zhǔn)化擴(kuò)展方案。作為 Kubernetes 原生的設(shè)備管理框架,Device Plugin 提供了一種高效、靈活且可擴(kuò)展的機(jī)制,用于發(fā)現(xiàn)、注冊(cè)和調(diào)度節(jié)點(diǎn)上的專用硬件資源。然而,盡管其在解決硬件資源調(diào)度難題方面表現(xiàn)出色,但仍然存在一定的局限性。
盡管通過(guò) Device Plugin,Kubernetes 在調(diào)度時(shí)可以一定程度上滿足對(duì) Extended Resource 的基本需求,但其調(diào)度機(jī)制主要基于設(shè)備數(shù)量的匹配。這種簡(jiǎn)單的資源分配方式在面對(duì)異構(gòu)設(shè)備或復(fù)雜硬件屬性需求時(shí)顯得不足。例如,當(dāng)硬件設(shè)備的屬性多樣化且 Pod 對(duì)某些特定硬件屬性有明確要求時(shí),單純依賴數(shù)量匹配的調(diào)度策略無(wú)法提供所需的精細(xì)化調(diào)度能力。此外,在資源分配方面,Device Plugin 對(duì)于配額(Quota)的限制粒度較粗,難以滿足更細(xì)化的資源管理需求。
1.基于節(jié)點(diǎn)標(biāo)簽與節(jié)點(diǎn)選擇器的調(diào)度方案
為了彌補(bǔ)上述不足,一種常見(jiàn)的替代方案是使用 Node Label 和 Node Selector 來(lái)優(yōu)化資源調(diào)度。通過(guò)為節(jié)點(diǎn)設(shè)置標(biāo)簽(Node Label)并在 Pod 配置中使用選擇器(Node Selector),可以實(shí)現(xiàn)某種類型硬件的定向分配。例如,將同一類型的 GPU(如 NVIDIA Tesla K80)掛載到同一個(gè)節(jié)點(diǎn),并通過(guò)節(jié)點(diǎn)標(biāo)簽將資源屬性暴露給調(diào)度器,從而實(shí)現(xiàn)按類型資源的調(diào)度。然而,這種方式依然存在明顯的限制:
- 屬性覆蓋不足:這種方法僅適用于同類型硬件資源的分配,無(wú)法支持更復(fù)雜的調(diào)度需求。例如,當(dāng)一個(gè)節(jié)點(diǎn)上掛載了多塊顯存不同的 GPU(如 8GB 和 12GB),某些應(yīng)用希望使用顯存大于 10GB 的 GPU,這種需求無(wú)法通過(guò)節(jié)點(diǎn)標(biāo)簽和選擇器實(shí)現(xiàn)。
- 靈活性不足:節(jié)點(diǎn)標(biāo)簽是一種靜態(tài)配置,無(wú)法動(dòng)態(tài)感知節(jié)點(diǎn)上硬件資源的變化。
2.基于 CRD 和調(diào)度器擴(kuò)展機(jī)制的解決方案
為了解決上述問(wèn)題,可以借助 Kubernetes 的 CustomResourceDefinition (CRD) 和 Scheduler Extender 機(jī)制。這種方法通過(guò)定義自定義資源(CR)來(lái)詳細(xì)描述硬件資源的屬性,并通過(guò)擴(kuò)展調(diào)度器邏輯,實(shí)現(xiàn)對(duì)異構(gòu)設(shè)備的精準(zhǔn)調(diào)度。以下是具體思路:
(1)定義 CRD 表達(dá)設(shè)備屬性
自定義資源定義(CRD)可用來(lái)表示設(shè)備的復(fù)雜屬性,例如顯存大小、計(jì)算能力(Compute Capability)等。節(jié)點(diǎn)上的設(shè)備插件負(fù)責(zé)動(dòng)態(tài)發(fā)現(xiàn)這些屬性并將其通過(guò) CR 報(bào)告給 Kubernetes 集群。
(2)擴(kuò)展調(diào)度器邏輯
使用 Scheduler Extender,可自定義調(diào)度邏輯,使調(diào)度器能夠根據(jù) Pod 對(duì)資源的特定需求(如顯存大于 10GB)篩選符合條件的節(jié)點(diǎn)。這種方法通過(guò)外部擴(kuò)展避免直接修改 Kubernetes 核心代碼,同時(shí)提高調(diào)度的靈活性和可擴(kuò)展性。
(3)動(dòng)態(tài)資源調(diào)度
結(jié)合 CRD 和調(diào)度器擴(kuò)展,設(shè)備插件能夠動(dòng)態(tài)報(bào)告硬件資源的狀態(tài),并根據(jù) Pod 的資源請(qǐng)求進(jìn)行智能調(diào)度。這種方法特別適合處理異構(gòu)設(shè)備場(chǎng)景。
盡管 CRD 和 Scheduler Extender 提供了更強(qiáng)大的功能,但它們的使用往往涉及到一定程度的 Kubernetes 源碼修改或額外的開(kāi)發(fā)投入:
- 復(fù)雜性增加:引入自定義資源和擴(kuò)展調(diào)度器需要開(kāi)發(fā)和維護(hù)額外的邏輯,對(duì)團(tuán)隊(duì)的技術(shù)能力提出了更高要求。
- 兼容性風(fēng)險(xiǎn):擴(kuò)展方案可能與 Kubernetes 的未來(lái)版本更新產(chǎn)生兼容性問(wèn)題,增加了維護(hù)成本。
綜上所述,Kubernetes Device Plugin 是實(shí)現(xiàn) GPU 資源調(diào)度的基礎(chǔ)組件,通過(guò)提供標(biāo)準(zhǔn)化接口將 GPU 資源透明地暴露給 Kubernetes 調(diào)度器,為工作負(fù)載的 GPU 需求提供精準(zhǔn)匹配。其輕量化設(shè)計(jì)專注于資源分配,簡(jiǎn)化了 GPU 與 Kubernetes 的集成,是滿足基本 GPU 使用需求的理想選擇。
然而,Kubernetes Device Plugin 功能相對(duì)單一,無(wú)法覆蓋驅(qū)動(dòng)安裝、高級(jí)功能配置等更復(fù)雜的運(yùn)維需求。因此,它更適合已完成基礎(chǔ) GPU 環(huán)境搭建的場(chǎng)景,尤其是在對(duì)調(diào)度性能和資源開(kāi)銷要求較高的工作負(fù)載中展現(xiàn)了獨(dú)特優(yōu)勢(shì)。對(duì)于尋求靈活、高效 GPU 資源調(diào)度的用戶,Device Plugin 是一種低門檻、高適配性的解決方案。
Happy Coding ~
Reference :
- [1] https://github.com/NVIDIA/k8s-device-plugin
- [2] https://aws.amazon.com/blogs/opensource/virtual-gpu-device-plugin-for-inference-workload-in-kubernetes/