随着人工智能和大模型的快速发展,云上GPU资源共享变得必要,因为它可以降低硬件成本,提升资源利用效率,并满足模型训练和推理对大规模并行计算的需求。

在kubernetes内置的资源调度功能中,GPU调度只能根据“核数”进行调度,但是深度学习等算法程序执行过程中,资源占用比较高的是显存,这样就形成了很多的资源浪费。

目前的GPU资源共享方案有两种。一种是将一个真正的GPU分解为多个虚拟GPU,即vGPU,这样就可以基于vGPU的数量进行调度;另一种是根据GPU的显存进行调度。

本文将讲述如何安装kubernetes组件实现根据GPU显存调度资源。

系统信息

  • 系统:centos stream8

  • 内核:4.18.0-490.el8.x86_64

  • 驱动:NVIDIA-Linux-x86_64-470.182.03

  • docker:20.10.24

  • kubernetes版本:1.24.0

1. 驱动安装

请登录nvida官网自行安装:https://www.nvidia.com/Download/index.aspx?lang=en-us

2. docker安装

请自行安装docker或其他容器运行时,如果使用其他容器运行时,第三步配置请参考NVIDA官网 https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#installation-guide

注意:官方支持docker、containerd、podman,但本文档只验证过docker的使用,如果使用其他容器运行时,请注意差异性。

3. NVIDIA Container Toolkit 安装

  1. 设置仓库与GPG Key
distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
&& curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.repo | sudo tee /etc/yum.repos.d/nvidia-container-toolkit.repo
  1. 开始安装
sudo dnf clean expire-cache --refresh
sudo dnf install -y nvidia-container-toolkit
  1. 修改docker配置文件添加容器运行时实现
sudo nvidia-ctk runtime configure --runtime=docker
  1. 修改/etc/docker/daemon.json,设置nvidia为默认容器运行时(必需)
{
"default-runtime": "nvidia",
"runtimes": {
"nvidia": {
"path": "/usr/bin/nvidia-container-runtime",
"runtimeArgs": []
}
}
}
  1. 重启docker并开始验证是否生效
sudo systemctl restart docker
sudo docker run --rm --runtime=nvidia --gpus all nvidia/cuda:11.6.2-base-ubuntu20.04 nvidia-smi

如果返回如下数据,说明配置成功

+-----------------------------------------------------------------------------+
| NVIDIA-SMI 450.51.06 Driver Version: 450.51.06 CUDA Version: 11.0 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|===============================+======================+======================|
| 0 Tesla T4 On | 00000000:00:1E.0 Off | 0 |
| N/A 34C P8 9W / 70W | 0MiB / 15109MiB | 0% Default |
| | | N/A |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=============================================================================|
| No running processes found |
+-----------------------------------------------------------------------------+

4. 安装K8S GPU调度器

  1. 首先执行以下yaml,部署调度器
# rbac.yaml
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: gpushare-schd-extender
rules:
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- apiGroups:
- ""
resources:
- pods
verbs:
- update
- patch
- get
- list
- watch
- apiGroups:
- ""
resources:
- bindings
- pods/binding
verbs:
- create
- apiGroups:
- ""
resources:
- configmaps
verbs:
- get
- list
- watch
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: gpushare-schd-extender
namespace: kube-system
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: gpushare-schd-extender
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: gpushare-schd-extender
subjects:
- kind: ServiceAccount
name: gpushare-schd-extender
namespace: kube-system

# deployment yaml
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: gpushare-schd-extender
namespace: kube-system
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: gpushare
component: gpushare-schd-extender
template:
metadata:
labels:
app: gpushare
component: gpushare-schd-extender
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ''
spec:
hostNetwork: true
tolerations:
- effect: NoSchedule
operator: Exists
key: node-role.kubernetes.io/master
- effect: NoSchedule
key: node-role.kubernetes.io/control-plane
operator: Exists
- effect: NoSchedule
operator: Exists
key: node.cloudprovider.kubernetes.io/uninitialized
nodeSelector:
node-role.kubernetes.io/control-plane: ""
serviceAccount: gpushare-schd-extender
containers:
- name: gpushare-schd-extender
image: registry.cn-hangzhou.aliyuncs.com/acs/k8s-gpushare-schd-extender:1.11-d170d8a
env:
- name: LOG_LEVEL
value: debug
- name: PORT
value: "12345"

# service.yaml
---
apiVersion: v1
kind: Service
metadata:
name: gpushare-schd-extender
namespace: kube-system
labels:
app: gpushare
component: gpushare-schd-extender
spec:
type: NodePort
ports:
- port: 12345
name: http
targetPort: 12345
nodePort: 32766
selector:
# select app=ingress-nginx pods
app: gpushare
component: gpushare-schd-extender
  1. 在/etc/kubernetes目录下添加调度策略配置文件
#scheduler-policy-config.yaml
---
apiVersion: kubescheduler.config.k8s.io/v1beta2
kind: KubeSchedulerConfiguration
clientConnection:
kubeconfig: /etc/kubernetes/scheduler.conf
extenders:
# 不知道为什么不支持svc的方式调用,必须用nodeport
- urlPrefix: "http://gpushare-schd-extender.kube-system:12345/gpushare-scheduler"
filterVerb: filter
bindVerb: bind
enableHTTPS: false
nodeCacheCapable: true
managedResources:
- name: aliyun.com/gpu-mem
ignoredByScheduler: false
ignorable: false

上面的 http://gpushare-schd-extender.kube-system:12345 注意要替换为你本地部署的{nodeIP}:{gpushare-schd-extender的nodeport端口},否则会访问不到

查询命令如下:

kubectl get service gpushare-schd-extender -n kube-system -o jsonpath='{.spec.ports[?(@.name=="http")].nodePort}'
  1. 修改kubernetes调度配置 /etc/kubernetes/manifests/kube-scheduler.yaml
1. 在commond中添加
- --config=/etc/kubernetes/scheduler-policy-config.yaml

2. 添加pod挂载目录
在volumeMounts:中添加
- mountPath: /etc/kubernetes/scheduler-policy-config.yaml
name: scheduler-policy-config
readOnly: true
在volumes:中添加
- hostPath:
path: /etc/kubernetes/scheduler-policy-config.yaml
type: FileOrCreate
name: scheduler-policy-config

注意:这里千万不要改错,否则可能会出现莫名其妙的错误

示例如下:



  1. 配置rbac及安装device插件
kubectl create -f https://raw.githubusercontent.com/AliyunContainerService/gpushare-device-plugin/master/device-plugin-rbac.yaml
kubectl create -f https://raw.githubusercontent.com/AliyunContainerService/gpushare-device-plugin/master/device-plugin-ds.yaml

5. 在GPU节点上添加标签

kubectl label node <target_node> gpushare=true

6. 安装kubectl Gpu 插件

cd /usr/bin/
wget https://github.com/AliyunContainerService/gpushare-device-plugin/releases/download/v0.3.0/kubectl-inspect-gpushare
chmod u+x /usr/bin/kubectl-inspect-gpushare

7. 验证

  1. 使用kubectl查询GPU资源使用情况
# kubectl inspect gpushare
NAME IPADDRESS GPU0(Allocated/Total) GPU Memory(GiB)
cn-shanghai.i-uf61h64dz1tmlob9hmtb 192.168.0.71 6/15 6/15
cn-shanghai.i-uf61h64dz1tmlob9hmtc 192.168.0.70 3/15 3/15
------------------------------------------------------------------------------
Allocated/Total GPU Memory In Cluster:
9/30 (30%)
  1. 创建一个有GPU需求的资源,查看其资源调度情况
apiVersion: apps/v1
kind: Deployment
metadata:
name: binpack-1
labels:
app: binpack-1
spec:
replicas: 1
selector: # define how the deployment finds the pods it manages
matchLabels:
app: binpack-1
template: # define the pods specifications
metadata:
labels:
app: binpack-1
spec:
tolerations:
- effect: NoSchedule
key: cloudClusterNo
operator: Exists
containers:
- name: binpack-1
image: cheyang/gpu-player:v2
resources:
limits:
# 单位GiB
aliyun.com/gpu-mem: 3

8. 问题排查

如果在安装过程中发现资源未安装成功,可以通过pod查看日志

kubectl get po -n kube-system -o=wide | grep gpushare-device
kubecl logs -n kube-system <pod_name>

参考地址:

NVIDA官网container-toolkit安装文档: https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#docker

阿里云GPU插件安装:https://github.com/AliyunContainerService/gpushare-scheduler-extender/blob/master/docs/install.md

如何在kubernetes环境中共享GPU的更多相关文章

  1. 业务零影响!如何在Online环境中巧用MySQL传统复制技术【转】

    业务零影响!如何在Online环境中巧用MySQL传统复制技术 这篇文章我并不会介绍如何部署一个MySQL复制环境或keepalived+双主环境,因为此类安装搭建的文章已经很多,大家也很熟悉.在这篇 ...

  2. 如何在windows环境中搭建apache+subversion(ZT)

    我一直有一个想法就是在本机上象scm一样的搭建一个subversion服务器,然后每天写完代码的时候提交一下,这种感觉好好哦,之前我在windows环境中搭建过纯subversion的服务器兴奋过一阵 ...

  3. (23/24) webpack实战技巧:如何在webpack环境中使用Json

    在webpack1或者webpack2版本中,若想在webpack环境中加载Json文件,则需要加载一个json-loader的loader进来的.但是在webpack3.x版本中,则不需要在另外引入 ...

  4. JDK 9 发布仅数月,为何在生产环境中却频遭嫌弃?

    千呼万唤始出来,在经历了整整一年的跳票之后,Java 9 终于在 9 月 21 日拨开云雾,露出真正的面目.对众多 Java 程序员来说,这一天无疑是一个重大的日子,首先 Java 开发者们再也不用羡 ...

  5. (转)如何在maven环境中设置JVM参数

    有时候我们需要设定maven环境下的JVM参数,以便通过maven执行的命令或启动的系统能得到它们需要的参数设定.比如:当我们使用jetty:run启动jetty服务器时,在进行热部署时会经常发生:J ...

  6. 如何在virtualenv环境中安装指定的python版本

    指定python版本:virtualenv   -p python执行文件路径     自定义虚拟环境名称.如果文件路径有空格,用引号. 如果不指定python版本,则默认使用环境变量中的python ...

  7. conda常用命令,如何在conda环境中安装gym库?

    查看已安装的环境: conda info -e 或 conda env list 创建新环境gymlab: conda create -n gymlab python=3.5 激活环境gymlab: ...

  8. openstack镜像如何在vmware 环境中运行

    1.云镜像文件下载地址: http://sahara-files.mirantis.com/sahara-juno-spark-1.0.0-ubuntu-14.04.qcow2(安装有sahara-s ...

  9. helm在kubernetes环境中搭建

    1.安装helm 1.1.安装helm客户端 各个版本的helm:https://github.com/helm/helm/releases wget https://get.helm.sh/helm ...

  10. 如何在spring环境中做单元测试

    在测试类的上方加入以下注解 @RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("classpath:spring.xm ...

随机推荐

  1. 作为国产深度学习框架中分布式计算特性最强大的OneFlow的最大缺点是什么?

    OneFlow是国产深度学习框架中分布式计算特性最强大的,因为其原生支持分布式特性,世界上的历史中的深度学习框架唯一可以做到这一点的也就只有Google的TensorFlow和Jax了,虽然有人说Go ...

  2. 【转载】 CV往哪卷?李飞飞指出三颗「北极星」:具身智能,视觉推理和场景理解

    原文地址: https://news.cnblogs.com/n/720105/ 新智元报道 编辑:LRS ============================================== ...

  3. Vector源码解读

    1.背景 阅读源码是提高编程技能的有效方式... 面试中也经常问到源码相关的问题..... 2.源码解读 在解读Vector时大家可以先解读ArrayList,因为这个两个的逻辑几乎是一样的.... ...

  4. [POI2008] POC-Trains 题解

    前言 题目链接:洛谷. 时间复杂度和输入同阶的做法. 题意简述 有 \(n\)(\(n \leq 10^3\))个长 \(m\) 的字符串,\(q\)(\(q \leq 10^5\))次操作,交换两个 ...

  5. vue 文件流下载

    /**  * 文件转为文件流  * @param {file} file //文件  */ export function getFileBlob(file) {   var dataUrl   va ...

  6. 编译stvo-pl报错error: ‘random_device’ was not declared in this scope 解决方案

    近来在研究PL-SLAM时,由于要安装stvo-pl库,所以我下载安装了这个库.在编译阶段我遇到了一个让人头大的问题. 即红框标出的地方报错:error: 'random_device' was no ...

  7. Python 项目及依赖管理工具技术选型

    Python 项目及依赖管理工具,类似于 Java 中的 Maven 与 Node 中的 npm + webpack,在开发和维护项目时起着重要的作用.使用适当的依赖管理工具可以显著提高开发效率,减少 ...

  8. OpenCV开发笔记(八十):基于特征点匹配实现全景图片拼接

    前言   一个摄像头视野不大的时候,我们希望进行两个视野合并,这样让正视的视野增大,从而可以看到更广阔的标准视野.拼接的方法分为两条路,第一条路是Sticher类,第二条思路是特征点匹配.  本篇使用 ...

  9. PLC 入口

    教程 全网最全西门子S7-1500PLC视频教程, https://www.bilibili.com/video/BV1Yi4y1U7Md?p=12&vd_source=7f5dfe09aaa ...

  10. 所见即所得,赋能RAG:PDF解析里的段落识别

    前几天,有一位用户使用OCR产品识别多栏论文后向我们询问:要怎么解决不合适的断句.分段以及错误阅读顺序的问题? 我们用一个相似案例为大家直观展示这位用户遇到的情况. 如图中的多栏期刊,如果用OCR识别 ...