k8s 运行分布式 tensorflow 实验
Closed this issue · 9 comments
k8s 运行分布式 tensorflow 实验
实验基于 @wangkuiyi 给出的 GitHub 地址 https://github.com/amygdala/tensorflow-workshop/tree/master/workshop_sections/distributed_tensorflow
我们目标需要在 k8s 上运行 tensorflow + ceph, 先通过这个实验流程来熟悉 tensorflow 在 k8s 上可行性和流程, 后续使用 ceph 存储来代替 NFS. 下面会记录实验流程和注意事项.
准备工作
- kubectl 能够正确连接 k8s 集群
- Clone 这个仓库(amygdala/tensorflow-workshop) 到本地
Step1: 运行 nfs_server 在 k8s 上
项目文档中需要我们先创建一个 GCE Persistent Disk, 这里我们使用 k8s 集群的 Node 空间作为 NFS Server 的磁盘
# 测试 kubectl 和 k8s 集群连接正常
kubectl get node
kubectl get pod --namespace=kube-system
# 进入下面指定目录, 我克隆仓库在 /opt
cd /opt/tensorflow-workshop-master/workshop_sections/distributed_tensorflow/k8s-configs
# 编辑 nfs-server-local.yaml, 删除 PersistentVolume 和 PersistentVolumeClaim 配置块, 因为我们没有使用 GCE 的磁盘
vim nfs-server-local.yaml
--------
kind: Service
apiVersion: v1
metadata:
name: tf-nfs
spec:
ports:
- name: nfs
port: 2049
- name: mountd
port: 20048
- name: rpcbind
port: 111
selector:
role: tf-nfs
---
apiVersion: v1
kind: ReplicationController
metadata:
name: tf-nfs
spec:
replicas: 1
selector:
role: tf-nfs
template:
metadata:
labels:
role: tf-nfs
spec:
containers:
- name: tf-nfs
image: gcr.io/google-samples/nfs-server:1.1
ports:
- name: nfs
containerPort: 2049
- name: mountd
containerPort: 20048
- name: rpcbind
containerPort: 111
securityContext:
privileged: true
volumeMounts:
- mountPath: /exports
name: mypvc
volumes:
- name: mypvc
hostPath:
path: /var/nfs-server
--------
# 创建 nfs-server
kubectl create -f nfs-server-local.yaml
# 查看 pod 创建过程日志, 如有报错, 会在里边输出
kubectl describe pod tf-nfs
Step2: 创建 nfs-pvc(PersistentVolumeClaim)
持久卷(PersistentVolumeClaim)持久化的存储(诸如gcePersistent
或iscsi
卷)而且还无须知道特定云环境的细节,在pod中使用persistentVolumeClaim
就可以挂载。
关于PersistentVolumeClaim的细节https://github.com/kubernetes/kubernetes/blob/release-1.0/docs/user-guide/persistent-volumes.md
创建 nfs 的持久卷
# 获得上面 tf-nfs 的 cluster ip 地址
kubectl get service tf-nfs
# 修改 nfs-pvc.yaml 中 server 地址为 上面的获得
vim nfs-pvc.yaml
--------
server: 10.3.0.37
# 创建 pv 和 pvc
kubectl create -f nfs-pvc.yaml
注意: 使用 NFS, 需要为集群中 Node 装上 nfs client, 如果是 coreos , 打开 rpc-statd.service 服务即可.
Step3: 执行导入数据 Job
按部就班, 确保前面的流程都没有问题
kubectl create -f k8s-configs/load_data.yaml
Step4: 创建 Tensorboard Server
kubectl create -f k8s-configs/tensorboard.yaml
# 可以通过集群中任意 Node IP 加下面 NodePort 登录到 WEBUI(如: 10.10.10.203:31175)
kubectl describe services tensorboard
Name: tensorboard
Namespace: default
Labels: <none>
Selector: tensorflow=tensorboard
Type: LoadBalancer
IP: 10.3.0.92
Port: <unset> 80/TCP
NodePort: <unset> 31175/TCP
Endpoints: 10.1.62.2:6006
Session Affinity: None
No events.
Step5: 启动 Tensorflow Job
任务会拉取 gcr.io/google-samples/tf-worker-example:latest
这个镜像(740MB), 每个 Node 都会拉取, 速度很慢会导致任务失败.
这边解决方法是上传到 163 的 docker hub 上, 得到 hub.c.163.com/vienlee/tf-worker-example:latest
, 替换 tf-cluster.yaml 中的 gcr.io/google-samples/tf-worker-example:latest
地址为hub.c.163.com/vienlee/tf-worker-example:latest
即可.
之所以没有用私有仓库, 因为当前没有搭建可用的私有仓库, 而且还需要支持 https(否则需要修改每个 Node 的 docker 配置增加私有仓库地址)
kubectl create -f tf-cluster.yaml
# 查看每个 pod 的状态
kubectl get pod
# 查看 pod 创建日志是否正常
kubectl describe pod <podname>
等待所有 Pod 创建成功, 状态为 Runing.
总结
通过实验证明 tensorflow 可以正常在 k8s 上运行, 后续流程我们可以提前创建 pv(使用 cephfs 存储) 和 pvc, 把训练数据导入到 pv 中. 然后编译我们自己的任务镜像, 编排 tf-cluster.yaml 执行任务.
kubectl create -f nfs-server 应该是kubectl create -f nfs-server-local.yaml,别的没问题
已修正问题.
- nfs-server-local.yaml 中 mountPath: /exports 和 path: /var/nfs-server 分别代表什么意思?
- https://github.com/amygdala/tensorflow-workshop/blob/master/workshop_sections/distributed_tensorflow/k8s-configs/ 中 nfs-server-local.yaml 和 nfs-server.yaml 什么区别
- 能把用的的yaml文件放到 git 里吗?
- 关于PersistentVolumeClaim的细节https://github.com/kubernetes/kubernetes/blob/release-1.0/docs/user-guide/persistent-volumes.md
,PersistentVolume 和 PersistentVolumeClaim 的使用方法, 一个 pod 通过 PersistentVolumeClaim 使用 PersistentVolume, 这个 PersistentVolume 会挂载在pod里,不需要挂载在 node 上吧?#8
- tf-cluster.yaml 里面都写了什么信息?
- gcr.io/google-samples/tf-worker-example:latest 这个能看到里面的运行脚本的内容吗,做了什么事情,或者有没有介绍?
- https://github.com/amygdala/tensorflow-workshop/blob/master/workshop_sections/distributed_tensorflow 这里面有个CNN的例子,有Dockerfile,可以build image 和 tf-cluster.yaml 配合就能跑起来,熟悉使用 tensorboard 查看任务状态和信息 #10
,需要GPU 的cluster 先跑起来 #7
,和我们自己的dockerhub #9
,方便image存储
回答相关问题
-
nfs-server-local.yaml 中 mountPath: /exports 和 path: /var/nfs-server 分别代表什么意思?
path: /var/nfs-server 代表 node 对应的路径
mountPath: /exports 代表挂载在容器中的路径 -
https://github.com/amygdala/tensorflow-workshop/blob/master/workshop_sections/distributed_tensorflow/k8s-configs/ 中 nfs-server-local.yaml 和 nfs-server.yaml 什么区别
nfs-server-local.yaml 和 nfs-server.yaml 区别就是是否使用挂载 gcePersistentDisk 的 PersistentVolumeClaim 卷
-
能把用的的yaml文件放到 git 里吗?
没有明白问题描述的意思.
-
关于PersistentVolumeClaim的细节https://github.com/kubernetes/kubernetes/blob/release-1.0/docs/user-guide/persistent-volumes.md ,PersistentVolume 和 PersistentVolumeClaim 的使用方法, 一个 pod 通过 PersistentVolumeClaim 使用 PersistentVolume, 这个 PersistentVolume 会挂载在pod里,不需要挂载在 node 上吧?
在 pod 的 yaml 的 volumes 中 persistentVolumeClaim 指定对应的持久卷名即可. 类似于集群的公共逻辑卷, 配置好配额和读写模式后就可以被 POD 挂载.
-
tf-cluster.yaml 里面都写了什么信息?
没有深入研究
-
gcr.io/google-samples/tf-worker-example:latest 这个能看到里面的运行脚本的内容吗,做了什么事情,或者有没有介绍?
没有找到对应 dockerfile, 推测应该和 https://github.com/amygdala/tensorflow-workshop/tree/master/workshop_sections/distributed_tensorflow/tf-worker 类似
k8s 使用 cephfs 创建 PersistentVolume
实验基于:
- cepfs 配置: https://github.com/kubernetes/kubernetes/tree/master/examples/volumes/cephfs
- Kernel 挂载方法: https://github.com/k8sp/ceph/blob/master/mount-cephfs-on-linux-machine.md
下面是流程描述和注意事项
准备工作
正常运行的 ceph 集群:
- monitors: 10.10.10.204:6789, 10.10.10.205:6789, 10.10.10.206:6789
- ceph.admin.key: AQBpza1XInniFRAAeHHDtf7oZkqvB8dXjP71/g==
创建 ceph 的 PersistentVolume 和 PersistentVolumeClaim
创建 ceph-pvc.yaml, 添加下面内容, 需要替换
- key: 使用 Base64 加密过的字符串(使用命令
echo -n "AQBpza1XInniFRAAeHHDtf7oZkqvB8dXjP71/g==" | base64
) - monitors: 替换 ceph 集群中的 monitors 信息
- path: 设置挂载 cephfs 中的 /exports 目录为根(ceph 中 /exports 需要提前创建)
apiVersion: v1
kind: Secret
metadata:
name: ceph-secret
data:
key: QVFCcHphMVhJbm5pRlJBQWVISER0ZjdvWmtxdkI4ZFhqUDcxL2c9PQ==
---
kind: PersistentVolume
apiVersion: v1
metadata:
name: tf-ceph
namespace: default
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteMany
cephfs:
monitors:
- 10.10.10.204:6789
- 10.10.10.205:6789
- 10.10.10.206:6789
user: admin
path: /exports
secretRef:
name: ceph-secret
readOnly: false
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: tf-ceph
namespace: default
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 100Gi
开始创建名为 tf-ceph 的 PersistentVolume 和 PersistentVolumeClaim
# 创建 ceph-pvc
kubectl create -f ceph-pvc.yaml
# 查看持久卷状态
kubectl get pv,pvc
使用持久卷
创建 load_data.yaml 文件
apiVersion: batch/v1
kind: Job
metadata:
name: load-data
spec:
template:
metadata:
name: load-data
spec:
restartPolicy: Never
containers:
- name: loader
image: gcr.io/google-samples/tf-workshop:v2
command:
- "/bin/sh"
- "-c"
args:
- "curl https://storage.googleapis.com/oscon-tf-workshop-materials/processed_reddit_data/news_aww/prepared_data.tar.gz | tar xzv -C /var/tensorflow/"
volumeMounts:
- name: tf-ceph
mountPath: /var/tensorflow
volumes:
- name: tf-ceph
persistentVolumeClaim:
claimName: tf-ceph
执行 load_data.yaml 任务
kubectl create -f load_data.yaml
# 查看任务状态, 是否有报错, 直到正常运行
kubectl describe pod load-data
通过上面的流程跑通了使用 cephfs 创建 PersistentVolume 和 PersistentVolumeClaim, 并能正确导入数据, 完成了 ceph 和 k8s 结合. tensorflow 或其他的 pod 只需要加入下面配置块, 就能正常挂载 ceph 了.
- mountPath: 挂载到容器中的路径
volumeMounts:
- name: tf-ceph
mountPath: /var/tensorflow
volumes:
- name: tf-ceph
persistentVolumeClaim:
claimName: tf-ceph
@ali8zake it was deleted by the author, which only can be visited from history commit now:
https://github.com/amygdala/tensorflow-workshop/tree/086d5a9f6ae2b4e76c5099b4a18acf3cb125fb9e/workshop_sections