关于linux:Kubernetes与GPU齐飞

15次阅读

共计 6838 个字符,预计需要花费 18 分钟才能阅读完成。



<Kubelet 从入门到放弃 > 系列将对 Kubelet 组件由基础知识到源码进行深刻梳理。在这篇文章 <Kubernetes 与 GPU 齐飞 > 中 zouyee 会先介绍 Nvidia 系列 GPU 如何加持 Kubernetes,后续介绍 Device Plugin 的相干概念以及 Kubelet 组件 Device Manager 的源码。

一、背景介绍

1.1 需要阐明

 在 Kubernetes 1.8 之前,用户应用 GPU 等设施时,举荐应用 Accelerators Feature Gate 的内置形式,连续 Kubernetes 的插件化的实现理念,各司其职,在 Kubernetes 1.10 版本后,引入设施插件框架,用户能够将零碎硬件资源引入到 Kubernetes 生态。本文将介绍 NVIDIA GPU 如何装置部署,Device Plugins 的相干介绍、工作机制和源码剖析,包含插件框架、应用和调度 GPU、和异样解决及优化等相干内容。

1.2 相干技术

 在 Kubernetes 1.10 中 Device Plugins 升为 Beta 个性,在 Kubernetes 1.8 时,为了给第三方厂商通过插件化的形式将设施资源接入到 Kubernetes,给容器提供 Extended Resources。通过 Device Plugins 形式,用户无须要改 Kubernetes 的代码,由第三方设施厂商开发插件,实现 Kubernetes Device Plugins 的相干接口即可(认真想想,Kubernetes 中的 volume 治理是否也是相似的逻辑?CSI、CNI、CRI?)。目前 Device Plugins 典型实现有:a)AMD GPU 插件

b)Intel 设施插件:GPU、FPGA 和 QuickAssist 设施

c)KubeVirt 用于硬件辅助的虚拟化设施插件

d)Nvidia 提供的 GPU 插件

e)高性能低提早 RDMA 卡插件

f)低提早 Solarflare 万兆网卡驱动

g)SR-IOV 网络设备插件

h)Xilinx FPGA 设施插件    

Device plugins 启动时,对外裸露几个 gRPC Service 提供服务,并通过 /var/lib/kubelet/device-plugins/kubelet.sock 与 Kubelet 通信。

二、部署介绍

 以后 Nvidia GPU 提供三种部署形式:docker 形式、Containerd 形式及 Operator 形式。因 docker 后续不再内置,相干阐明能够查看 < 对于 Kubernetes 废除内置 docker CRI 性能的阐明 >,下文将次要介绍 Containerd 部署,Operator 形式后续独自成文,以后 nvidia-container-toolkit 曾经反对 containerd 和 cri- o 两种部署形式,在承受 containerd 部署前,先阐明后期遇到的相干问题:1)Error while dialing dial unix:///run/containerd/containerd.sock

其中 Kubelet 问题形容:Events:
  Type     Reason         Age                   From               Message
  ----     ------         ----                  ----               -------
  Normal   Scheduled      10m                   default-scheduler  Successfully assigned gpu-operator-resources/nvidia-device-plugin-daemonset-f99md to cl-gpu-md-0-f4gm6
  Warning  InspectFailed  10m (x3 over 10m)     kubelet            Failed to inspect image "nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda10.2": rpc error: code = Unavailable desc = all SubConns are in TransientFailure, latest connection error: connection error: desc = "transport: Error while dialing dial unix /run/containerd/containerd.sock: connect: connection refused"

其中 Nvidia Device Plugin Daemonset 某一个 Pod 相干谬误,如下

# kubectl logs ‐f nvidia‐device‐plugin‐daemonset‐q9svq ‐nkube‐system
2021/02/11 01:32:29 Loading NVML
2021/02/11 01:32:29 Failed to initialize NVML: could not load NVML library.
2021/02/11 01:32:29 If this is a GPU node, did you set the docker default runtime to `nvidia`?
2021/02/11 01:32:29 You can check the prerequisites at: https://github.com/NVIDIA/k8s-device-plugin#prerequisites
2021/02/11 01:32:29 You can learn how to set the runtime at: https://github.com/NVIDIA/k8s-device-plugin#quick-start
2021/02/11 01:32:29 If this is not a GPU node, you should set up a toleration or nodeSelector to only deploy this plugin on GPU nodes

该问题因为 containerd 的配置文件 containerd.toml 未将 default_runtime_name = "runc" 批改为 default_runtime_name = "nvidia"

相干问题:https://github.com/NVIDIA/gpu-operator/issues/143

2)devices.allow: no such file or directory: unknown

    相干问题:https://github.com/NVIDIA/libnvidia-container/issues/119

    在 kubelet 配置的 cgroup driver 为 systemd 时,Nvidia 的 container prestart hook 在解决 cgroup 门路逻辑与 containerd 不统一。containerd[76114]: time="2020-12-04T08:52:13.029072066Z" level=error msg="StartContainer for"7a1453c6e7ab8af7395ccc8dac5efcffa94a0834aa7b252e1dcd5b51f92bf13e"failed" error="failed to create containerd task: OCI runtime create failed: container_linux.go:370: starting container process caused: process_linux.go:459: container init caused: Running hook #0:: error running hook: exit status 1, stdout: , stderr: nvidia-container-cli: mount error: open failed: /sys/fs/cgroup/devices/system.slice/containerd.service/kubepods-pod80540e95304d8cece2ae2afafd8b8976.slice/devices.allow: no such file or directory: unknown"

解决方案为降级 libnvidia-container 或者 container-toolkit

接下来,介绍部署相干内容。

2.1 Containerd

版本阐明

版本阐明 软件名称
CentOS 操作系统
4.19.25 内核版本
Tesla T4 GPU 型号
418.39 driver 版本
10.1 CUDA 版本
1.18.5 K8S
v0.7.3 Nvidia Device plugin
v1.4.3 Containerd
1.0.0-rc1 runc

装置

注:下文为内网离线部署,若各位在联网环境下,只需参考部署步骤及部署配置即可

a. 装置驱动

$ tar ‐zxvf gpu.tar.gz 
## 装置依赖 
$ cd gpu/runtime 
$ tar ‐zxvf dependency.tar.gz 
$ cd dependency 
## 查看是否反对 CUDA 的 Nvidia 的 GPU 
$ cd ./lspci/ 
$ yum localinstall ‐y *.rpm 
$ lspci | grep ‐i nvidia ## 装置 devel 
$ cd ../devel 
$ yum localinstall ‐y *.rpm 
## 装置 gcc $ cd ../gcc 
$ yum localinstall ‐y *.rpm 
## 卸载 nouveau 驱动 
$ lsmod | grep nouveau 
$ rmmod nouveau 
## 装置驱动,过程见上面附的图片。如果要更新驱动,从 https://developer.nvidia.com/cuda‐75‐downloads‐ archive 下载 
$ cd ../../../driver 
$ sh cuda_10.1.105_418.39_linux.run ## 测试驱动,有如下输入则失常装置


执行命令验证后果

$ nvidia‐smi


附:装置驱动图

(1) 输出 accept,回车

(2) 抉择 install,回车


b. 配置 Containerd

## 更新 runc,下载地址 https://github.com/opencontainers/runc/releases 
$ cd ../runtime 
$ cp runc /usr/bin/ 
## 更新 containerd,下载地址 https://github.com/containerd/containerd/releases 
$ tar ‐zxvf containerd‐1.4.3‐linux‐amd64.tar.gz 
$ cp bin/* /usr/bin/ 
## 装置 nvidia‐container‐runtime,yum 源 https://nvidia.github.io/nvidia‐docker/centos7/nvidia‐ docker.repo,yum 装置:yum install ‐y nvidia‐container‐runtime $ tar ‐zxvf nvidia‐container‐runtime.tar.gz 
$ cd nvidia‐container‐runtime 
$ yum localinstall ‐y *.rpm

批改改 containerd 启动参数

# 配置 containerd 的参数 
$ mkdir /etc/containerd/ 
$ vi /etc/containerd/config.toml 
# 配置 containerd.service 
$ vi /usr/lib/systemd/system/containerd.service 
$ systemctl daemon‐reload 
$ systemctl restart containerd 
# 配置 crictl 
$ tar ‐zxvf crictl‐v1.18.0‐linux‐amd64.tar.gz 
$ mv crictl /usr/bin/ 
$ vi /etc/profile alias crictl='crictl ‐‐runtime‐endpoint unix:///run/containerd/containerd.sock' 
$ source /etc/profile 
# 测试 containerd 和 nvidia‐container‐runtime 装置是否胜利 
$ cd test‐image 
$ ctr images import cuda‐vector‐add_v0.1.tar 
$ ctr images push ‐‐plain‐http registry.paas/cmss/cuda‐vector‐add:v0.1

执行测验

ctr run ‐t ‐‐gpus 0 registry.paas/cmss/cuda‐vector‐add:v0.1 cp nvidia‐smi

后果如下:清理容器

ctr c rm cp

1)config.toml

执行 containerd config default > /etc/containerd/config.toml 生成配置,并做如下批改:留神:如上所述,1)default_runtime_name 值为 nvidia,2)新增一个 runtimes 3)若有外部镜像仓库,可批改 docker.io 为外部仓库名称

2)containerd.service

[Unit] 
Description=containerd container runtime 
Documentation=https://containerd.io After=network.target

[Service] 
ExecStartPre=‐/sbin/modprobe overlay 
ExecStart=/usr/bin/containerd 
KillMode=process 
Delegate=yes 
LimitNOFILE=1048576 
# Having non‐zero Limit*s causes performance problems due to accounting overhead # in the kernel. We recommend using cgroups to do container‐local accounting. LimitNPROC=infinity 
LimitCORE=infinity 
TasksMax=infinity 
[Install] 
WantedBy=multi‐user.target

c. 部署 Device Plugin

 在部署完 Kubernetes 集群后,批改 kubelet 运行时配置:$ vi /apps/conf/kubernetes/kubelet.env ‐‐container‐runtime=remote ‐‐container‐runtime‐endpoint=unix:///run/containerd/containerd.sock

$ cd device‐plugin 
$ docker load ‐i k8s‐device‐plugin_v0.7.3.tar 
$ docker push
// https://github.com/NVIDIA/k8s-device-plugin/tree/master/deployments/static
$ kubectl apply ‐f nvidia‐device‐plugin.yml 
$ kubectl logs ‐f nvidia‐device‐plugin‐daemonset‐q9svq ‐nkube‐system 
2021/02/08 06:32:36 Loading NVML 2021/02/08 06:32:42 Starting FS watcher. 2021/02/08 06:32:42 Starting OS watcher. 2021/02/08 06:32:42 Retreiving plugins. 2021/02/08 06:32:42 Starting GRPC server for 'nvidia.com/gpu' 2021/02/08 06:32:42 Starting to serve 'nvidia.com/gpu' on /var/lib/kubelet/device‐ plugins/nvidia‐gpu.sock 2021/02/08 06:32:42 Registered device plugin for 'nvidia.com/gpu' with Kubelet

d. 功能测试

$ cd test‐image 
# 启动测试 pod 
$ kubectl apply ‐f demo.yml
// https://github.com/NVIDIA/gpu-operator/blob/master/tests/gpu-pod.yaml
$ kubectl logs ‐f cuda‐vector‐add 
[Vector addition of 50000 elements] 
Copy input data from the host memory to the CUDA device 
CUDA kernel launch with 196 blocks of 256 threads 
Copy output data from the CUDA device to the host memory 
Test PASSED 
Done



后续相干内容,请查看公众号:DCOS

https://mp.weixin.qq.com/s/kl…

正文完
 0