摘要:OpenStack社區在Ussuri版本完成了nova-cyborg interaction功能的開發, 該功能加強了nova和cyborg的聯繫, 解耦了nova的PCI加速設備管理功能, 通過cyborg和placement可以讓加速器資源的管理更加靈活。
概念
PR
resource provider, placement中的概念, 資源提供者。
Device Profile
Device profile是Cyborg中的概念, 它用於描述單個或多個加速設備,可以將之看作加速設備的flavor. 廣義上, 它包括了兩點:
- 特定資源類的數量(resource class)
- RP需要滿足的要求(trait)
一個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字段進行的, 規則如下:
- device profile中的group的順序並不重要, 但是cyborg保留了這個順序. 因此每個RequestGroup都有一個唯一的索引;
- 當cyborg返回的device profile groups添加到request spec中時, 對於第N個RequestGroup, requester_id將被設置爲`device_profile_<N>`. 因爲每個request spec只有一個device profile, 所以device profile的名稱不需要包含在其中;
- 當cyborg爲device profile創建一個ARQ時, 它會在ARQ中嵌入group的索引, 然後將之返回給nova;
- 匹配由以下兩步完成:每個ARQ使用的requester_id字段映射到request spec的RequestGroup中;每個RequestGroup被映射到特定的RP, 與neutron bandwidth provider的邏輯一致。
一個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`方法中解析設備相關信息並掛載到實例上。
參考文獻
- https://specs.openstack.org/openstack/cyborg-specs/specs/train/approved/device-profiles.html
- https://specs.openstack.org/openstack/nova-specs/specs/ussuri/approved/nova-cyborg-interaction.html
- https://github.com/openstack/nova/blob/63380a6b494e0f0f220b67b197edec836f1c5a42/nova/objects/request_spec.py#L777