|
|
|
@ -1,34 +1,34 @@
|
|
|
|
|
# Kubernetes on AWS
|
|
|
|
|
|
|
|
|
|
我们将向你展示怎么样在AWS的kubernetes集群上运行分布式paddlepaddle训练,让我们从核心概念开始
|
|
|
|
|
我们将向你展示怎么样在AWS的Kubernetes集群上运行分布式PaddlePaddle训练,让我们从核心概念开始
|
|
|
|
|
|
|
|
|
|
## 分布式paddlepaddle训练的核心概念
|
|
|
|
|
## PaddlePaddle分布式训练的核心概念
|
|
|
|
|
|
|
|
|
|
### 分布式训练任务
|
|
|
|
|
|
|
|
|
|
一个分布式训练任务可以看做是一个kubernetes任务
|
|
|
|
|
每一个kubernetes任务都有相应的配置文件,此配置文件指定了像任务的pods和环境变量信息
|
|
|
|
|
一个分布式训练任务可以看做是一个Kubernetes任务
|
|
|
|
|
每一个Kubernetes任务都有相应的配置文件,此配置文件指定了像任务的pod个数之类的环境变量信息
|
|
|
|
|
|
|
|
|
|
在分布式训练任务中,我们可以如下操作:
|
|
|
|
|
|
|
|
|
|
1. 在分布式文件系统中,准备分区数据和配置文件(在此次教学中,我们会用到亚马逊分布式存储服务(EFS))
|
|
|
|
|
1. 在分布式文件系统中,准备分块数据和配置文件(在此次教学中,我们会用到亚马逊分布式存储服务(EFS))
|
|
|
|
|
2. 创建和提交一个kubernetes任务配置到集群中开始训练
|
|
|
|
|
|
|
|
|
|
### 参数服务和训练
|
|
|
|
|
### Parameter Server和Trainer
|
|
|
|
|
|
|
|
|
|
在paddlepaddle集群中有两个角色:参数服务(pserver)者和训练者, 每一个参数服务过程都会以一个全局模型碎片存在。每一个训练者都可以进行本地模型拷贝,并可以利用本地数据更新模型。在这个训练过程中,训练者发送模型更新到参数服务中,参数服务职责就是聚合这些更新,以便于训练者可以把全局模型同步到本地。
|
|
|
|
|
在paddlepaddle集群中有两个角色:参数服务器(pserver)者和trainer, 每一个参数服务器过程都会保存一部分模型的参数。每一个trainer都保存一份完整的模型参数,并可以利用本地数据更新模型。在这个训练过程中,trainer发送模型更新到参数服务器中,参数服务器职责就是聚合这些更新,以便于trainer可以把全局模型同步到本地。
|
|
|
|
|
|
|
|
|
|
为了能够和pserver联通,训练者需要每一个pserver的IP地址。在kubernetes中利用服务发现机制(比如:DNS、hostname)要比静态的IP地址要好一些,因为任何一个pod都会被杀掉然后新的pod被重启到另一个不同IP地址的node上。现在我们可以先用静态的IP地址方式,这种方式是可以更改的。
|
|
|
|
|
为了能够和pserver通信,trainer需要每一个pserver的IP地址。在Kubernetes中利用服务发现机制(比如:DNS、hostname)要比静态的IP地址要好一些,因为任何一个pod都会被杀掉然后新的pod被重启到另一个不同IP地址的node上。现在我们可以先用静态的IP地址方式,这种方式是可以更改的。
|
|
|
|
|
|
|
|
|
|
参数服务者和训练者一块被打包成一个docker镜像,这个镜像会运行在被kebernetes集群调度的pod中。
|
|
|
|
|
参数服务器和trainer一块被打包成一个docker镜像,这个镜像会运行在被Kubernetes集群调度的pod中。
|
|
|
|
|
|
|
|
|
|
### 训练者ID
|
|
|
|
|
|
|
|
|
|
每一个训练过程都需要一个训练ID,以0作为基础值,作为命令行参数传递。训练过程因此用这个ID去读取数据分区。
|
|
|
|
|
每一个训练过程都需要一个训练ID,以0作为基础值,作为命令行参数传递。训练过程因此用这个ID去读取数据分片。
|
|
|
|
|
|
|
|
|
|
### 训练
|
|
|
|
|
|
|
|
|
|
利用shell脚本进入容器,可以看到许多kubernetes预先定义好的环境变量。这里可以定义任务identity,在任务中identity可以用来远程访问包含所有pod的kubernetes apiserver服务。
|
|
|
|
|
PaddlePaddle容器的入口是一个shell脚本,这个脚本可以读取Kubernetes内预置的环境变量。这里可以定义任务identity,在任务中identity可以用来远程访问包含所有pod的Kubernetes apiserver服务。
|
|
|
|
|
|
|
|
|
|
每一个pod通过ip来排序。每一个pod的序列作为“pod id”。因为我们会在每一个pod中运行训练和参数服务,可以用“pod id”作为训练ID。入口脚本详细工作流程如下:
|
|
|
|
|
|
|
|
|
@ -38,7 +38,7 @@
|
|
|
|
|
4. 以trainer_id来训练将自动把结果写入到EFS卷中。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## AWS的kubernetes中的paddlepaddle
|
|
|
|
|
## AWS的Kubernetes中的PaddlePaddle
|
|
|
|
|
|
|
|
|
|
### 选择AWS服务区域
|
|
|
|
|
这个教程需要多个AWS服务工作在一个区域中。在AWS创建任何东西之前,请检查链接https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/ 选择一个可以提供如下服务的区域:EC2, EFS, VPS, CloudFormation, KMS, VPC, S3。在教程中我们使用“Oregon(us-west-2)”作为例子。
|
|
|
|
@ -70,7 +70,7 @@
|
|
|
|
|
在AWS中[kube-aws](https://github.com/coreos/kube-aws)是一个自动部署集群的CLI工具
|
|
|
|
|
|
|
|
|
|
##### kube-aws完整性验证
|
|
|
|
|
提示:如果你用的是非官方版本(e.g RC release)的kube-aws,可以跳过这一步骤。引入 coreos的应用程序签名公钥:
|
|
|
|
|
提示:如果你用的是非官方版本(e.g RC release)的kube-aws,可以跳过这一步骤。引入coreos的应用程序签名公钥:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
gpg2 --keyserver pgp.mit.edu --recv-key FC8A365E
|
|
|
|
@ -110,9 +110,9 @@ mv ${PLATFORM}/kube-aws /usr/local/bin
|
|
|
|
|
|
|
|
|
|
#### kubectl
|
|
|
|
|
|
|
|
|
|
[kubectl](https://kubernetes.io/docs/user-guide/kubectl-overview/) 是一个操作kubernetes集群的命令行接口
|
|
|
|
|
[kubectl](https://Kubernetes.io/docs/user-guide/kubectl-overview/) 是一个操作Kubernetes集群的命令行接口
|
|
|
|
|
|
|
|
|
|
利用`curl`工具从kubernetes发布页面中下载`kubectl`
|
|
|
|
|
利用`curl`工具从Kubernetes发布页面中下载`kubectl`
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
# OS X
|
|
|
|
@ -257,7 +257,7 @@ DNS名称含有CNAME指向到集群DNS名称或者记录指向集群的IP地址
|
|
|
|
|
|
|
|
|
|
#### S3 bucket
|
|
|
|
|
|
|
|
|
|
在启动kubernetes集群前需要创建一个S3 bucket
|
|
|
|
|
在启动Kubernetes集群前需要创建一个S3 bucket
|
|
|
|
|
|
|
|
|
|
在AWS上创建s3 bucket会有许多的bugs,所以使用[s3 console](https://console.aws.amazon.com/s3/home?region=us-west-2)。
|
|
|
|
|
|
|
|
|
@ -313,9 +313,9 @@ kube-aws render credentials --generate-ca
|
|
|
|
|
```
|
|
|
|
|
kube-aws render stack
|
|
|
|
|
```
|
|
|
|
|
asserts(模板和凭证)用于创建、更新和当前目录被创建的kubernetes集群相关联
|
|
|
|
|
asserts(模板和凭证)用于创建、更新和当前目录被创建的Kubernetes集群相关联
|
|
|
|
|
|
|
|
|
|
### 启动kubernetes集群
|
|
|
|
|
### 启动Kubernetes集群
|
|
|
|
|
|
|
|
|
|
#### 创建一个在CloudFormation模板上定义好的实例
|
|
|
|
|
|
|
|
|
@ -415,7 +415,7 @@ ip-10-0-0-55.us-west-2.compute.internal Ready 6m
|
|
|
|
|
|
|
|
|
|
### 开始在AWS上进行paddlepaddle的训练
|
|
|
|
|
|
|
|
|
|
#### 配置kubernetes卷指向EFS
|
|
|
|
|
#### 配置Kubernetes卷指向EFS
|
|
|
|
|
|
|
|
|
|
首先需要创建一个持久卷[PersistentVolume](https://kubernetes.io/docs/user-guide/persistent-volumes/) 到EFS上
|
|
|
|
|
|
|
|
|
@ -464,7 +464,7 @@ kubectl --kubeconfig=kubeconfig create -f pvc.yaml
|
|
|
|
|
|
|
|
|
|
#### 准备训练数据
|
|
|
|
|
|
|
|
|
|
启动kubernetes job在我们创建的持久层上进行下载、保存并均匀拆分训练数据为3份.
|
|
|
|
|
启动Kubernetes job在我们创建的持久层上进行下载、保存并均匀拆分训练数据为3份.
|
|
|
|
|
|
|
|
|
|
用`paddle-data-job.yaml`保存
|
|
|
|
|
```
|
|
|
|
@ -613,7 +613,7 @@ chmod 400 key-name.pem
|
|
|
|
|
ssh -i key-name.pem core@INSTANCE_IP
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`INSTANCE_IP`: EC2上kubernetes工作节点的公共IP地址,进入[EC2 console](https://us-west-2.console.aws.amazon.com/ec2/v2/home?region=us-west-2#Instances:sort=instanceId) 中检查任何`paddle-cluster-kube-aws-worker`实例的 `public IP`
|
|
|
|
|
`INSTANCE_IP`: EC2上Kubernetes工作节点的公共IP地址,进入[EC2 console](https://us-west-2.console.aws.amazon.com/ec2/v2/home?region=us-west-2#Instances:sort=instanceId) 中检查任何`paddle-cluster-kube-aws-worker`实例的 `public IP`
|
|
|
|
|
|
|
|
|
|
2. 挂载EFS
|
|
|
|
|
```
|
|
|
|
@ -647,7 +647,7 @@ sudo mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,ret
|
|
|
|
|
```
|
|
|
|
|
`server.log` 是`pserver`的log日志,`train.log`是`trainer`的log日志,模型快照和描述存放在`pass-0000*`.
|
|
|
|
|
|
|
|
|
|
### kubernetes集群卸载或删除
|
|
|
|
|
### Kubernetes集群卸载或删除
|
|
|
|
|
|
|
|
|
|
#### 删除EFS
|
|
|
|
|
|
|
|
|
|