共计 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…