Kubelet 从入门到放弃系列:GPU 加持
<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/klpgz3KGOFAn2fW6UdgjbA
评论