在 Kubernetes 中使用 vGPU 設備插件

vGPU device plugin 基于 NVIDIA 官方插件(NVIDIA/k8s-device-plugin),在保留官方功能的基礎上,實現了對物理 GPU 進行切分,并對顯存和計算單元進行限制,從而模擬出多張小的 vGPU 卡。在 k8s 集群中,基于這些切分后的 vGPU 進行調度,使不同的容器可以安全的共享同一張物理 GPU,提高 GPU 的利用率。此外,插件還可以對顯存做虛擬化處理(使用到的顯存可以超過物理上的顯存),運行一些超大顯存需求的任務,或提高共享的任務數,可參考性能測試報告。
GitHub 地址:https://github.com/4paradigm/k8s-device-plugin
使用場景
顯存、計算單元利用率低的情況,如在一張 GPU 卡上運行 10 個 tf-serving。 需要大量小顯卡的情況,如教學場景把一張 GPU 提供給多個學生使用、云平臺提供小 GPU 實例。 物理顯存不足的情況,可以開啟虛擬顯存,如大 batch、大模型的訓練。
性能測試
在測試報告中,我們一共在下面五種場景都執(zhí)行了 ai-benchmark 測試腳本,并匯總最終結果:
| 測試環(huán)境 | 環(huán)境描述 |
|---|---|
| Kubernetes version | v1.12.9 |
| Docker version | 18.09.1 |
| GPU Type | Tesla V100 |
| GPU Num | 2 |
| 測試名稱 | 測試用例 |
|---|---|
| Nvidia-device-plugin | k8s + nvidia 官方 k8s-device-plugin |
| vGPU-device-plugin | k8s + VGPU k8s-device-plugin,無虛擬顯存 |
| vGPU-device-plugin(virtual device memory) | k8s + VGPU k8s-device-plugin,高負載,開啟虛擬顯存 |
測試內容
| test id | 名稱 | 類型 | 參數 |
|---|---|---|---|
| 1.1 | Resnet-V2-50 | inference | batch=50,size=346*346 |
| 1.2 | Resnet-V2-50 | training | batch=20,size=346*346 |
| 2.1 | Resnet-V2-152 | inference | batch=10,size=256*256 |
| 2.2 | Resnet-V2-152 | training | batch=10,size=256*256 |
| 3.1 | VGG-16 | inference | batch=20,size=224*224 |
| 3.2 | VGG-16 | training | batch=2,size=224*224 |
| 4.1 | DeepLab | inference | batch=2,size=512*512 |
| 4.2 | DeepLab | training | batch=1,size=384*384 |
| 5.1 | LSTM | inference | batch=100,size=1024*300 |
| 5.2 | LSTM | training | batch=10,size=1024*300 |
測試結果:


測試步驟:
1、安裝 nvidia-device-plugin,并配置相應的參數
2、運行 benchmark 任務
$ kubectl apply -f benchmarks/ai-benchmark/ai-benchmark.yml
3、通過 kubctl logs 查看結果
$ kubectl logs [pod id]
功能
指定每張物理 GPU 切分的 vGPU 的數量 限制 vGPU 的顯存 限制 vGPU 的計算單元 對已有程序零改動
實驗性功能
虛擬顯存
vGPU 的顯存總和可以超過 GPU 實際的顯存,這時候超過的部分會放到內存里,對性能有一定的影響。
產品限制
分配到節(jié)點上任務所需要的 vGPU 數量,不能大于節(jié)點實際 GPU 數量
已知問題
開啟虛擬顯存時,如果某張物理 GPU 的顯存已用滿,而這張 GPU 上還有空余的 vGPU,此時分配到這些 vGPU 上的任務會失敗。 目前僅支持計算任務,不支持視頻編解碼處理。
開發(fā)計劃
支持視頻編解碼處理 支持 Multi-Instance GPUs (MIG)
安裝要求
NVIDIA drivers >= 384.81 nvidia-docker version > 2.0 docker 已配置 nvidia 作為默認 runtime Kubernetes version >= 1.10
快速入門
GPU 節(jié)點準備
以下步驟要在所有 GPU 節(jié)點執(zhí)行。這份 README 文檔假定 GPU 節(jié)點已經安裝 NVIDIA 驅動和nvidia-docker套件。
注意你需要安裝的是nvidia-docker2而非nvidia-container-toolkit。因為新的--gpus選項 kubernetes 尚不支持。安裝步驟舉例:
# 加入套件倉庫
$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
$ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
$ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
$ sudo apt-get update && sudo apt-get install -y nvidia-docker2
$ sudo systemctl restart docker
你需要在節(jié)點上將 nvidia runtime 做為你的 docker runtime 預設值。我們將編輯 docker daemon 的配置文件,此文件通常在/etc/docker/daemon.json路徑:
{
"default-runtime": "nvidia",
"runtimes": {
"nvidia": {
"path": "/usr/bin/nvidia-container-runtime",
"runtimeArgs": []
}
}
"default-shm-size": "2G"
}
如果
runtimes字段沒有出現, 前往的安裝頁面執(zhí)行安裝操作 nvidia-docker。
Kubernetes 開啟 vGPU 支持
當你在所有 GPU 節(jié)點完成前面提到的準備動作,如果 Kubernetes 有已經存在的 NVIDIA 裝置插件,需要先將它移除。然后,你能通過下面指令下載我們的 Daemonset yaml 文件:
$ wget https://raw.githubusercontent.com/4paradigm/k8s-device-plugin/master/nvidia-device-plugin.yml
在這個 DaemonSet 文件中, 你能發(fā)現nvidia-device-plugin-ctr容器有一共 4 個 vGPU 的客制化參數:
fail-on-init-error:布爾類型, 預設值是 true。當這個參數被設置為 true 時,如果裝置插件在初始化過程遇到錯誤時程序會返回失敗,當這個參數被設置為 false 時,遇到錯誤它會打印信息并且持續(xù)阻塞插件。持續(xù)阻塞插件能讓裝置插件即使部署在沒有 GPU 的節(jié)點(也不應該有 GPU)也不會拋出錯誤。這樣你在部署裝置插件在你的集群時就不需要考慮節(jié)點是否有 GPU,不會遇到報錯的問題。然而,這么做的缺點是如果 GPU 節(jié)點的裝置插件因為一些原因執(zhí)行失敗,將不容易察覺?,F在預設值為當初始化遇到錯誤時程序返回失敗,這個做法應該被所有全新的部署采納。device-split-count:整數類型,預設值是 2。NVIDIA 裝置的分割數。對于一個總共包含N張 NVIDIA GPU 的 Kubernetes 集群,如果我們將device-split-count參數配置為K,這個 Kubernetes 集群將有K * N個可分配的 vGPU 資源。注意,我們不建議將 NVIDIA 1080 ti/NVIDIA 2080 tidevice-split-count參數配置超過 5,將 NVIDIA T4 配置超過 7,將 NVIDIA A100 配置超過 15。device-memory-scaling:浮點數類型,預設值是 1。NVIDIA 裝置顯存使用比例,可以大于 1(啟用虛擬顯存,實驗功能)。對于有M顯存大小的 NVIDIA GPU,如果我們配置device-memory-scaling參數為S,在部署了我們裝置插件的 Kubenetes 集群中,這張 GPU 分出的 vGPU 將總共包含S * M顯存。每張 vGPU 的顯存大小也受device-split-count參數影響。在先前的例子中,如果device-split-count參數配置為K,那每一張 vGPU 最后會取得S * M / K大小的顯存。device-cores-scaling:浮點數類型,預設值是 1。NVIDIA 裝置算力使用比例,可以大于 1。如果device-cores-scaling參數配置為Sdevice-split-count參數配置為K,那每一張 vGPU 對應的一段時間內 sm 利用率平均上限為S / K。屬于同一張物理 GPU 上的所有 vGPU sm 利用率總和不超過 1。enable-legacy-preferred:布爾類型,預設值是 false。對于不支持 PreferredAllocation 的 kublet(<1.19)可以設置為 true,更好的選擇合適的 device,開啟時,本插件需要有對 pod 的讀取權限,可參看 legacy-preferred-nvidia-device-plugin.yml。對于 kubelet >= 1.9 時,建議關閉。
完成這些可選參數的配置后,你能透過下面命令開啟 vGPU 的支持:
$ kubectl apply -f nvidia-device-plugin.yml
運行 GPU 任務
NVIDIA vGPUs 現在能透過資源類型nvidia.com/gpu被容器請求:
apiVersion: v1
kind: Pod
metadata:
name: gpu-pod
spec:
containers:
- name: ubuntu-container
image: ubuntu:18.04
command: ["bash", "-c", "sleep 86400"]
resources:
limits:
nvidia.com/gpu: 2 # 請求2個vGPUs
現在你可以在容器執(zhí)行nvidia-smi命令,然后比較 vGPU 和實際 GPU 顯存大小的不同。
注意:如果你使用插件裝置時,如果沒有請求 vGPU 資源,那容器所在機器的所有 vGPU 都將暴露給容器。
測試
TensorFlow 1.14.0-1.15.0/2.2.0-2.6.2 torch1.1.0-1.8.0 mxnet 1.4.0 mindspore 1.1.1 xgboost 1.0-1.4 nccl 2.4.8-2.9.9
以上框架均通過測試。
日志
啟動日志:在使用 vGPU 功能的 pod 中添加環(huán)境變量
LIBCUDA_LOG_LEVEL=5
獲取 vGPU 相關的日志:
$ kubectl logs xxx | grep libvgpu.so
反饋和參與
bug、疑惑、修改歡迎提在 Github Issues 想了解更多或者有想法可以參與到 Discussions 和 slack 交流
原文鏈接:https://www.cnblogs.com/9849aa/p/15037772.html?utm_source=pocket_mylist


你可能還喜歡
點擊下方圖片即可閱讀

云原生是一種信仰 ??
關注公眾號
后臺回復?k8s?獲取史上最方便快捷的 Kubernetes 高可用部署工具,只需一條命令,連 ssh 都不需要!


點擊 "閱讀原文" 獲取更好的閱讀體驗!
發(fā)現朋友圈變“安靜”了嗎?


