RKE搭建K8S集群并配置GPU共享完整流程

本文最后更新于:3 个月前

声明

本文所有内容基于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,直接执行官方安装脚本安装:

1
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

安装完成后,使用Docker version查看版本,目前安装的话一般为20.10版本,能成功查询版本说明安装成功。

安装之后,执行以下命令设置docker自启动:

1
2
systemctl start docker
systemctl enable docker

nvidia-docker2安装参见上一篇文章《Ubuntu实现K8S调度NVIDIA GPU小记》安装nvidia-docker安装部分。
在安装完之后,我们需要修改docker默认的运行时,使其支持nvidia的调度,编辑/etc/docker/daemon.json配置(不存在则新建):

1
2
3
4
5
6
7
8
9
10
{
"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版本如下:
image.png
这里我k8s版本采用的是v1.17.6-rancher2-1版本。

确定了各种工具版本之后,下载对应的工具,此处链接根据需求更换,不是一成不变的:

1
2
3
4
5
6
7
8
9
10
# 下载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集群文件目录:

1
2
mkdir rke-config
cd rke-config

以下是rke集群文件的内容,使用vim 进行编辑,vim cluster.yml,如果你有现有的集群,就对你的集群yaml进行编辑,在services下添加scheduler节点的所有内容即可(也适用于直接使用rancher创建的集群,只不过是通过rancher-ui进行操作):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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节点都需要执行:

1
2
cd /etc/kubernetes/ssl/
curl -O https://raw.githubusercontent.com/AliyunContainerService/gpushare-scheduler-extender/master/config/scheduler-policy-config.json

然后,构建集群,需要进入到上一步创建的cluster.yml的目录下:

1
rke up

如果提示docker版本不支持,则添加参数忽略版本即可:

1
rke up --ignore-docker-version

待执行完毕,此时集群就搭建好了,之后进行如下配置:

1
2
3
4
mkdir ~/.kube
# kube_config_cluster.yml文件为rke up创建集群时在当前目录生成
cp kube_config_cluster.yml ~/.kube
mv ~/.kube/kube_config_cluster.yml ~/.kube/config

接下来安装kubectl来管理集群:

1
2
3
4
5
6
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:

1
2
# 查看pod
kubectl get pods

自此,k8s集群搭建完毕,接下来做GPU共享配置

GPU Sharing部署

  1. 部署GPU共享调度插件gpushare-schd-extender:

    1
    2
    3
    4
    5
    6
    7
    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
  2. 部署设备插件gpushare-device-plugin

如果你的集群不是新搭建的,之前如果已经安装了nvidia-device-plugin,需要将其删除,rancher版本的k8s可以使用kubectl get pods看到nvidia-device-plugin相应的pod,删除即可。然后部署设备插件gpushare-device-plugin:

1
2
3
4
5
6
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
  1. 为GPU节点打标签

为了将GPU程序调度到带有GPU的服务器,需要给服务打标签gpushare=true:

1
2
3
4
5
6
# 查看所有节点
kubectl get nodes
# 选取GPU节点打标
kubectl label node <target_node> gpushare=true
# 例如我这里主机名为master,则打标语句为:
# kubectl label node master gpushare=true
  1. 更新kubectl可执行程序:
1
2
3
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信息,则代表安装成功:

image.png

可以看到,此时GPU显存总数为7981MiB,使用为0。

测试

接下来进行测试,我们获取阿里云的示例程序:

1
2
3
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占用率:
启动第一个:
image.png
启动第二个:
image.png
启动第三个:
image.png

至此,rancher版本k8s配置GPU共享成功。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!