SkyForm ECP基于Kubernetes构建AIaaS平台

■ 文/ 天云软件 张伟

1. 背景介绍

作者在之前的文章《在SkyForm ECP上运行深度学习框架》中介绍过深度学习框架运行在kubernetes上的优势,以及这种实践方式的基本架构。

社区中也出现了很多tensorflow on kubernetes的方案,比如最早使用jinja模板的方案(点击了解),以及后来的kubeflow(点击了解)和Tensorflow/k8s(点击了解),都是为了能够更好的把tensorflow运行在kubernetes上,简化手工搭建tensorflow集群时的繁琐工作。

其中Tensorflow/k8s用kubernetes的CRD定义新的资源类型TFJob,可以在TFJob中定义PS、Worker和TensorBoard的信息,方便创建一个分布式的tensorflow集群。

SkyForm ECP的AIaaS的方案和社区方案的一个简单对比如下:

Tensorflow/k8s kubeflow AIaaS方案
深度学习框架支持 Tensorflow Tensorflow Tensorflow,Mxnet,Caffe
Hybrid MPI Jobs 不支持 不支持 支持
深度学习工作流 JupyterHub,Tensorflow training,Tensorflow serving 只支持Tensorflow training,没有工作流 Jupyter,

Tensorflow training,Tensorflow serving

Gangscheduling 不支持 不支持 支持,自研
任务控制器 专门针对Tensorflow的控制器 专门针对Tensorflow的控制器 自研通用的HybridJob控制器
其它 完整的多租户、日志、存储、监控方案

 

SkyForm ECP平台不但支持Tensorflow、Mxnet、Caffe等多种深度学习框架,而且集成了OpenFace等AI应用,以及经过严格测试开箱即用的算法框架。

2. SkyForm ECP的AIaaS核心技术详解

目前Kubernetes社区关于深度学习的方案基本都仅支持单一框架,同时调度器的功能也很简单。在实际的应用中还存在以下不足:

  1. 扩展性差:很难扩展到不同的深度学习框架。如果需要扩展其它的深度学习框架,需要重写CRD,工作量巨大。
  2. 资源浪费和资源死锁:使用Kubernetes原生的调度器,只考虑资源充足情况下的分配方案,对有激烈竞争时的资源分配方案考虑较少。而GPU资源作为一种稀缺资源,在实际的生成环境中必然会发生资源争抢的情况。

为了解决上述问题,SkyForm ECP平台中提出了一种HybridJob混合任务的概念,使用CRD定义HybridJob任务类型,开发了HybridJob Controller控制器对HybridJob任务进行处理。HybridJob中支持对每种任务设置最大副本数和最小副本数,以便在集群资源紧张时动态调整。同时SkyForm ECP设计了新的调度器——Gang Scheduler,它在分配资源的过程中,不再将Pod单独调度,而是把相互关联的Pod作为一个整体来打包调度,避免只有部分Pod调度成功但是训练任务不能正常执行,已启动的Pod浪费集群资源的情况。具体的工作流程如下图所示:

流程图

1)用户使用kubectl或在Portal提交HybridJob资源对象,HybridJob Controller根据提交的HybridJob信息生成对应的pod。

2)Gang scheduler参考集群当前资源情况,决定在minReplicas-maxReplicas范围内运行哪些pod。

3)对已成功调度的pod进行bind操作,并将其提交到kubernetes集群中运行。

HybridJob Controller

HybridJob Controller是SkyForm研发的一种混合任务控制器,可以在Hybridjob中同时创建PS和Worker等多种不同类型的任务。HybridJob的模型如下:

模型

HybridJob中可以有多个ReplicaSpec,每个ReplicaSpec代表一种任务类型。每个任务类型可以自定义最小副本数minReplicas和最大副本数maxReplicas,任务实际运行的Pod数在最小副本数和最大副本数之间。其中,最小副本数是任务运行必须满足的副本数,如果任务调度后获得资源的Pod数目小于最小副本数,表示调度失败,等待下个周期重新调度;最大副本数是副本数的上限。具体运行的Pod数目是根据集群的实际可用资源动态调整的。HybridJob和每个ReplicaSpec都有状态信息记录,可以分别查看它们的当前状态。

Gang Scheduler

Gang Scheduler是一种Pod组调度器,它保证了只有组中的minReplicas条件满足时才会真正创建Pod。这样的做法不仅在集群资源紧张的时候更灵活地调度资源,而且能有效防止资源死锁。

Gang Scheduler的特性主要包括两点:1.以组为单位调度相互关联的多个Pod,任务实际运行的Pod数可以在minReplicas和maxReplicas之间动态变化;2.兼容原生调度器的所有规则策略,比如NodeSelector,NodeAffinity,PodAffinity等。

Gang Scheduler具体的调度流程如下:

1)以minReplicas数目为目标分别调度每个ReplicaSpec。

2)调度成功后,以maxReplicas为上限分别调度每个ReplicaSpec,调度过程中考虑每个ReplicaSpec的优先级,优先级越高,其所属Pod的调度概率就越大。

3)根据调度结果修改调度组的状态,如果ReplicaSpec最终获得资源的Pod数目小于minReplicas,则认为该任务调度失败,调度失败后释放其中已调度成功的pod资源,重新添加调度组到queue;调度成功bind所有已调度成功的pod。

4)HybridJob Controller监听Pod的状态,根据Pod实际运行情况修改HybridJob的状态,删除未绑定的多余Pod。

3. 运行结果展示

本节以Tensorflow为例展示SkyForm ECP平台,在平台上应用Tensorflow的训练过程如下图所示:

运行结果1)上传训练代码和数据:目前支持的后端存储类型包括nfs和glusterfs,也可以创建jupyter应用在线开发。

1.上传(1)

2)启动训练任务:在应用市场选择tensorflow,填写存储信息、任务启动命名、PS的最小和最大副本数、Worker的最小和最大副本数等参数,点击部署运行训练任务,在以下动图中可以看到实际运行的副本数在最小和最大副本数之间,具体数目由gang scheduler根据集群的资源使用情况动态调整;训练过程中可以查看每个Pod的实时日志;训练完成后可以在存储卷中查看生成的model信息;TensorBord提供的外部端口可访问TensorBoard服务。

2.运行任务(1)

3)启动Serving:在应用市场选择serving,填写存储信息,model的位置,以及model的名称信息,填写serving的副本数及资源需求;选择是否启用HPA对serving服务做自动伸缩,或者在serving服务部署后手动更改serving服务的副本数。

3.运行serving(1)

4)测试Serving:在demo应用中输入serving的服务地址及端口,进行手写数字识别。

4.测试serving(1) 5)重新运行任务:重新运行任务支持修改任务启动命令,传入新的训练参数;每次重新执行任务都会根据集群当前的资源情况进行调度,决定实际运行的Pod副本数。

5.重新执行任务(1)

4. 后续的计划

SkyForm ECP平台上实践了多种深度学习框架,针对实际应用中存在的部分问题进行了改进,并取得了一些效果。但还有许多特殊需求和技术问题需要进一步地研究开发,主要包括:

1)HybridJob中的pod数可以根据实际资源使用情况在min和max之间动态伸缩,现阶段只考虑了调度时间点的资源使用情况,任务运行后不会改变。当集群资源紧张时,需要考虑回收min和实际运行pod数目之间的pod,让排队的任务可以尽快运行起来。

2)整合fair scheduler(基于Kubernetes的公平调度器)和gang scheduler,平衡多租户共享集群执行训练任务时的公平问题。

3)调度时应考虑集群资源的动态变化,结合RNN等多种深度学习算法,使用各种监控信息做更合理的资源调度。

4)增强对Spark、Storm等数据处理框架的支持,打通包括数据、计算和算法整个AIaaS生命周期的各个环节。