前言

AI 落地时,在某些场景下 AI 模型在训练或者是推理时,其算力要求不需要占用整卡的 GPU,比如只需要0.5卡 GPU 即可满足需求。

在这种情况下,可以使用 GPU 虚拟化技术来解决这个问题,将整卡的 GPU 虚拟化为两个0.5卡的 GPU,这样就可以在一张卡上同时跑两个 AI 训练或者 AI 推理应用服务,极大压榨算力资源,降低成本。

vGPUNVIDIA 提供的一种 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

kubernetes安装配置使用vGPU的更多相关文章

  1. Kubernetes安装配置(包括master和node)

    部署Kubernetes云计算平台,至少准备两台服务器,此处为4台,包括一台Docker仓库: Kubernetes Master节点:192.168.124.20 Kubernetes Node1节 ...

  2. 离线环境下使用二进制方式安装配置Kubernetes集群

    本文环境 Redhat Linux 7.3,操作系统采用的最小安装方式. Kubernetes的版本为 V1.10. Docker版本为18.03.1-ce. etcd 版本为 V3.3.8. 1. ...

  3. Docker系列(九)Kubernetes安装

    环境: A.B两天机器A机器IP:192.169.0.104,B机器IP:192.168.0.102,其中A为Master节点,B为Slave节点 操作系统:Centos7 Master与Slave节 ...

  4. kubernetes安装

    本文主要参考自: https://blog.csdn.net/real_myth/article/details/78719244 还有一份更适合在生产环境使用的超强高可用(多master,nginx ...

  5. docker官方文档学习-1-Docker for mac安装配置

    https://docs.docker.com/docker-for-mac/ Get started with Docker for Mac 首先像在本博客docker-1-环境安装及例子实践处将环 ...

  6. [ci] jenkins kubernetes插件配置(容器模式)-通过jnlp

    有个小伙用sh结合jenkins搞的k8s cicd还不错 jenkins kubernetes插件 首先插件管理,搜索kubernetes plugin安装 配置kubernetes云 配置项目 执 ...

  7. CoreDNS kubernetes 安装使用

     kubernetes 以前是skydns 后面变为 dnsmasq,coredns 也是一个不错的工具 1. 准备环境 安装 kubernetes 配置 kubelet 的cluster-dns 2 ...

  8. 轻松加愉快的 Kubernetes 安装教程

    轻松加愉快的 Kubernetes 安装教程 马哥Linux运维 2 days ago 作者:无聊的学习者 来源:见文末 在国内安装 K8S,一直是大家很头痛的问题,各种麻烦,关键是还不知道需要下载什 ...

  9. Kuboard Kubernetes安装

    一.简介 Kubernetes 容器编排已越来越被大家关注,然而使用 Kubernetes 的门槛却依然很高,主要体现在这几个方面: 集群的安装复杂,出错概率大 Kubernetes相较于容器化,引入 ...

  10. Kustomize安装配置入门文档

    一,简介 kustomize是sig-cli的一个子项目,它的设计目的是给kubernetes的用户提供一种可以重复使用同一套配置的声明式应用管理,从而在配置工作中用户只需要管理和维护kubernet ...

随机推荐

  1. 龙哥量化:通达信板块概念FAQ,*期强势、*期弱势是怎么划分的?等问题是官网的解释,股友可以根据文章的提示迸发策略灵感

    如果您需要代写公式, 请联系我. 龙哥QQ:591438821 龙哥微信:Long622889 比如第9条,*期强势:20日涨幅>=30%,     3日涨幅>0,非停牌.非ST.非未开板 ...

  2. React部署到线上Nginx环境中刷新页面后404解决方案

    我们需要在Nginx的配置文件中修改以下内容(通常Nginx配置文件位置为/etc/nginx/nginx.conf): server { # ... location / { # ... # 增加下 ...

  3. Qt编写视频监控系统76-Onvif跨网段组播搜索和单播搜索的实现

    一.前言 在视频监控行业一般会用国际onvif工具来测试设备是否支持onvif协议,工具的名字叫ONVIF Device Manager(还有个工具叫ONVIF Device Test Tool,专用 ...

  4. Qt编写安防视频监控系统35-onvif抓拍图片

    一.前言 以前不知道onvif也可以做抓拍功能,直到近期重新用Onvif Device Test Tool工具测试的时候,发现还有抓图的接口,于是抓跑分析出要收发的数据,然后加入到自己封装的onvif ...

  5. 大端地址 小端地址 网络字节序 intel主机字节序

    小端字节序:低字节数据存放在内存低地址处,高字节数据存放在内存高地址处:大端字节序:高字节数据存放在内存低地址处,低字节数据存放在内存高地址处. 网络字节序: MSB 高字节前存法 Most Sign ...

  6. TNN-linux编译测试记录

    Github: https://github.com/Tencent/TNN docs: https://github.com/Tencent/TNN/blob/master/doc/cn/user/ ...

  7. Android增加USB Camera摄像头驱动支持

    一般情况下kernel需要添加以下宏 ================================= CONFIG_VIDEO_DEV=yCONFIG_VIDEOBUF2_CORE=yCONFIG ...

  8. CSP2024 游记

    前文 Day -1 上午考试了,多少分忘了. 晚上老师布置模板题. Day 0 继续前一天的模板题,并没有 AK. Day 1 J 组 先看 T1,发现是一道简单的水题,切了. 再看 T2,也是水题, ...

  9. 工作流调度器-Azkaban

    1.工作流调度器 1.为什么需要工作流调度系统 一个完整的数据分析系统通常都是由大量任务单元组成: shell脚本程序,java程序,mapreduce程序.hive脚本等 各任务单元之间存在时间先后 ...

  10. Golang-容器3

    http://c.biancheng.net/golang/container/ Go语言数组详解 数组是一个由固定长度的特定类型元素组成的序列,一个数组可以由零个或多个元素组成.因为数组的长度是固定 ...