【ArchSummit架构师峰会】探讨数据与人工智能相互驱动的关系>>> 了解详情
写点什么

如何使用 Kubernetes GPU 集群自动化深度学习训练

  • 2017-07-12
  • 本文字数:5940 字

    阅读完需:约 19 分钟

本文最初发布于 GitHub ,经原作者授权由 InfoQ 中文站翻译并分享。

该指南能帮助同行研究者和爱好者们轻松地使用 Kubernetex GPU 集群来自动化和加速他们的深度学习训练。因此,我将解释如何轻松地在多个 Ubuntu 16.04 裸机服务器上搭建一个 GPU 集群,并提供一些有用的脚本和.yaml 文件来完成这些工作。

另外,如果你需要把 Kubernetes GPU 集群用于其他地方,该指南可能对你也有帮助。

为什么写这个指南?

我一直在创业公司 understand.ai 实习,在那里我留意到了一个麻烦:首先得在本地设计一个机器学习算法,然后将其放到云上用不同的参数和数据集来训练模型。这第二步,将算法放到云上进行全面的训练,所耗费的时间要比想象的更长,通常让人很沮丧而且涉及到很多陷阱。

因此,我决定解决这个问题,让第二步变得容易、简单和快捷。

我写了这篇很有用的指南,描述了每个人如何设置他们自己的 Kubernetes GPU 集群来加速他们的工作。

给深度学习研究者的新处理过程:

用 Kubernetes GPU 集群进行自动化的深度学习训练,它能极大地改进在云上训练模型的过程。

(点击放大图像)

声明

下面的章节可能有些武断。Kubernetes 是一个进化的、快节奏的环境,这就意味着这个指南很可能会在某个时间过时,这取决于作者的空余时间和个人贡献。因此,非常感谢对此的贡献。

Kubernetes 快速参考

如果你需要重温下 Kubernetes 知识,下面这些文章很有用。

集群结构粗览

核心想法是用一个很小的只有 CPU 的 master 节点来控制一组 GPU worker 节点。

(点击放大图像)

初始化节点

在我们使用集群之前,要先对其初始化,这一点很重要。因此,要手动地初始化每个节点,随后将它加入集群中。

我的设置

该配置非常适合这里所描述的用例。对其他用例、操作系统等,需要进一步地调整配置。

Master

  • Ubuntu 16.04 带 root 权限
    • 我用了一个 Google Compute Engine VM 实例
  • SSH 权限
  • 停用 ufw
  • 可用端口(udp 和 tcp)
    • 6443,443,8080
    • 30000-32767(仅在需要时激活)
    • 这些将被用于获取集群外部的服务

Worker

  • Ubuntu 16.04 带 root 权限
    • 我用了一个 Google Compute Engine VM 实例
  • SSH 权限
  • 停用 ufw
  • 可用端口(udp 和 tcp)
    • 6443,443

关于安全:当然,如果你想在产品中使用,就应该启用某些防火墙;这里出于简单考虑我停用了 ufw。设置 Kubernetes 以用于实际的产品中,理所当然应该启用某些防火墙如 ufw、iptables 或者你的云提供商的防火墙。在云上设置集群会更加复杂。通常云提供商的防火墙与主机级别的防火墙是分开的。你可能需要停用 ufw、并开启云提供商防火墙的规则来让这篇文档里的步骤生效。

设置指南

这些指南涵盖了我在 Ubuntu 16.04 的经验,对其他操作系统可能适用,也可能不适用。

我创建了两个脚本对 master 和 worker 节点完全初始化。脚本如下所示。如果你想用快速通道,可以直接使用这些脚本。否则,我建议你阅读一步一步的指南。

快速通道设置脚本

将下面相应的脚本拷贝到你的 master worker 上。

MASTER 节点

运行初始化脚本,记下token。

Token 的格式类似于–token f38242.e7f3XXXXXXXXe231e。

复制代码
chmod +x init-master.sh
sudo ./init-master.sh <IP-of-master>

WORKER 节点

运行初始化脚本,使用正确的 token 和 master IP。

端口通常是 6443。

复制代码
chmod +x init-worker.sh
sudo ./init-worker.sh <Token-of-Master> <IP-of-master>:<Port>

详细的一步一步指南

MASTER 节点

1. 将 Kubernetes Repository 加入 packagemanager

复制代码
sudo bash -c 'apt-get update && apt-get install -y apt-transport-https
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF
apt-get update'

2. 安装 docker-engine、kubeadm、kubectl 和 kubernetes-cni

复制代码
sudo apt-get install -y docker-engine
sudo apt-get install -y kubelet kubeadm kubectl kubernetes-cni
sudo groupadd docker
sudo usermod -aG docker $USER
echo 'You might need to reboot / relogin to make docker work correctly'

3. 由于我们想创建一个使用 GPU 的集群,我们要在 master 节点上启用 GPU 加速功能。记住,在 Kubernetes 之后的版本中,这一步可能被淘汰了或者完全更改了。

3.I 在集群初始化之前,添加 GPU 支持到 Kubeadm 配置。

这一步必须对集群中的每一个节点进行,即使某些节点没有 GPU。

复制代码
sudo vim /etc/systemd/system/kubelet.service.d/<<Number>>-kubeadm.conf

因此,在 ExecStart 后追加上标签–feature-gates=“Accelerators=true”,最终格式如下:

复制代码
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS [...] --feature-gates="Accelerators=true"

3.II 重启 kubelet

复制代码
sudo systemctl daemon-reload
sudo systemctl restart kubelet

4. 现在初始化 master 节点。

你需要 master 节点的 IP。而且,这一步会向你提供认证信息,用于添加 worker 节点,因为要记住你的 token。

Token 的格式类似于–token f38242.e7f3XXXXXXXXe231e 130.211.XXX.XXX:6443。

复制代码
sudo kubeadm init --apiserver-advertise-address=<ip-address>

5. 由于 Kubernetes 1.6 从 ABAC 卷管理变成了 RBAC 式,因此我们需要向用户公布认证信息。每一次登录机器,都需要执行这一步。

复制代码
sudo cp /etc/kubernetes/admin.conf $HOME/
sudo chown $(id -u):$(id -g) $HOME/admin.conf
export KUBECONFIG=$HOME/admin.conf

6. 安装网络插件让节点能相互通信。Kubernetes 1.6 对网络插件有一些要求,如:

  • 基于 CNI 的网络
  • RBAC 支持

这篇 GoogleSheet 文档包含很多合适的网络插件。链接: GoogleSheet Network Add-on comparison

出于个人的偏好,我会使用 wave-works。

复制代码
kubectl apply -f https://git.io/weave-kube-1.6

7. 现在都设置好了。检查所有的 pod 都在线上,确认一切运转顺利。

复制代码
kubectl get pods --all-namespaces

N. 如果你想撤掉 master 节点,你需要重置它。

复制代码
sudo kubeadm reset

WORKER NODE

前面几步对你而言应该很熟悉了,能让进程加快一些。

1. 将 Kubernetes Repository 加入 packagemanager

复制代码
sudo bash -c 'apt-get update && apt-get install -y apt-transport-https
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF
apt-get update'

2. 安装 docker-engine、kubeadm、kubectl 和 kubernetes-cni

复制代码
sudo apt-get install -y docker-engine
sudo apt-get install -y kubelet kubeadm kubectl kubernetes-cni
sudo groupadd docker
sudo usermod -aG docker $USER
echo 'You might need to reboot / relogin to make docker work correctly'

3. 由于我们想创建一个使用 GPU 的集群,我们要在 master 节点上启用 GPU 加速功能。记住,在 Kubernetes 之后的版本中,这一步可能被淘汰了或者完全更改了。

3.I 在集群初始化之前,添加 GPU 支持到 Kubeadm 配置。

这一步必须对集群中的每一个节点进行,即使某些节点没有 GPU。

复制代码
sudo vim /etc/systemd/system/kubelet.service.d/<<Number>>-kubeadm.conf

因此,在 ExecStart 后追加上标签–feature-gates=“Accelerators=true”,最终格式如下:

复制代码
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS [...] --feature-gates="Accelerators=true"

3.II 重启 kubelet

复制代码
sudo systemctl daemon-reload
sudo systemctl restart kubelet

4. 现在我们将 worker 加入到集群中。

你需要记住 master 节点的 token,所以查看下节点。

复制代码
sudo kubeadm join --token f38242.e7f3XXXXXXe231e 130.211.XXX.XXX:6443

5. 完成。在 master 上检查节点,看看是否一切运转顺利。

复制代码
kubectl get nodes

N. 如果你想撤掉 worker 节点,你需要将该节点从集群中移除,然后重置该节点。从集群中移除 worker 节点是很有帮助的。

在 master 节点上:

复制代码
kubectl delete node <worker node name>

在 worker 节点上

复制代码
sudo kubeadm reset

客户端

为了控制你的集群,如从客户端控制 master,你需要对客户端的正确用户进行认证。该指南中并没有为客户端创建一个单独的用户,我们只是从 master 节点复制用户。相信我,这样做会更简单。

[会在将来加入如何添加用户的指导]

1. 在客户端安装 kubectl。我只在 mac 上测试过,但应该也适用 linux。我不知道是否适用于 windows,但又有谁关心 windows 呢。

Mac

复制代码
brew install kubectl

Ubuntu 你要么遵循官方指南 https://kubernetes.io/docs/tasks/tools/install-kubectl/ ,要么从上面的 worker 指南中提取需要的步骤(可能只在 Ubuntu 上可行)。

2. 将 master 的 admin 认证拷贝到客户端。

复制代码
scp uai@130.211.XXX.64:~/admin.conf ~/.kube/

3. 将 admin.conf 配置和认证信息添加到 Kubernetes 配置中。你需要对每个代理都执行该步骤。

复制代码
export KUBECONFIG=~/.kube/admin.conf

你可以在本地的客户端上使用 kubectl 了。

4. 你可以测试列出所有的 pod

复制代码
kubectl get pods --all-namespaces

安装 Kubernetes dashboard

Kubernetes dashboard 非常的漂亮,它向那些跟我一样喜欢摆弄脚本的人提供了很多功能。要使用 dashboard 的话,你需要让客户端运行,RBAC 会确保这一点。

你可以直接在 master 节点上或者从客户端运行下面的步骤。

1. 检查已经安装了 dashboard: kubectl get pods --all-namespaces | grep dashboard

2. 如果没有安装,则安装它

复制代码
kubectl create -f https://git.io/kube-dashboard

如果不成功,检查.yaml 中定义的容器 git.io/kube-dashboard 是否存在。(这个软件故障曾让我花费了很多时间)

为了能访问你的 dashboard,你需要在客户端进行认证。

3. 添加 dashboard 代理到客户端。

在客户端运行:

复制代码
kubectl proxy

4. 用浏览器访问 dashboard,访问 127.0.0.1:8001/ui。

如何构建你的 GPU 容器

这里帮助你运行一个需要 GPU 权限的 Docker 容器。

在该指南中,我选择创建一个 Docker 容器的例子,它用 TensorFlow GPU 二进制文件,并能在 Jupyter 笔记本中运行 TensorFlow 程序。

请记住,该指南适用于 Kubernetes 1.6,因此可能不适用于今后的变化。

.yml 的关键部分

为了能够让你的带 CUDA 的 Nvidia GPU 运行,你需要将 Nvidia 驱动和 CUDA 库文件传给容器。因此,我们将使用 hostPath,让 Kubernetes pod 能访问它们。实际的路径因机器而异,因为它们是由 Nvidia 驱动和 CUDA 安装程序来设置的。

复制代码
volumes:
- hostPath:
path: /usr/lib/nvidia-375/bin
name: bin
- hostPath:
path: /usr/lib/nvidia-375
name: lib

将包含有驱动和 CUDA 的卷加载到容器中的正确目录下。根据你的容器的具体要求,这些设置可能有所不同。

复制代码
volumeMounts:
- mountPath: /usr/local/nvidia/bin
name: bin
- mountPath: /usr/local/nvidia/lib
name: lib

因为你要告诉 Kubernetes 你需要 n 个 GPU,所以你可以在这里定义这些需求。

复制代码
resources:
limits:
alpha.kubernetes.io/nvidia-gpu: 1

这就是你需要创建 Kuberntes 1.6 容器的所有东西。

这是我的所有经验:

Kubernetes + Docker + Machine Learning + GPUs = 顶呱呱

GPU 部署例子

文件 example-gpu-deployment.yaml 描述了两部分,部署和服务,因为我想让 juptyer 笔记本能被外部访问。

运行 kubectl 来让其对外可见。

复制代码
kubectl create -f deployment.yaml

文件 deployment.yaml 内容如下:

复制代码
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: tf-jupyter
spec:
replicas: 1
template:
metadata:
labels:
app: tf-jupyter
spec:
volumes:
- hostPath:
path: /usr/lib/nvidia-375/bin
name: bin
- hostPath:
path: /usr/lib/nvidia-375
name: lib
containers:
- name: tensorflow
image: tensorflow/tensorflow:0.11.0rc0-gpu
ports:
- containerPort: 8888
resources:
limits:
alpha.kubernetes.io/nvidia-gpu: 1
volumeMounts:
- mountPath: /usr/local/nvidia/bin
name: bin
- mountPath: /usr/local/nvidia/lib
name: lib
---
apiVersion: v1
kind: Service
metadata:
name: tf-jupyter-service
labels:
app: tf-jupyter
spec:
selector:
app: tf-jupyter
ports:
- port: 8888
protocol: TCP
nodePort: 30061
type: LoadBalancer
---

为了验证这些设置是正确的,你可以访问 JupyterNotebook 实例,链接是 http://:30061。

现在我们要验证你的 JupyterNotebook 实例可以访问 GPU。因此,在一个新的笔记本中运行下面的程序。它将列出 tensorflow 可用的所有服务。

复制代码
from tensorflow.python.client import device_lib
def get_available_devices():
local_device_protos = device_lib.list_local_devices()
return [x.name for x in local_device_protos]
print(get_available_devices())

输出结果应该类似于 [u’/cpu:0’, u’/gpu:0’]。

一些有用的命令

Get 命令,输出基本信息

复制代码
kubectl get services # 列出该命名空间的所有服务
kubectl get pods --all-namespaces # 列出所有命名空间的所有 pod
kubectl get pods -o wide # 列出该命名空间的所有 pod,给出细节
kubectl get deployments # 列出所有部署
kubectl get deployment my-dep # 列出给定部署

Describe 命令,输出冗长的信息

复制代码
kubectl describe nodes <node-name>
kubectl describe pods <pod-name>

删除资源

复制代码
kubectl delete -f ./pod.yaml # 删除 pod,其类型和名字被定义在 pod.yaml 中
kubectl delete pod,service baz foo # 删除名字为“baz”和“foo”的 pod 和服务
kubectl delete pods,services -l name=<myLabel> # 删除标签名为 myLabel 的 pod 和服务
kubectl -n <namespace> delete po,svc --all # 删除命名空间 my-ns 的所有 pod 和服务

进入某个 pod 的 bash 控制台:

复制代码
kubectl exec -it <pod-name> -- /bin/bash

致谢

有很多指南、github 仓库、问题和帮助过我的人们。

我想感谢每一个人的帮助。

特别感谢创业公司 understand.ai 的支持。

作者

Frederic Tausch - 原创 - Langhalsdino

许可

该项目采用 MIT 许可,具体细节请查看 LICENSE.md 文件。

查看英文原文: How to automate deep learning training with Kubernetes GPU-cluster

感谢陈思对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

公众号推荐:

跳进 AI 的奇妙世界,一起探索未来工作的新风貌!想要深入了解 AI 如何成为产业创新的新引擎?好奇哪些城市正成为 AI 人才的新磁场?《中国生成式 AI 开发者洞察 2024》由 InfoQ 研究中心精心打造,为你深度解锁生成式 AI 领域的最新开发者动态。无论你是资深研发者,还是对生成式 AI 充满好奇的新手,这份报告都是你不可错过的知识宝典。欢迎大家扫码关注「AI前线」公众号,回复「开发者洞察」领取。

2017-07-12 17:206816
用户头像

发布了 21 篇内容, 共 88907 次阅读, 收获喜欢 3 次。

关注

评论 1 条评论

发布
用户头像
但是这里似乎没有涉及到gpu的调度相关,只是自己指定了gpu,那么使用k8s的目的是什么?我们平时训练深度学习任务也可以直接在代码中指定gpu啊
2019-12-06 16:14
回复
没有更多了
发现更多内容

猎杀时刻!阿里高工总结698页Spring学习笔记,疯狂狩猎大厂offer

Java~~~

Java spring 架构 面试 微服务

爆款阿里P5到P7晋升之路,九大源码文档助我超神果然努力幸运并存

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

一夜标星过百万,轻松霸榜GitHub的手绘图解HTTP笔记,竟来源阿里

Java~~~

Java 架构 面试 网络 HTTP

缓存知识总结

十二万伏特皮卡丘

MySQL 系列教程之(三) MySQL 基本概念和操作

若尘

MySQL 8月日更

网络攻防学习笔记 Day105

穿过生命散发芬芳

态势感知 网络攻防 8月日更

FastApi-14-文件上传-2

Python研究所

FastApi 8月日更

Alibaba22届校招启动!连夜整理一份七大专题Java架构速成笔记

Java~~~

Java 架构 面试 阿里 校招

一切努力似乎都徒劳?|靠谱点评

无量靠谱

秒杀系统设计-超卖问题

泽睿

秒杀 秒杀系统

这份阿里P8级别内部疯传的“Linux私房菜”让你一次吃个饱

Java 编程 程序员 IT 计算机

细说JavaScript正则表达式(RegExp)

devpoint

正则表达式 regex JavaScrip 8月日更

马士兵老师亲自总结3000+道Java面试题,刷完吊打架构师面试官

Java 程序员 架构 面试 计算机

腾讯跟阿里两位王者之间的对比

Linux服务器开发

腾讯 阿里 C/C++ Linux服务器开发 Linux后台开发

网络安全证书合集系列

网络安全学海

网络安全 证书 信息安全 渗透测试 安全漏洞

DAPP钱包开发模式详细介绍

Geek_23f0c3

dapp 钱包系统开发 DAPP智能合约交易系统开发

【LeetCode】股票的最大利润Java题解

Albert

算法 LeetCode 8月日更

“硬钢字节”阿里大牛分享内部数据结构与算法(诛仙版)源码笔记

Java~~~

Java 架构 面试 算法 数据结构与算法

前方高能!Alibaba最新出版的JDK源码剖析手册(究极奥义版)开源

Java~~~

Java 架构 jdk 面试 架构师

netty系列之:使用UDP协议

程序那些事

Java Netty nio udp 程序那些事

解除限制!Alibaba不在低调,P8大神纯手撸300页Java高并发手册

Java~~~

Java 架构 面试 高并发 架构师

Alibaba12年技术老兵整理的“MySQL 学习笔记”带你轻松拿捏MySQL

Java~~~

Java MySQL 数据库 架构 面试

我为什么不建议大家等公司倒闭之后,再找工作!

非著名程序员

面试 认知提升 招聘管理 8月日更

被boss直聘转发过多而“封杀”的2021年全套java高级面试题有多牛

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

校友名片小程序设计方案

CC同学

小程序云开发 校友小程序

MySQL 系列教程之(二)Windows 安装 MySQL5.7.17

若尘

MySQL 8月日更

大专的我狂刷29天“阿里内部面试笔记”最终直接斩获十七个Offer

Java 程序员 架构 面试 IT

终于拿到了阿里2021年度九大Java技术文档——面试题+文档+白皮书

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

上线仅仅三小时,豆瓣评分均9.0的“四本程序员必刷书籍”火了

Java 编程 面试 IT 计算机

震惊!300多页美团百亿级系统架构设计实录首公开

Java 编程 架构 面试 架构师

Java的四种引用类型

W🌥

Java JVM 8月日更

如何使用Kubernetes GPU集群自动化深度学习训练_语言 & 开发_Frederic Tausch_InfoQ精选文章