摘要:OpenStack社区在Ussuri版本完成了nova-cyborg interaction功能的开发, 该功能加强了nova和cyborg的联系, 解耦了nova的PCI加速设备管理功能, 通过cyborg和placement可以让加速器资源的管理更加灵活。
PR
resource provider, placement中的概念, 资源提供者。
Device Profile
Device profile是Cyborg中的概念, 它用于描述单个或多个加速设备,可以将之看作加速设备的flavor. 广义上, 它包括了两点:
一个device profile的结构如下:
``` json
{
'name': 'gpu-nvidia-t4',
'description': 'Nvidia tesla t4',
'groups': [
{'resources:PGPU': '1',
'CUSTOM_GPU_PRODUCT_ID_1EB8': 'required'
},
{'resources:PGPU': '2',
'CUSTOM_GPU_PRODUCT_ID_1E04': 'required'
}
]
'uuid': 'd6cd5b94-f95c-4148-85c5-2ce22a38a796'
}
```
目前仅允许管理员创建/更新/删除device profiles。
ARQ
ARQ即accelerator request, 它是一个对象, 用于描述实例请求分配加速设备的状态,ARQ的创建和管理由cyborg完成, 并且数据存储在cyborg数据库中。
一个ARQ只能表示单个加速设备分配请求. `device_profile`可以有N个group, 每个group请求M个加速设备, 此时将会创建N*M个ARQ。
Cyborg初始化一个ARQ后, 该ARQ并不会和特定的计算节点主机名或RP id关联, 此时我们可以认为该ARQ处于未绑定状态(unbound). 之后, nova调用cyborg将ARQ绑定到一个计算节点主机名和一个加速设备的RP id和一个实例 id上. 如果实例孵化失败, nova不会删除这个ARQ, 而是取消绑定. nova会在删除实例时解绑和删除ARQ。
在绑定ARQ前, 每个ARQ都需要与nova选择的allocation candidate匹配。当前nova会建立RequestGroup到RPs的映射, nova中的cyborg客户端模块据此将ARQ匹配到RequestGroup上。匹配是使用RequestGroup对象中的requester_id字段进行的, 规则如下:
一个ARQ的结构如下:
``` json
{'arqs': [
{'uuid': 'c406129e-821c-4583-b094-d948fe6f4aa1',
'state': 'Bound',
'device_profile_name': 'gpu-nvidia-t4',
'device_profile_group_id': 0,
'hostname': 'vgpu02',
'device_rp_uuid': '2a0c2b8f-2ec1-3364-a773-0ba4166e9a34',
'instance_uuid': '81334887-7044-44cd-805f-0f7e206e04b8',
'attach_handle_type': 'PCI',
'attach_handle_info': {
'bus': '5e',
'device': '00',
'domain': '0000',
'function': '0'
},
'created_at': '2020-04-27T11:42:11+00:00',
'updated_at': '2020-04-27T11:42:11+00:00'}
]}
```
``` graph
+------+ +----------+ +----------------+ +--------------+ +--------+
| User | | Nova api | | Nova conductor | | Nova Compute | | Cyborg |
+--+---+ +----+-----+ +-------+--------+ +-------+------+ +---+----+
| | | | |
| Create Instance | | | |
+---------------->+ | | |
| | | | |
| | Get Device Profile | | |
| +<------------------------------------------------------------->+
| | | | |
| | Scheduler and | | |
| +-------------------->+ | |
| | build instance | | |
| | | Create ARQs | |
| | +---------------------------------------->+
| | | | |
| | | Bind ARQs | |
| | +---------------------------------------->+
| | | | |
| | | Spawn instance | |
| | +--------------------->+ |
| | | | |
| | | | Notify bind end |
| | | +<-----------------+
| | | | |
| | | | Get ARQs info |
| | | +<---------------->+
| | | | |
| | | | |
| | | +-----+ |
| | | | |Spawn |
| | | | |Instace |
| | | +<----+ |
| | | | |
```
1. nova-api收到创建虚机的请求
`nova.compute.api.API._provision_instances`会尝试解析flavor extra specs,若`flavor.extra_specs.get('accel:device_profile')`属性不为`None`, 该属性应当为device profile的名称, 调用`nova.accelerator.cyborg.get_device_profile_request_groups`获取该deviceprofile中的groups值:
cyborg API返回的数据结构如下:
``` json
{
"device_profiles": [
{
"name": "gpu-nvidia-t4",
"groups": [
{
"trait:CUSTOM_GPU_PRODUCT_ID_1EB8": "required",
"resources:PGPU": "1"
}
]
}
]
}
```
该调用返回列表:`nova.objects.request_spec.RequestGroup`, 需要注意此处只使用到了`groups`的`trait`, `resources`相关属性, `accel`并未被使用:
``` list
[
RequestGroup(requester_id='device_profile_0',
resources={'PGPU': 1},
required_traits={'CUSTOM_GPU_PRODUCT_ID_1EB8'})
]
```
返回的RequestGroup合并到RequestSpec.required_resources中, 用于接下来的调度和创建实例。
2. nova-conductor/nova-scheduler调度
nova conductor调用nova-scheduler调度, nova-scheduler使用RequestSpec中的信息向placement查询合适的RP, 这些流程没有变动。
3. nova-conductor创建ARQ(accelerator request)
`nova.conductor.manager.ComputeTaskManager.schedule_and_build_instances`在调度完成后调用`_creaet_and_bind_arqs`创建并绑定ARQ。
首先调用`nova.accelerator.cyborg.create_arqs_and_match_resource_providers`,为该device profile创建ARQs, 获取新建的ARQs, 并按照group的索引,ResourceGroup及RPs的映射, 将ARQ的`device_rp_uuid`重置为对应的RP id并返回。
之后调用`nova.accelerator.cyborg.bing_arqs`将ARQ与计算节点主机名, 实例id,加速设备RP id绑定. Cyborg会依据不同的设备类型进行绑定, 例如FPGA在绑定时可能会烧写镜像。Cyborg绑定完成后会向nova发送一个ExternalEvent的notification, 其结构如下:
``` list
[
{
'name': 'accelerator-request-bound',
'server_uuid': 'instance_uuid',
'tag': 'arq_uuid',
'status': 'arq_bind_status'
}
]
```
Cyborg的绑定是异步的, 所以nova可以继续通过RPC调用`nova.compute.ComputeManager.build_and_run_instance`, ARQ uuids作为参数`accel_uuids`传入。
4. nova-compute孵化实例
在`nova.compute.ComputeManager._bild_and_run_instance`中调用`_build_resources`, 该方法尝试调用`_get_bound_arq_resources`以等待上述的notification发送. 若收到notification, 则尝试通过cyborg client获取ARQs详情并返回; 若在`CONF.arq_binding_timeout`内未收到notification, 则抛出异常。
在`nova.virt.libvirt.driver.LibvirtDriver.spawn`中调用`_get_guest_xml`,最后在`_get_guest_config`和`_guest_add_accel_pci_devices`方法中解析设备相关信息并挂载到实例上。