本文所有内容基于Docker,k8s集群由rancher提供的rke工具搭建(后文中称为rancher版本k8s,也适用于使用RancherUI搭建的集群),GPU共享技术采用了阿里GPU Sharing。使用了其他容器技术的本文不一定适用,或者使用了kubeadm进行k8s搭建的可能有部分不适用,kubeadm搭建的k8s在部署GPU Sharing时网上可查的资料和官网资料都很多,而rancher版本的k8s和原生kubernetes有所差别,后面会夹带一些具体说明。
准备工作
++如果你已经有了Rancher版本的K8S集群,则直接从「k8s集群搭建」开始看++
安装docker和nvidia-docker2
安装Docker,直接执行官方安装脚本安装:
curl -fsSL https://get.docker.com | bash -s docker –mirror Aliyun
安装完成后,使用Docker version查看版本,目前安装的话一般为20.10版本,能成功查询版本说明安装成功。
安装之后,执行以下命令设置docker自启动:
systemctl start docker
systemctl enable docker
nvidia-docker2安装参见上一篇文章《Ubuntu实现K8S调度NVIDIA GPU小记》安装nvidia-docker安装部分。
在安装完之后,我们需要修改docker默认的运行时,使其支持nvidia的调度,编辑/etc/docker/daemon.json配置(不存在则新建):
{
“runtimes”: {
“nvidia”: {
“path”: “/usr/bin/nvidia-container-runtime”,
“runtimeArgs”: []
}
},
“default-runtime”: “nvidia”,
“exec-opts”: [“native.cgroupdriver=systemd”]
}
其中:runtimes参数是定义运行时,这里定义了一个名为nvidia的运行时环境,default-runtime表示指定默认的运行时为刚刚定义的nvidia。
最后一句”exec-opts”: [“native.cgroupdriver=systemd”]的作用是,因为K8S的文件驱动为cgroupfs,而docker的文件驱动为systemd,两者不同会导致镜像无法启动,因此需要将K8S文件驱动也指定为systemd。
GPU驱动
GPU驱动安装和简单调度参见上一篇文章《Ubuntu实现K8S调度NVIDIA GPU小记》英伟达驱动部分。
下载rke工具
下载rke之前,需要确定你是否需要指定版本的k8s集群或者指定版本的rancher,在github中rancher仓库中,可以在对应的rancher版本中查看到其支持的k8s版本和所需的rke工具版本,相反,你确定了需要的k8s版本也可以反推rancher版本和rke版本。
我这里的需求是使用rancher2.3.8,对应的rke版本为1.0.9,rke-1.0.9对应的k8s版本如下:
这里我k8s版本采用的是v1.17.6-rancher2-1版本。
确定了各种工具版本之后,下载对应的工具,此处链接根据需求更换,不是一成不变的:
下载rke
wget https://github.com/rancher/rke/releases/download/v1.0.9/rke_linux-amd64
配置rke
mv rke_linux-amd64 rke
chmod 755 rke
mv rke /usr/local/bin/
验证
rke –version
k8s集群搭建
rke需要根据yaml文件来进行集群的创建,我这里使用的是单节点,首先来创建rke集群文件目录:
mkdir rke-config
cd rke-config
以下是rke集群文件的内容,使用vim 进行编辑,vim cluster.yml,如果你有现有的集群,就对你的集群yaml进行编辑,在services下添加scheduler节点的所有内容即可(也适用于直接使用rancher创建的集群,只不过是通过rancher-ui进行操作):
nodes:
- address: 192.168.1.102 user: root role:
- controlplane
- etcd
- worker
services:
scheduler:
extra_args:
address: 0.0.0.0
kubeconfig: /etc/kubernetes/ssl/kubecfg-kube-scheduler.yaml
leader-elect: ‘true’
policy-config-file: /etc/kubernetes/ssl/scheduler-policy-config.json
profiling: ‘false’
v: ‘2’
kubernetes_version: “v1.17.6-rancher2-1”
cluster_name: “aliyun”
nodes配置节点是配置集群的主机,此处为单节点,因此角色需要包含control、etcd和worker三种。services下的scheduler节点是指定调度的相关配置,这里就是一个rancher版本k8s和原生k8s不一样的地方,原生k8s中,kube-scheduler作为一个可执行文件存在,而在rancher中是一个容器,scheduler节点部分的内容可以通过docker inspect kube-scheduler查看到,这里只需要复制过来并添加policy-config-file: /etc/kubernetes/ssl/scheduler-policy-config.json即可。
我们从github上获取scheduler-policy-config.json,放到/etc/kubernetes/ssl/下,如果有多个master节点,则每个master节点都需要执行:
cd /etc/kubernetes/ssl/
curl -O https://raw.githubusercontent.com/AliyunContainerService/gpushare-scheduler-extender/master/config/scheduler-policy-config.json
然后,构建集群,需要进入到上一步创建的cluster.yml的目录下:
rke up
如果提示docker版本不支持,则添加参数忽略版本即可:
rke up –ignore-docker-version
待执行完毕,此时集群就搭建好了,之后进行如下配置:
mkdir ~/.kube
kube_config_cluster.yml文件为rke up创建集群时在当前目录生成
cp kube_config_cluster.yml ~/.kube
mv ~/.kube/kube_config_cluster.yml ~/.kube/config
接下来安装kubectl来管理集群:
curl -LO “https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl”
配置kubectl
chmod 755 ./kubectl
mv ./kubectl /usr/local/bin/kubectl
查看版本
kubectl version
使用kubectl查看pod:
查看pod
kubectl get pods
自此,k8s集群搭建完毕,接下来做GPU共享配置
GPU Sharing部署
部署GPU共享调度插件gpushare-schd-extender:
cd /tmp/
curl -O https://raw.githubusercontent.com/AliyunContainerService/gpushare-scheduler-extender/master/config/gpushare-schd-extender.yaml
因为是使用单节点,因此需要能够在master上进行调度,所以需要在gpushare-schd-extender.yaml中将
nodeSelector:
node-role.kubernetes.io/master: “”
这两句删除,使k8s能够在master上进行调度
kubectl create -f gpushare-schd-extender.yaml
部署设备插件gpushare-device-plugin
如果你的集群不是新搭建的,之前如果已经安装了nvidia-device-plugin,需要将其删除,rancher版本的k8s可以使用kubectl get pods看到nvidia-device-plugin相应的pod,删除即可。然后部署设备插件gpushare-device-plugin:
cd /tmp/
wget https://raw.githubusercontent.com/AliyunContainerService/gpushare-device-plugin/master/device-plugin-rbac.yaml
kubectl create -f device-plugin-rbac.yaml
wget https://raw.githubusercontent.com/AliyunContainerService/gpushare-device-plugin/master/device-plugin-ds.yaml
默认情况下,GPU显存以GiB为单位,若需要使用MiB为单位,需要在这个文件中,将–memory-unit=GiB修改为–memory-unit=MiB
kubectl create -f device-plugin-ds.yaml
为GPU节点打标签
为了将GPU程序调度到带有GPU的服务器,需要给服务打标签gpushare=true:
查看所有节点
kubectl get nodes
选取GPU节点打标
kubectl label node gpushare=true
例如我这里主机名为master,则打标语句为:
kubectl label node master gpushare=true
更新kubectl可执行程序:
wget https://github.com/AliyunContainerService/gpushare-device-plugin/releases/download/v0.3.0/kubectl-inspect-gpushare
chmod u+x kubectl-inspect-gpushare
mv kubectl-inspect-gpushare /usr/local/bin
然后执行kubectl inspect gpushare,若能看到GPU信息,则代表安装成功:
可以看到,此时GPU显存总数为7981MiB,使用为0。
测试
接下来进行测试,我们获取阿里云的示例程序:
wget https://raw.githubusercontent.com/AliyunContainerService/gpushare-scheduler-extender/master/samples/1.yaml
wget https://raw.githubusercontent.com/AliyunContainerService/gpushare-scheduler-extender/master/samples/2.yaml
wget https://raw.githubusercontent.com/AliyunContainerService/gpushare-scheduler-extender/master/samples/3.yaml
这四个文件分别是四个需要调度GPU的示例容器的yaml,直接使用kubectl create -f x.yaml启动即可,这些文件中调度的GPU都是以G为单位的,这里我修改了调度数值,调度数值的参数名为:aliyun.com/gpu-mem,第一个为128,第二个是256,第三个是512,逐个启动,观察GPU占用率:
启动第一个:
启动第二个:
启动第三个:
至此,rancher版本k8s配置GPU共享成功。