前言

前两天闹得沸沸扬扬的事件不知道大家有没有听说,Google 竟然将 Docker 踢出了 Kubernetes 的群聊,不带它玩了。。。

我这里简单描述下,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

  • 访问官网[1]下载。

  • 选择操作系统和安装包,并单击【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 内部的并行计算引擎。这里安装的方式和显卡驱动安装类似。

  • 访问官网[2]下载

  • 下载对应版本如下图

  • 配置环境变量

  $ 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)[3] 来允许 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: OnFailurecontainers:- name: cuda-vector-addimage: "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 只支持卡级别的调度,并且显卡资源是独占,无法在多个容器之间分享。

参考资料

  • 容器中使用 GPU 的基础环境搭建[4]

参考资料

[1]官网: https://www.nvidia.com/Download/Find.aspx

[2]官网: https://developer.nvidia.com/cuda-toolkit-archive

[3]设备插件(Device Plugins): https://v1-18.docs.kubernetes.io/zh/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/

[4]容器中使用 GPU 的基础环境搭建: https://lxkaka.wang/docker-nvidia/

听过K8S玩家都关注了它

后台回复◉k8s◉获取史上最方便快捷的 Kubernetes 高可用部署工具

只需一条命令,连 ssh 都不需要!

【往期推荐】

殊途同归!招聘软件与社交软件最终都要走向约P宿命?

2020-12-05

Spring-Retry重试实现原理

2020-12-05

今年最后一月数据库排名公布!前三难以撼动!

2020-12-04

8 种常见的SQL错误用法

2020-12-04

一手好牌打的稀烂,如今面临倒计时,网友哭求众筹活下去...

2020-12-03

Elasticsearch Top 51 重中之重面试题及答案

2020-12-03

深度内容

推荐加入

将 Docker 踢出群聊后,Kubernetes 还能否欢快地蹦跶吗?相关推荐

  1. egg extend ts_胜者组新“四大天王”,DYG、AG级别更高,TS被踢出群聊

    点击蓝色关注 更多精彩内容等你~ 2020KPL秋季赛常规赛赛程即将过半.而截至目前呢,除了极个别战队之外,绝大部分战队都已经至少打了7场比赛.如今的KPL积分排行榜已经很能够说明问题了.有一说一,这 ...

  2. 踢掉 Docker 后,Kubernetes 还能欢快地跑 GPU?

    Kubernetes 集群中 Docker 如何使用 GPU 早就被说烂了,那么以 Containerd 作为容器运行时的集群是如何使用 GPU的,有人知道吗? 头图 | CSDN 下载自东方 IC ...

  3. 程序员遭遇:一觉睡来7个未接电话,到公司时已被踢出群

    本文来自洞见网http://www.localonline.com.cn/,文章链接:http://www.localonline.com.cn/view/society/901.html,转载请注明 ...

  4. TCP多人聊天程序Java实现(群聊,私聊,在线用户,踢出用户)

    本程序在程序 https://blog.csdn.net/joffy/article/details/18079331 的基础是上添加了私聊,踢出用户两个功能. 由客户端和服务器端构成程序,程序借助J ...

  5. 小游戏正在毁灭微信群聊(文中有福利)

    小游戏已经成为毁灭微信群聊体验的第一杀手. 在几年前群聊杀手还主要是养生文和鸡汤文,但后来随着商家开发各种玩法以及抄袭各种玩法,主流的杀手变成了抢票.拼团.网课推荐.邀请注册等.小游戏虽然起步晚,但是 ...

  6. 使用java做一个能赚钱的微信群聊机器人(2020年基于PC端协议最新可用版)

    前言 微信群机器人,主要用来管理群聊,提供类似天气查询.点歌.机器人聊天等用途.由于微信将web端的协议封杀后,很多基于http协议的群聊机器人都失效了,所以这里使用基于PC端协议的插件来实现. 声明 ...

  7. android微信群聊功能,微信安卓内测更新,这个群聊功能等了8年

    近日,安卓版微信悄然迎来了 8.0.3 内测版更新,本次内测又带来了哪些新功能呢,一起来看看吧. 01 群聊支持键入 @所有人 微信作为国民级应用,而微信群又是微信中的一个重要组成部分." ...

  8. 用java做一个能赚钱的微信群聊机器人(PC协议)

    前言 微信群机器人,主要用来管理群聊,提供类似天气查询.点歌.机器人聊天等用途.由于微信将web端的协议封杀后,很多基于http协议的群聊机器人都失效了,所以这里使用基于PC端协议的插件来实现. 声明 ...

  9. 小游戏正在毁灭微信群聊[联络易]

    小游戏已经成为毁灭微信群聊体验的第一杀手. 在几年前群聊杀手还主要是养生文和鸡汤文,但后来随着商家开发各种玩法以及抄袭各种玩法,主流的杀手变成了抢票.拼团.网课推荐.邀请注册等.小游戏虽然起步晚,但是 ...

最新文章

  1. 设置cookie存活时间_Django之cookie、session、token
  2. java操作storm,Storm集群常用批量操作命令
  3. 局部变量和成员变量的初始值问题
  4. java插件获取首选项_Eclipse RCP 中创建自定义首选项,并能读取首选项中的值
  5. 编程类-----matlab基础语法复习(1)
  6. phpdesigner 8 注册码
  7. Zabbix5系列-监控惠普服务器iLO管理口 (六)
  8. 液压系统管路流速推荐表_液压系统中油管尺寸的选择
  9. 天宇优配|“宁组合”全线大跌,“蔚小理”也重挫!医药
  10. Road to Coder _Game
  11. 使用ARCGIS多重缓冲区分析工具建立颜色渐变行政边界
  12. 写给四十岁男人的忠告
  13. Java学习路线·进阶
  14. 纯干货!一款APP从设计稿到切图过程全方位揭秘
  15. Android camera2 框架学习记录
  16. Revit中为房间添加填充图例和“构件快速上色”
  17. mysql5.7出现:ERROR 2003 (HY000): Can‘t connect to MySQL server on ‘localhost‘ (10061)问题解决
  18. 论文阅读_对比学习_SimCSE
  19. 安装Ubuntu13.10后的首要事情
  20. nodeJS生成随机token

热门文章

  1. 窗体和控件使用中的注意事项有哪些?
  2. 第一篇读书笔记,关于UML和模式应用(1)--书籍简介
  3. linux 密码文件 /etc/shadow md5,SHA256,SHA512 破解
  4. linux yum localinstall 解决本地rpm包的依赖问题
  5. python3 打印异常堆栈信息
  6. sqlmap os shell解析
  7. SQL Server之存储过程基础知识
  8. VC++运算符与优先级
  9. LeakDiag 微软一款检测memory leak的工具
  10. Android之 AndroidManifest.xml 文件解析