kubernetes安装配置使用vGPU
前言
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
fail-on-init-error:布尔类型, 预设值是 true。当这个参数被设置为 true 时,如果装置插件在初始化过程遇到错误时程序会返回失败,当这个参数被设置为 false 时,遇到错误它会打印信息并且持续阻塞插件。持续阻塞插件能让装置插件即使部署在没有 GPU 的节点(也不应该有 GPU)也不会抛出错误。这样你在部署装置插件在你的集群时就不需要考虑节点是否有 GPU,不会遇到报错的问题。然而,这么做的缺点是如果 GPU 节点的装置插件因为一些原因执行失败,将不容易察觉。现在预设值为当初始化遇到错误时程序返回失败,这个做法应该被所有全新的部署采纳。
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 时,建议关闭。
打上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
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· [翻译] 为什么 Tracebit 用 C# 开发
· Deepseek官网太卡,教你白嫖阿里云的Deepseek-R1满血版
· 2分钟学会 DeepSeek API,竟然比官方更好用!
· .NET 使用 DeepSeek R1 开发智能 AI 客户端
· 刚刚!百度搜索“换脑”引爆AI圈,正式接入DeepSeek R1满血版