前言
AI
落地時,在某些場景下 AI
模型在訓練或者是推理時,其算力要求不需要佔用整卡的 GPU
,比如只需要0.5卡 GPU
即可滿足需求。
在這種情況下,可以使用 GPU
虛擬化技術來解決這個問題,將整卡的 GPU
虛擬化為兩個0.5卡的 GPU
,這樣就可以在一張卡上同時跑兩個 AI
訓練或者 AI
推理應用服務,極大壓榨算力資源,降低成本。
vGPU
是 NVIDIA
提供的一種 GPU
虛擬化的一種方案,同時也可以實現對多使用者的強 GPU
隔離方案
基本痛點:
- 容器使用的單卡
GPU
利用率不夠高,特別是推理任務; - 為了提高
GPU
的利用率、避免算力浪費,需要在單個GPU
上執行多個容器 - 而
vGPU
的使用需要額外從NVIDIA
公司購買license
。年度訂閱和永久許可證
其他vGPU外掛
https://github.com/4paradigm/k8s-vgpu-scheduler
4paradigm
提供了 k8s-device-plugin
,該外掛基於NVIDIA官方外掛( NVIDIA/k8s-device-plugin
),在保留官方功能的基礎上,實現了對物理 GPU
進行切分,並對視訊記憶體和計算單元進行限制,從而模擬出多張小的 vGPU卡`。
在 k8s
叢集中,基於這些切分後的 vGPU
進行排程,使不同的容器可以安全的共享同一張物理 GPU
,提高 GPU
的利用率。
此外,外掛還可以對視訊記憶體做虛擬化處理(使用到的視訊記憶體可以超過物理上的視訊記憶體),執行一些超大視訊記憶體需求的任務,或提高共享的任務數。
部署
配置docker
nvidia-smi
命令,檢視當前顯示卡資訊
如果你使用了 docker
,需要講將 nvidia runtime
設定為 docker runtime
預設值,此檔案通常在 /etc/docker/daemon.json
路徑:
{
"default-runtime": "nvidia",
"runtimes": {
"nvidia": {
"path": "/usr/bin/nvidia-container-runtime",
"runtimeArgs": []
}
}
}
docker
重新載入配置
systemctl daemon-reload && systemctl restart docker
配置containerd
你需要在節點上將 nvidia runtime
做為你的 containerd runtime
預設值。
我們將編輯 containerd daemon
的配置檔案,此檔案通常在 /etc/containerd/config.toml
路徑
version = 2
[plugins]
[plugins."io.containerd.grpc.v1.cri"]
[plugins."io.containerd.grpc.v1.cri".containerd]
default_runtime_name = "nvidia"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia]
privileged_without_host_devices = false
runtime_engine = ""
runtime_root = ""
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia.options]
BinaryName = "/usr/bin/nvidia-container-runtime"
containerd
重新載入配置
systemctl daemon-reload && systemctl restart containerd
檢視當前gpu分配情況
可以透過 kubectl describe node node1
命令,檢視你指定節點的 gpu
個數情況:
Allocatable:
cpu: 32
ephemeral-storage: 94059137278
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 65738804Ki
nvidia.com/gpu: 2
pods: 110
關閉NVIDIA官方外掛
把 nvidia-device-plugin ds
描述檔案移除即可,為安全可以移動到其它目錄,如下移動到家目錄做備份儲存。
mv /etc/kubernetes/manifests/nvidia-device-plugin.yml .
啟用新的gpu裝置外掛
啟動 4paradigm
新的 k8s-device-plugin
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:
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ""
labels:
name: nvidia-device-plugin-ds
spec:
tolerations:
- key: CriticalAddonsOnly
operator: Exists
- key: nvidia.com/gpu
operator: Exists
effect: NoSchedule
priorityClassName: "system-node-critical"
containers:
- image: 4pdosc/k8s-device-plugin:latest
imagePullPolicy: Always
name: nvidia-device-plugin-ctr
args: ["--fail-on-init-error=false", "--device-split-count=6", "--device-memory-scaling=2", "--device-cores-scaling=1"]
env:
- name: PCIBUSFILE
value: "/usr/local/vgpu/pciinfo.vgpu"
- name: NVIDIA_MIG_MONITOR_DEVICES
value: all
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
add: ["SYS_ADMIN"]
volumeMounts:
- name: device-plugin
mountPath: /var/lib/kubelet/device-plugins
- name: vgpu-dir
mountPath: /usr/local/vgpu
- mountPath: /tmp
name: hosttmp
volumes:
- name: device-plugin
hostPath:
path: /var/lib/kubelet/device-plugins
- name: vgpu-dir
hostPath:
path: /usr/local/vgpu
- hostPath:
path: /tmp
name: hosttmp
nodeSelector:
nvidia-vgpu: "on"
將以上程式碼儲存為 vgpu-nvdp.yaml
檔案,然後安裝
kubectl apply -f vgpu-nvdp.yaml
打上gpu標籤
在需要進行虛擬化的節點打上標籤 nvidia-vgpu:"on"
,否則該節點不會被排程到,或者你打其他標籤也行,取決於你設定的 nodeSelector
kubectl label node {nodeid} nvdia-vgpu=on
等外掛部署完成後,再次執行 kubectl describe node node1
命令,檢視節點的 gpu
個數情況
執行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
nvidia.com/gpumem: 3000 # 每個vGPU申請3000m視訊記憶體 (可選,整數型別)
nvidia.com/gpucores: 30 # 每個vGPU的算力為30%實際顯示卡的算力 (可選,整數型別)
如果你的任務無法執行在任何一個節點上(例如任務的 nvidia.com/gpu
大於叢集中任意一個 GPU
節點的實際 GPU
數量),那麼任務會卡在 pending
狀態
現在你可以在容器執行 nvidia-smi
命令,然後比較 vGPU
和實際 GPU
視訊記憶體大小的不同。
監控vGPU使用情況
排程器部署成功後,監控預設自動開啟,你可以透過
http://{nodeip}:{monitorPort}/metrics
來獲取監控資料,其中 monitorPort
可以在 Values
中進行配置,預設為 31992
grafana dashboard
示例:https://github.com/4paradigm/k8s-vgpu-scheduler/blob/master/docs/dashboard_cn.md
注意 節點上的
vGPU
狀態只有在其使用vGPU
後才會被統計W