人工智能和机器学习 云计算管理平台

基于vRealize Automation实现机器学习云平台


引言

 

在之前的文章中,我们介绍了IT基础架构对于机器学习的重要性,以及如何基于成熟的软件定义数据中心架构进行扩展,从而构建机器学习云平台。(如有需要,请参看:VMware云平台加速机器学习。)

本文中,我们做一些比较深入的技术探讨。重点在基于vRealize Automation实现GPU/vGPU的自动化调度。

这不是一份设计文档,但是会覆盖关键的技术点。读者应该具备一定的vRealize Automation的基本知识,并且具备一定的二次开发能力,以充分理解并且可以在项目中实现。如果您还没有这样的能力,强烈建议参加使用VMware Hands on Lab在线实验进行学习。

 


概述

 

vRealize Automation基本逻辑架构

首先,我们还是看一下vRealize Automation的基本逻辑架构。

图1:vRealize Automation的基本逻辑架构

图1:vRealize Automation的基本逻辑架构

 

vRA包含两个基本的组件:Appliance和IaaS Component. 其中Appliance是一个经过定制和裁剪之后的Linux,通过ova文件直接导入vSphere就可以了。IaaS Component是一个基于Windows的VM,需要管理员自行安装其中的组件。

我们在架构图中可以看到,Appliance组件主要包含User Interface,VIDM,PostgreSQL和vRO。其中,User Interface(UI)顾名思义,就是负责用户界面。VIDM是一个统一身份管理组件,全称叫VMware Identity Manager,vIDM会对接AD进行身份管理。IaaS组件包含一个很重要的模块叫“Distributed Execution Manager(DEM)”,这个组件负责和vSphere进行集成,并完成虚拟机的部署工作。

一个最简单的执行流程就是: UI驱动DEM,DEM驱动vSphere,实现整个部署过程。

 

基于vRealize Automation的扩展

以上流程是系统内置的,但是vRA提供了一些可以定制化的“hook”。具体就是通过vRO(vRealize Orchestrator)来实现。vRO是一个工作流平台,我们需要在vRO上面创建一系列工作流(Workflow),以支持在某个VM上面增加、删除或者修改GPU设置。并且通过系统配置,让系统知道在适当的时候调用这些工作流。这样的系统配置包括两种方式:(1)通过在蓝图中设置XaaS;(2)通过Event Broker Service(EBS)触发。关于vRA定制的全面而详细的文档,可以参看VMware官方文档:Life Cycle Extensibility

 

具体到机器学习云平台,我们需要做的扩展包括:

  1. 在Blueprint中增加一个XaaS的组件,在虚拟机部署完成之后,执行GPU增加的vRO workflow。
  2. 增加一个Action操作,并且关联到相应的Blueprint,可以执行GPU变更的vRO workflow。
  3. 在EBS中增加一个Subscription,当虚拟机被删除的时候,执行GPU删除的vRO workflow。(可能会有疑问,当VM都被删除了,GPU的配置为什么还需要额外做一次删除呢?稍后会提到)

 

由于vRO只是一个工作流平台,所谓工作流,是没有状态(Stateless)的,而且主要作为集成用途,业务逻辑不宜过于复杂。所以,我们增加了一个组件,用于GPU的调度,这个GPU Scheduler组件作为一个应用独立运行。vRO通过Restful Web Service调用GPU Scheduler组件,进行GPU的申请、变更和回收,这也就是上面第3点提到的,即使VM被删除之后,依然需要调用GPU Scheduler,以回收GPU的注册信息。架构如下图所示:

图2:包含GPU的逻辑架构

图2:vRO调用GPU Scheduler

 

下面,我们就这几个具体的技术要点做阐述。包括:

  1. GPU Scheduler
  2. 虚拟机部署过程中的GPU加载
  3. 虚拟机部署完成之后,进行的GPU变更
  4. 虚拟机被删除之后,进行的GPU回收

 


GPU Scheduler

 

Rest API定义

GPU Scheduler的接口至少应该包含以下两个:Update GPU,Delete GPU

 

Update GPU:HTTP PUT /vms/<vm-id>/gpus

Request Body:

{

“model”: “P40 / V100 / TitanV / grid_p40-8q”

“number”: 2

}

其中,model可以是P40、V100、TitanV这样的直通模式的配置,也可以是grid_p40-8q这样的vGPU配置。当model为vGPU时,在当前的vSphere版本(6.5)中,只支持1个vGPU,所以number这个数量就不重要了,可以省略。

 

Response body:

{

“host”: “host01.corp.local”,

“gpuId”: [“0000:04:00.0”, “0000:05:00.0”]

}

其中当request为vGPU申请时,gpuId无需设置。

 

Delete GPU:HTTP DELETE /vms/<vm-id>/gpus

 

无论是Update还是Delete操作,都应当是幂等的,以提供较好的容错性。

 

GPU Scheduler应用架构

GPU Scheduler模块的应用架构应该很简单,基本上需要一个提供Rest服务的Web前端,以及一个数据库。具体的语言和数据库的选择,大家可以各显神通,用自己熟悉的程序设计语言、REST框架和数据库来实现。但是,其中有几点和GPU相关的说明。

  • 如果一台物理服务器包含多块CPU和GPU,比如下图中,有两块CPU和8块GPU,他们之间的关系是这样的。当某一台VM申请两块GPU卡,我们尽量分配在同一侧,比如GPU1+GPU2,这样GPU1和GPU2之间的通信不需要跨越CPU,性能会比较好。

图3:GPU连接示意图

 

  • 由于存在申请大数量GPU的情况,比如一台VM需要4块GPU,甚至8块GPU卡。在这种情况,可能存在虽然整个资源池有足够的GPU,但是分布在不同的服务器上,导致没有一台服务器有足够的卡分给这台VM。直通方式的GPU不支持vMotion,所以,很难在不停机的情况下,在线进行碎片整理。所以,在制定分配策略的时候,需要充分考虑。
  • 并发必须充分考虑

 


虚拟机部署过程中的GPU加载

 

我们将会介绍三个重点:(1)vRA的蓝图;(2)vRO workflow;(3)参数的传递

 

蓝图

在vRealize Automation平台中,所有的部署都是通过蓝图(blueprint)来实现的。我们来看一下下面这个blueprint。

图4:包含GPU的蓝图

 

这个blueprint包含两个重要部分,一部分是vSphere和其中的网络配置,另一部分是一个Add GPU的操作。vSphere部分是最常见的配置,在此我们不做赘述。我们重点看一下Add GPU的vRO workflow。

 

vRO workflow

下图是vRealize Orchestrator中的workflow截图。

图5:更新GPU的vRO Workflow

 

我们具体看一下,每一步的工作。

  1. Validate and Transform Parameters:vRA的蓝图传递过来的参数需要做一些校验和转换。
  2. Power off VM in need:所有的GPU的配置操作都需要VM在停机状态下执行,所以确保VM是停机的。
  3. Allocate GPU:这一步操作,实际上就是通过Rest API去调用GPU Scheduler,去申请GPU。
  4. Remove all GPUs from VM:删除VM当前所有的GPU配置,这步操作主要用在变更GPU的时候,但是即使是一台没有GPU配置的VM,也不会发生错误。
  5. Migrate VM:将VM迁移到GPU Scheduler分配的ESXi host上面。
  6. Attach GPUs to VM:进行VM配置的变更。
  7. Start VM:启动VM,并等待vmtools正常运行。

 

其中,我们重点看一下第6步的代码:

  1. var vmSpec = new VcVirtualMachineConfigSpec();
  2. var myDeviceChanges = [];
  3. for (var i = 0; i < gpuIdsArray.length; i++) {
  4.         var gpuId = gpuIdsArray[i];
  5.         var change = new VcVirtualDeviceConfigSpec();
  6.         change.operation = VcVirtualDeviceConfigSpecOperation.add;
  7.         change.device = new VcVirtualPCIPassthrough();
  8.         change.device.backing = new VcVirtualPCIPassthroughDeviceBackingInfo();
  9.         change.device.backing.deviceId = System.getModule(“xxx.yyy”).getGpuDeviceId(vm.runtime.host, gpuId).toString(16);
  10.         change.device.backing.systemId = vm.environmentBrowser.queryConfigTarget(null).pciPassthrough[0].systemId;
  11.         change.device.backing.deviceName = “PCI device ” + i;
  12.         change.device.backing.vendorId = NVIDIA_VENDOR_ID;
  13.         change.device.backing.id = gpuId;
  14.         myDeviceChanges.push(change);
  15. }
  16. vmSpec.deviceChange = myDeviceChanges;
  17. vmSpec.memoryReservationLockedToMax = true;
  18. var task = vm.reconfigVM_Task(vmSpec);

 

需要特别说明的几点:

  • 不管是GPU直通还是vGPU模式,VM的内存都需要全部预留,否则VM可能启动会失败,参看第17行。
  • 第9行,我们调用了一个vRO的action去获得一个参数deviceId。这个action的内容其实也很简单,拷贝如下,供大家参考:

for each (device in host.hardware.pciDevice){
if (device.id == gpuId){
return device.deviceId;
}
}

 

如果是vGPU,相关的示例代码如下:

var vmSpec = new VcVirtualMachineConfigSpec();
var myDeviceChanges = [];
var change = new VcVirtualDeviceConfigSpec();
change.operation = VcVirtualDeviceConfigSpecOperation.add;
change.device = new VcVirtualPCIPassthrough();
change.device.backing = new VcVirtualPCIPassthroughVmiopBackingInfo();
change.device.backing.vgpu = vGpuProfile;
myDeviceChanges.push(change);
vmSpec.deviceChange = myDeviceChanges;
vmSpec.memoryReservationLockedToMax = true;
var task = vm.reconfigVM_Task(vmSpec);

 

当然,这样的workflow并没有考虑到异常处理,在实际生产中,应充分考虑。比如,vRO到GPU Scheduler的通信异常,GPU Scheduler的异常返回。在当前的workflow中,出现任何异常都导致整个申请失败,新创建的VM最终会被删除,这样的行为是否符合用户预期,需要具体情况具体分析。

 

参数传递

参数传递包括几个阶段,(1)用户从Web界面输入参数 (2)参数保存到vSphere VM的Custom Property中 (3)参数传递到XaaS所代表的vRO工作流。

 

这里面,重点需要理解Custom Property。Custom Property,顾名思义,就是自定义的一些属性。对于一个VM来说,CPU、memory、磁盘、网络… 这些都是系统自带的属性,但是GPU配置并没有。所以,我们就自定义一个这样的属性。如下图所示,我们定义了两个属性com.vmware.demo.GpuModel和com.vmware.demo.GpuNumber。

 

图6:用于记录GPU信息的Custom Property

 

这个参数,我们需要在用户界面上面显示出来,让用户进行输入。最简单的方法就是用系统默认的表单展示,如下图所示:

图7:系统自带的用户界面表单

 

当然,这种做法从审美的角度可能有些用户不喜欢。另外一种做法就是通过自定义表单(Custom Form)来实现。比如下面这张图。

图8:自定义表单

 

Custom Property,以及VM的相关信息,最终需要传递到vRO的workflow中。具体我们可以参看一下下面这三张截图,分别传递的是VM的名称、GPU Model和GPU number。

 图9:蓝图到XaaS的参数传递

 


虚拟机部署完成之后,进行的GPU变更

 

GPU的变更通过vRA提供的Action操作完成。每一个Action对应一个vRO workflow,其实,GPU的变更Workflow和GPU的增加workflow非常类似,只是在输入参数方面有一些差别。

 

我们先看一下VM部署过程中增加GPU的vRO workflow的参数。

图10:增加GPU vRO workflow输入参数

 

我们比较一下VM部署之后变更GPU的vRO workflow的参数。

图11:变更GPU vRO workflow输入参数

 


虚拟机被删除之后,进行的GPU回收

 

当虚拟机的生命周期结束,被删除之后,原则上说,虚拟机本身的GPU配置是不需要做额外的删除,但是GPU Scheduler中的配置需要变更,否则GPU Scheduler会认为这些分配出去的GPU依然在被使用。这个回收的工作流相对简单,只需要调用GPU Scheduler的HTTP DELETE操作即可。但是,何时触发这个操作,需要用到vRealize Automation提供的Event Broker Service。我们简单看一下,这一块的具体配置,如下图所示:

图12:事件订阅的条件

 

这三条关系分别如下:

  1. Data > Lifecycle state > Lifecycle state name = VMPSMasterWorkflow32.Disposing
  2. Data > Lifecycle state > State phase = PRE
  3. Data > Machine > Machine Type = Virtual Machine

 

其三条条件之间是AND的关系,当同时满足,vRO工作流被触发。这个vRO工作流的参数是payload,如下图所示。这个payload中包含所有的事件信息。

图13:事件触发workflow的输入参数

 


总结

 

至此,基于vRealize Automation的机器学习云平台的实现方法大致介绍完毕。Again,这不是一个完整的设计方案,只是包含了设计思路和关键技术点。如果您对vRealize Automation比较了解,并具备一定的编程能力,应该能够很快完成实现。祝大家好运!

 

作者:

韩亮  VMware资深解决方案架构师

姚晨锴 VMware资深技术顾问

龚华  VMware资深解决方案架构师