Kubernetes 教程:在 Containerd 容器中使用 GPU
原文链接:https://fuckcloudnative.io/posts/add-nvidia-gpu-support-to-k8s-with-containerd/
前两天闹得沸沸扬扬的事件不知道大家有没有听说,Google 竟然将 Docker 踢出了 Kubernetes 的群聊,不带它玩了。。。
具体的解释请看《听说 K8s 要甩了 Docker 了》,我这里简单描述下,Kubernetes 是通过 CRI 来对接容器运行时的,而 Docker 本身是没有实现 CRI 的,所以 Kubernetes 内置了一个 “为 Docker 提供 CRI 支持” 的 dockershim 组件。现在 Kubernetes 宣布不再维护这个组件了,大概的意思就是:Docker 虽然好用,但那是对人来说的,Kubernetes 又不是人,不需要那些花里胡哨的东西!
Kubernetes 这是话里有话,说白了就是:我特么以前为了兼容你,我集成在我自己这里,现在我就想自己单纯一点,要么你自己写 CRI 的接口 要么就再见。
众 YAML 工程师直呼 Containerd 真香!
下面进入今天的主题,Kubernetes 具有对机器的资源进行分配和使用的能力,比如可以指定容器最多使用多少内存以及使用多少 CPU 计算资源。那么问题来了,一般来说容器就是使用 CPU 和内存资源,那么对于需要使用显卡的 Pod,Kubernetes 也能够支持吗?答案当然是可以啦!目前 Kubernetes 不仅支持容器请求 GPU 资源,还支持请求几块显卡的 GPU 资源,这使得 Kubernetes 在深度学习和区块链等场景下也有了用武之地。
关于 Kubernetes 集群中 Docker 如何使用 GPU,Kubernetes 的官方文档已经说的很清楚了,网上也有铺天盖地的博客手把手教你怎么做。至于以 Containerd 作为容器运行时的集群如何使用 GPU,网上还找不到一篇像样的文档来告诉大家怎么做,今天我就来做吃螃蟹的第一人。
要想在容器里使用 GPU,本质上就是我们要在容器里能看到并且使用宿主机上的显卡,所有的步骤都是围绕这个来做的。当然,本文不会涉及如何安装 Containerd,也不会涉及如何安装 Kubernetes,如果这些都搞不定,建议不要往下看。
1. Nvidia 驱动
某些命令以 Ubuntu 作为示例。 首先宿主机上必现安装 Nvidia 驱动。这里推荐从 Nvidia 官网下载脚本安装,安装和卸载都比较方便并且适用于任何 Linux 发行版,包括 CentOS,Ubuntu 等。 NVIDIA Telsa GPU 的 Linux 驱动在安装过程中需要编译 kernel module,系统需提前安装 gcc 和编译 Linux Kernel Module 所依赖的包,例如 kernel-devel-$(uname -r) 等。
安装 gcc 和 kernel-dev(如果没有)
sudo apt install gcc kernel-dev -y。访问官网下载。
选择操作系统和安装包,并单击【SEARCH】搜寻驱动,选择要下载的驱动版本

下载对应版本安装脚本 在宿主机上执行:
$ wget https://www.nvidia.com/content/DriverDownload-March2009/confirmation.php?url=/tesla/450.80.02/NVIDIA-Linux-x86_64-450.80.02.run&lang=us&type=Tesla
安装 执行脚本安装:
$ chmod +x NVIDIA-Linux-x86_64-450.80.02.run && ./NVIDIA-Linux-x86_64-450.80.02.run
验证 使用如下命令验证是否安装成功
nvidia-smi如果输出类似下图则驱动安装成功。
2. CUDA 驱动
CUDA(Compute Unified Device Architecture)是显卡厂商 NVIDIA 推出的运算平台。CUDA 是一种由 NVIDIA 推出的通用并行计算架构,该架构使 GPU 能够解决复杂的计算问题。它包含了 CUDA 指令集架构(ISA)以及 GPU 内部的并行计算引擎。 这里安装的方式和显卡驱动安装类似。
访问官网下载
下载对应版本如下图

配置环境变量
$ echo 'export PATH=/usr/local/cuda/bin:$PATH' | sudo tee /etc/profile.d/cuda.sh
$ source /etc/profile
3. nvidia-container-runtime
nvidia-container-runtime 是在 runc 基础上多实现了 nvidia-container-runime-hook(现在叫 nvidia-container-toolkit),该 hook 是在容器启动后(Namespace已创建完成),容器自定义命令(Entrypoint)启动前执行。当检测到 NVIDIA_VISIBLE_DEVICES 环境变量时,会调用 libnvidia-container 挂载 GPU Device 和 CUDA Driver。如果没有检测到 NVIDIA_VISIBLE_DEVICES 就会执行默认的 runc。
下面分两步安装:
先设置 repository 和 GPG key:
$ curl -s -L https://nvidia.github.io/nvidia-container-runtime/gpgkey | sudo apt-key add - $ curl -s -L https://nvidia.github.io/nvidia-container-runtime/$(. /etc/os-release;echo $ID$VERSION_ID)/nvidia-container-runtime.list | sudo tee /etc/apt/sources.list.d/nvidia-container-runtime.list
安装:
$ apt install nvidia-container-runtime -y
配置 Containerd 使用 Nvidia container runtime
如果
/etc/containerd目录不存在,就先创建它:$ mkdir /etc/containerd
生成默认配置:
$ containerd config default > /etc/containerd/config.toml
Kubernetes 使用设备插件(Device Plugins) 来允许 Pod 访问类似 GPU 这类特殊的硬件功能特性,但前提是默认的 OCI runtime 必须改成
nvidia-container-runtime,需要修改的内容如下:/etc/containerd/config.toml
...
[plugins."io.containerd.grpc.v1.cri".containerd]
snapshotter = "overlayfs"
default_runtime_name = "runc"
no_pivot = false
...
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
runtime_type = "io.containerd.runtime.v1.linux" # 将此处 runtime_type 的值改成 io.containerd.runtime.v1.linux
...
[plugins."io.containerd.runtime.v1.linux"]
shim = "containerd-shim"
runtime = "nvidia-container-runtime" # 将此处 runtime 的值改成 nvidia-container-runtime
...
重启 containerd 服务:
$ systemctl restart containerd
4. 部署 NVIDIA GPU 设备插件
一条命令解决战斗:
$ kubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.7.1/nvidia-device-plugin.yml
查看日志:
$ kubectl -n kube-system logs nvidia-device-plugin-daemonset-xxx
2020/12/04 06:30:28 Loading NVML
2020/12/04 06:30:28 Starting FS watcher.
2020/12/04 06:30:28 Starting OS watcher.
2020/12/04 06:30:28 Retreiving plugins.
2020/12/04 06:30:28 Starting GRPC server for 'nvidia.com/gpu'
2020/12/04 06:30:28 Starting to serve 'nvidia.com/gpu' on /var/lib/kubelet/device-plugins/nvidia-gpu.sock
2020/12/04 06:30:28 Registered device plugin for 'nvidia.com/gpu' with Kubelet
可以看到设备插件部署成功了。在 Node 上面可以看到设备插件目录下的 socket:
$ ll /var/lib/kubelet/device-plugins/
total 12
drwxr-xr-x 2 root root 4096 Dec 4 01:30 ./
drwxr-xr-x 8 root root 4096 Dec 3 05:05 ../
-rw-r--r-- 1 root root 0 Dec 4 01:11 DEPRECATION
-rw------- 1 root root 3804 Dec 4 01:30 kubelet_internal_checkpoint
srwxr-xr-x 1 root root 0 Dec 4 01:11 kubelet.sock=
srwxr-xr-x 1 root root 0 Dec 4 01:11 kubevirt-kvm.sock=
srwxr-xr-x 1 root root 0 Dec 4 01:11 kubevirt-tun.sock=
srwxr-xr-x 1 root root 0 Dec 4 01:11 kubevirt-vhost-net.sock=
srwxr-xr-x 1 root root 0 Dec 4 01:30 nvidia-gpu.sock=
5. 测试 GPU
首先测试本地命令行工具 ctr,这个应该没啥问题:
$ ctr images pull docker.io/nvidia/cuda:9.0-base $ ctr run --rm -t --gpus 0 docker.io/nvidia/cuda:9.0-base nvidia-smi nvidia-smi
Fri Dec 4 07:01:38 2020
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 440.95.01 Driver Version: 440.95.01 CUDA Version: 10.2 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 GeForce RTX 208... Off | 00000000:A1:00.0 Off | N/A |
| 30% 33C P8 9W / 250W | 0MiB / 11019MiB | 0% Default |
+-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+
| Processes: GPU Memory |
| GPU PID Type Process name Usage |
|=============================================================================|
| No running processes found |
+-----------------------------------------------------------------------------+
最后进入终极测试:在 Pod 中测试 GPU 可用性。先创建部署清单:
gpu-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: cuda-vector-add
spec:
restartPolicy: OnFailure
containers:
- name: cuda-vector-add
image: "k8s.gcr.io/cuda-vector-add:v0.1"
resources:
limits:
nvidia.com/gpu: 1
执行
kubectl apply -f ./gpu-pod.yaml创建 Pod。使用kubectl get pod可以看到该 Pod 已经启动成功:$ kubectl get pod
NAME READY STATUS RESTARTS AGE
cuda-vector-add 0/1 Completed 0 3s
查看 Pod 日志:
$ kubectl logs 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
可以看到成功运行。这也说明 Kubernetes 完成了对 GPU 资源的调用。需要注意的是,目前 Kubernetes 只支持卡级别的调度,并且显卡资源是独占,无法在多个容器之间分享。
参考资料
Kubernetes 1.18.2 1.17.5 1.16.9 1.15.12离线安装包发布地址http://store.lameleg.com ,欢迎体验。 使用了最新的sealos v3.3.6版本。 作了主机名解析配置优化,lvscare 挂载/lib/module解决开机启动ipvs加载问题, 修复lvscare社区netlink与3.10内核不兼容问题,sealos生成百年证书等特性。更多特性 https://github.com/fanux/sealos 。欢迎扫描下方的二维码加入钉钉群 ,钉钉群已经集成sealos的机器人实时可以看到sealos的动态。

Kubernetes 教程:在 Containerd 容器中使用 GPU的更多相关文章
- 在Docker容器中搭建MXNet/Gluon开发环境
		
在这篇文章中没有直接使用MXNet官方提供的docker image,而是从一个干净的nvidia/cuda镜像开始,一步一步部署mxnet需要的相关软件环境,这样做是为了更加细致的了解mxnet的运 ...
 - 企业运维实践-丢弃手中的 docker build , 使用Kaniko直接在Kubernetes集群或Containerd环境中快速进行构建推送容器镜像
		
关注「WeiyiGeek」公众号 设为「特别关注」每天带你玩转网络安全运维.应用开发.物联网IOT学习! 希望各位看友[关注.点赞.评论.收藏.投币],助力每一个梦想. 本章目录 目录 首发地址: h ...
 - Kubernetes将弃用Docker!与 containerd容器引擎
		
时间戳:2022-06-07 20:32:19 星期二 撰写文档参考:(阿良-腾讯课堂)Kubernetes将弃用Docker 参考博客k8s入坑之路(3)containerd容器 container ...
 - .NET Core开发的iNeuOS工业互联平台,iNeuKernel物联网核心组件在Docker容器中部署。
		
目 录 1. 概述... 2 2. 演示信息... 2 3. 安装Docker容器... 2 4. 安装dotnet镜像... 3 5. ...
 - Docker Swarm和Kubernetes在大规模集群中的性能比较
		
Contents 这篇文章主要针对Docker Swarm和Kubernetes在大规模部署的条件下的3个问题展开讨论.在大规模部署下,它们的性能如何?它们是否可以被批量操作?需要采取何种措施来支持他 ...
 - Kubernetes 教程:根据 PID 获取 Pod 名称
		
原文链接:https://fuckcloudnative.io/posts/find-kubernetes-pod-info-from-process-id/ 在管理 Kubernetes 集群的过程 ...
 - 无需手动输入命令,简单3步即可在K8S集群中启用GPU!
		
随着全球各大企业开始广泛采用Kubernetes,我们看到Kubernetes正在向新的阶段发展.一方面,Kubernetes被边缘的工作负载所采用并提供超越数据中心的价值.另一方面,Kubernet ...
 - kubernetes/k8s CRI分析-容器运行时接口分析
		
关联博客:kubernetes/k8s CSI分析-容器存储接口分析 概述 kubernetes的设计初衷是支持可插拔架构,从而利于扩展kubernetes的功能.在此架构思想下,kubernetes ...
 - 容器中的容器——利用Dind实现开箱即用的K3s
		
我在学习 Rancher 和 Minikube 的时候,发现它们都可以在自己的容器环境中提供一个 K3s 或 K8s 集群.尤其是 Minikube ,用户可以在它的容器环境中执行 docker ps ...
 
随机推荐
- 利用 Github Actions 的 service container 进行集成测试
			
Github Action 中 Service Container 的使用 Intro 之前写过一个 StackExchange.Redis 的一个扩展,测试项目依赖 redis,所以之前测试一直只是 ...
 - 手把手教你使用Vuex(四)
			
3.Action Action类似于mutation,不同之处在于: Action提交的是mutation,而不是直接变更状态 Action可以包含任何异步操作 可以理解为将mutations里面处理 ...
 - kafka常见面试题
			
1.Kafka 中的 ISR(InSyncRepli).OSR(OutSyncRepli).AR(AllRepli)代表什么? 1.AR = ISR+OSR ISR: kafka 使用多副本来保证消息 ...
 - c++实现split
			
#include<iostream> #include<vector> #include<algorithm> #include<string> usi ...
 - linux 源码下载和在线查看网站
			
下载: https://www.kernel.org/ 查看: https://elixir.bootlin.com/linux/
 - 与pandas初相识
			
前一阵子有个同事说,他看不懂从kibana上拉下来的日志,但是又想分析一些数据,感觉很头痛,每次都找开发给他整理一下,但是开发也很忙,要数据的频率也略高,那时候正好我跟这位需求方的项目,负责测试工作. ...
 - java 打包压缩包下载文件
			
1. 下载压缩包zip方法 @Override public void downloadZip(HttpServletResponse servletResponse) { String nowTim ...
 - CSS属性(背景属性)
			
1.背景属性 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset=" ...
 - Linux权限位(含特殊权限位s s t) 及chown\chmod命令使用
			
1.普通权限位 ls –l查看文件的属性 [root@oldboy ~]# ls -l -rw-------. 1 root root 1073 Mar 4 22:08 anaconda-ks.cfg ...
 - 网站实现微信扫码登录 php
			
微信开放平台账号一个,必须是商户,不然你也开不了 1.在开放平台创建应用,并设置回调地址(域名即可) 2.生成二维码,前端代码,用户扫码后会给你的回调地址发送code <span id=&quo ...