写点什么

Kubelet 从入门到放弃系列:GPU 加持

用户头像
DCOS
关注
发布于: 2021 年 03 月 04 日
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://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c286e4b3c73349e2b6248ce66b8aac26~tplv-k3u1fbpfcp-watermark.image)


https://mp.weixin.qq.com/s/klpgz3KGOFAn2fW6UdgjbA


用户头像

DCOS

关注

还未添加个人签名 2020.09.22 加入

公众号:DCOS

评论

发布
暂无评论
Kubelet从入门到放弃系列:GPU加持