使用提供者树建模¶
概述¶
Placement 支持对不同资源提供者之间的分层关系进行建模。虽然父提供者可以拥有多个子提供者,但子提供者只能属于一个父提供者。因此,整个架构可以被认为是一个“树”结构,并且“树”顶端的资源提供者被称为“根提供者”。(有关详细信息,请参阅 嵌套资源提供者 规范。)
通过在创建资源提供者时使用 POST /resource_providers 操作指定父提供者来完成关系的建模。
注意
如果尚未设置父提供者,您也可以通过 PUT /resource_providers/{uuid} 操作在创建后为资源提供者设置父提供者。但是,不支持重新设置资源提供者的父级。
树中的资源提供者——以及下一节中描述的共享提供者——可以在 GET /allocation_candidates 操作的响应中以单个分配请求的形式返回。这意味着 placement 服务会查找一个资源提供者树,其中资源提供者可以共同包含所有请求的资源。
本文档描述了一些案例研究,以解释在 GET /allocation_candidates 操作中涉及提供者树的情况下,共享提供者、聚合和特征的工作方式。
筛选聚合¶
在上述示例中,CN1 和 CN2 之间的差异出现在您在 GET /allocation_candidates 操作中显式指定聚合时,使用 member_of 查询参数。 member_of 查询参数接受聚合 UUID,并将候选者筛选到给定聚合中的资源提供者。有关详细信息,请参阅 按聚合成员资格筛选 规范。
请注意,GET /allocation_candidates 操作假定“根提供者上的聚合跨越整个树,而非根提供者上的聚合不跨越整个树”。
例如,在上述环境中,请求
GET /allocation_candidates?resources=VCPU:1,MEMORY_MB:512,DISK_GB:500&member_of=<aggA uuid>
将返回八个候选者,
NUMA1_1(VCPU) +CN1(MEMORY_MB,DISK_GB)NUMA1_2(VCPU) +CN1(MEMORY_MB,DISK_GB)NUMA2_1(VCPU) +CN2(MEMORY_MB,DISK_GB)NUMA2_2(VCPU) +CN2(MEMORY_MB,DISK_GB)NUMA1_1(VCPU) +CN1(MEMORY_MB) +SS1(DISK_GB)NUMA1_2(VCPU) +CN1(MEMORY_MB) +SS1(DISK_GB)NUMA2_1(VCPU) +CN2(MEMORY_MB) +SS1(DISK_GB)NUMA2_2(VCPU) +CN2(MEMORY_MB) +SS1(DISK_GB)
这是因为聚合 A 位于根提供者 CN1 和 CN2 上,因此 API 假定子提供者 NUMA1_1、NUMA1_2、NUMA2_1 和 NUMA2_2 也位于聚合 A 中。
指定聚合 B
GET /allocation_candidates?resources=VCPU:1,MEMORY_MB:512,DISK_GB:500&member_of=<aggB uuid>
将返回两个候选者。
NUMA1_1(VCPU) +CN1(MEMORY_MB,DISK_GB)NUMA1_2(VCPU) +CN1(MEMORY_MB,DISK_GB)
这是因为 SS1 不在聚合 B 中,并且由于聚合 B 在 NUMA2_1 上不跨越整个树,因为资源提供者 NUMA2_1 不是根资源提供者。
按特征筛选¶
特征不仅用于指示共享提供者。它们用于表示资源提供者的功能。(有关详细信息,请参阅 Traits API 规范。)
可以在 GET /allocation_candidates 操作中使用 required 查询参数显式请求特征,但资源提供者上的特征永远不会跨越其他资源提供者。如果请求了特征,则出现在分配候选者中的资源提供者之一必须具有该特征,而与共享或嵌套提供者无关。有关详细信息,请参阅 请求特征 规范。 required 查询参数还支持否定表达式,通过 ! 前缀,用于禁止的特征。如果指定了禁止的特征,则分配候选者中出现的所有资源提供者都不应具有该特征。有关详细信息,请参阅 禁止的特征 规范。 required 参数还支持 in:T1,T2,... 语法,这意味着我们正在寻找在其上具有特征 T1 或 T2 的资源提供者。可以通过重复 required 查询参数来组合两种特征查询语法。因此,查询具有 (T1 或 T2) 且 T3 且不具有 T4 的提供者可以用 required=in:T1,T2&required=T3,!T4 表示。
例如,假设我们有以下环境
+----------------------------------------------------+
| +----------------------------------------------+ |
| | Compute Node (CN1) | |
| | resources: | |
| | VCPU: 8, MEMORY_MB: 1024, DISK_GB: 1000 | |
| | trait: [] | |
| +----------+------------------------+----------+ |
| | nested | nested |
| +----------+-----------+ +----------+----------+ |
| | NIC1_1 | | NIC1_2 | |
| | resources: | | resources: | |
| | SRIOV_NET_VF:8 | | SRIOV_NET_VF:8 | |
| | trait: | | trait: | |
| | [HW_NIC_ACCEL_SSL]| | [] | |
| +----------------------+ +---------------------+ |
+----------------------------------------------------+
假设尚未对任何资源提供者进行分配,则请求
GET /allocation_candidates?resources=VCPU:1,MEMORY_MB:512,DISK_GB:500,SRIOV_NET_VF:2
&required=HW_NIC_ACCEL_SSL
将仅为 SRIOV_NET_VF 返回 NIC1_1。因此,我们得到一个候选者。
CN1(VCPU,MEMORY_MB,DISK_GB) +NIC1_1(SRIOV_NET_VF)
相反,对于禁止的特征
GET /allocation_candidates?resources=VCPU:1,MEMORY_MB:512,DISK_GB:500,SRIOV_NET_VF:2
&required=!HW_NIC_ACCEL_SSL
将排除 NIC1_1 的 SRIOV_NET_VF。
CN1(VCPU,MEMORY_MB,DISK_GB) +NIC1_2(SRIOV_NET_VF)
如果特征不在 required 参数中,则该特征将在 GET /allocation_candidates 操作中被简单忽略。
例如
GET /allocation_candidates?resources=VCPU:1,MEMORY_MB:512,DISK_GB:500,SRIOV_NET_VF:2
将返回两个候选者。
CN1(VCPU,MEMORY_MB,DISK_GB) +NIC1_1(SRIOV_NET_VF)CN1(VCPU,MEMORY_MB,DISK_GB) +NIC1_2(SRIOV_NET_VF)
细粒度资源请求¶
如果您想一次从多个资源提供者处获取相同类型的资源,或者如果您需要特定请求的资源类别的提供者具有特定的特征或聚合成员资格,则可以使用 细粒度资源请求 功能。
通过对 resources、member_of 和 required 查询参数进行编号来启用此功能。
例如,在上述环境中,请求
GET /allocation_candidates?resources=VCPU:1,MEMORY_MB:512,DISK_GB:500
&resources1=SRIOV_NET_VF:1&required1=HW_NIC_ACCEL_SSL
&resources2=SRIOV_NET_VF:1
&group_policy=isolate
将返回一个候选者,其中两个提供者提供 SRIOV_NET_VF 资源。
CN1(VCPU,MEMORY_MB,DISK_GB) +NIC1_1(SRIOV_NET_VF:1) +NIC1_2(SRIOV_NET_VF:1)
群组策略 group_policy=isolate 确保一个资源来自具有 HW_NIC_ACCEL_SSL 特性的提供者,而另一个资源来自另一个提供者,没有特性约束。
如果 group_policy 设置为 none,则允许一个提供者服务多个细粒度请求。 也就是说
GET /allocation_candidates?resources=VCPU:1,MEMORY_MB:512,DISK_GB:500
&resources1=SRIOV_NET_VF:1&required1=HW_NIC_ACCEL_SSL
&resources2=SRIOV_NET_VF:1
&group_policy=none
将返回两个候选者。
CN1(VCPU,MEMORY_MB,DISK_GB) +NIC1_1(SRIOV_NET_VF:1) +NIC1_2(SRIOV_NET_VF:1)CN1(VCPU,MEMORY_MB,DISK_GB) +NIC1_1(SRIOV_NET_VF:2)
这是因为 NIC1_1 同时满足请求 1(具有 HW_NIC_ACCEL_SSL 特性)和请求 2(没有特性约束)。
请注意,如果在细粒度请求中指定了 member_of<N>,API 不会假设“根提供者上的聚合跨越整个树”。 它只会查找候选资源提供者时,查看指定的聚合是否直接与资源提供者关联。
按树过滤¶
如果您想按特定的提供者树过滤结果,请使用 按提供者树过滤分配候选 功能,并使用 in_tree 查询参数。 例如,假设我们有以下环境
+-----------------------+ +-----------------------+
| Sharing Storage (SS1) | | Sharing Storage (SS2) |
| DISK_GB: 1000 | | DISK_GB: 1000 |
+-----------+-----------+ +-----------+-----------+
| |
+-----------------+----------------+
| Shared via an aggregate
+-----------------+----------------+
| |
+--------------|---------------+ +--------------|--------------+
| +------------+-------------+ | | +------------+------------+ |
| | Compute Node (CN1) | | | | Compute Node (CN2) | |
| | DISK_GB: 1000 | | | | DISK_GB: 1000 | |
| +-----+-------------+------+ | | +----+-------------+------+ |
| | nested | nested | | | nested | nested |
| +-----+------+ +----+------+ | | +----+------+ +----+------+ |
| | NUMA1_1 | | NUMA1_2 | | | | NUMA2_1 | | NUMA2_2 | |
| | VCPU: 4 | | VCPU: 4 | | | | VCPU: 4 | | VCPU: 4 | |
| +------------+ +-----------+ | | +-----------+ +-----------+ |
+------------------------------+ +-----------------------------+
请求
GET /allocation_candidates?resources=VCPU:1,DISK_GB:50&in_tree=<CN1 uuid>
将通过 CN1 过滤候选,并返回 2 个分配候选组合。
NUMA1_1(VCPU) +CN1(DISK_GB)NUMA1_2(VCPU) +CN1(DISK_GB)
指定的树可以是非根提供者。 请求
GET /allocation_candidates?resources=VCPU:1,DISK_GB:50&in_tree=<NUMA1_1 uuid>
将返回相同的结果,并意识到与 NUMA1_1 资源提供者在同一树中的资源提供者。
NUMA1_1(VCPU) +CN1(DISK_GB)NUMA1_2(VCPU) +CN1(DISK_GB)
注意
在上述情况下,我们不会排除 NUMA1_2。 这种功能是单独提出的,并且正在进行中。 请参阅 支持子树过滤器 规范以获取详细信息。
带有后缀语法 in_tree<$S>(其中 $S 在微版本 1.25-1.32 中是一个数字,从 1.33 开始是 [a-zA-Z0-9_-]{1,64})也受 细粒度资源请求 的支持。 这会将满足带有后缀的细粒度资源组的提供者限制为指定提供者的树。
例如,在上述环境中,当您想要从 CN1 获取 VCPU,并从任何地方获取 DISK_GB 时,请求可能如下所示
GET /allocation_candidates?resources=VCPU:1&in_tree=<CN1 uuid>
&resources1=DISK_GB:10
这将返回共享提供者以及本地磁盘。
NUMA1_1(VCPU) +CN1(DISK_GB)NUMA1_2(VCPU) +CN1(DISK_GB)NUMA1_1(VCPU) +SS1(DISK_GB)NUMA1_2(VCPU) +SS1(DISK_GB)NUMA1_1(VCPU) +SS2(DISK_GB)NUMA1_2(VCPU) +SS2(DISK_GB)
这是因为未加后缀的 in_tree 仅应用于未加后缀的资源 VCPU,而不应用于加后缀的资源 DISK_GB。
当您想要从任何地方获取 VCPU,并从 SS1 获取 DISK_GB 时,请求可能如下所示
GET /allocation_candidates?resources=VCPU:1
&resources1=DISK_GB:10&in_tree1=<SS1 uuid>
这将坚持使用第一个共享提供者来获取 DISK_GB。
NUMA1_1(VCPU) +SS1(DISK_GB)NUMA1_2(VCPU) +SS1(DISK_GB)NUMA2_1(VCPU) +SS1(DISK_GB)NUMA2_2(VCPU) +SS1(DISK_GB)
当您想要从 CN1 获取 VCPU,并从 SS1 获取 DISK_GB 时,请求可能如下所示
GET /allocation_candidates?resources1=VCPU:1&in_tree1=<CN1 uuid>
&resources2=DISK_GB:10&in_tree2=<SS1 uuid>
&group_policy=isolate
这将只返回 2 个候选。
NUMA1_1(VCPU) +SS1(DISK_GB)NUMA1_2(VCPU) +SS1(DISK_GB)
按根提供者特性过滤¶
当特性与特定资源关联时,提供者树应构建为将特性与拥有该资源库存的提供者关联。 例如,特性 HW_CPU_X86_AVX2 是与 VCPU 资源关联的特性,因此应将其放置在具有 VCPU 库存的资源提供者上,无论该提供者在树结构中的位置如何。(感知 NUMA 的主机可能在子提供者中建模 VCPU 库存,而非感知 NUMA 的主机可能在根提供者中建模它。)
另一方面,某些特性与资源无关,而是与提供者本身关联。 例如,计算主机可能能够 COMPUTE_VOLUME_MULTI_ATTACH,或与 CUSTOM_WINDOWS_LICENSE_POOL 关联。 在这种情况下,建议使用根资源提供者来表示“计算主机”的概念;因此,这些类型的特性应始终放置在根资源提供者上。
以下环境说明了上述概念
+---------------------------------+ +-------------------------------------------+
|+-------------------------------+| | +-------------------------------+ |
|| Compute Node (NON_NUMA_CN) || | | Compute Node (NUMA_CN) | |
|| VCPU: 8, || | | DISK_GB: 1000 | |
|| MEMORY_MB: 1024 || | | traits: | |
|| DISK_GB: 1000 || | | STORAGE_DISK_SSD, | |
|| traits: || | | COMPUTE_VOLUME_MULTI_ATTACH | |
|| HW_CPU_X86_AVX2, || | +-------+-------------+---------+ |
|| STORAGE_DISK_SSD, || | nested | | nested |
|| COMPUTE_VOLUME_MULTI_ATTACH, || |+-----------+-------+ +---+---------------+|
|| CUSTOM_WINDOWS_LICENSE_POOL || || NUMA1 | | NUMA2 ||
|+-------------------------------+| || VCPU: 4 | | VCPU: 4 ||
+---------------------------------+ || MEMORY_MB: 1024 | | MEMORY_MB: 1024 ||
|| | | traits: ||
|| | | HW_CPU_X86_AVX2 ||
|+-------------------+ +-------------------+|
+-------------------------------------------+
以这种方式建模的树可以利用 root_required 查询参数,仅返回在其根提供者上具有(或不具有)特定特性的树中的分配候选。 例如,要返回包括具有 HW_CPU_X86_AVX2 指令集的 VCPU 以及能够 COMPUTE_VOLUME_MULTI_ATTACH 的主机的分配候选,请求可能如下所示
GET /allocation_candidates
?resources1=VCPU:1,MEMORY_MB:512&required1=HW_CPU_X86_AVX2
&resources2=DISK_GB:100
&group_policy=none
&root_required=COMPUTE_VOLUME_MULTI_ATTACH
这将从 NUMA_CN 和 NON_NUMA_CN 返回结果,因为两者都具有根提供者上的 COMPUTE_VOLUME_MULTI_ATTACH 特性;但只有 NUMA2 具有 HW_CPU_X86_AVX2,因此从 NUMA_CN 只有一个结果。
NON_NUMA_CN(VCPU,MEMORY_MB,DISK_GB)NUMA_CN(DISK_GB) +NUMA2(VCPU,MEMORY_MB)
要限制分配候选仅限于不在您的 CUSTOM_WINDOWS_LICENSE_POOL 中,请求可能如下所示
GET /allocation_candidates
?resources1=VCPU:1,MEMORY_MB:512
&resources2=DISK_GB:100
&group_policy=none
&root_required=!CUSTOM_WINDOWS_LICENSE_POOL
这将仅从 NUMA_CN 返回结果,因为 NON_NUMA_CN 在根提供者上具有禁止的 CUSTOM_WINDOWS_LICENSE_POOL。
NUMA_CN(DISK_GB) +NUMA1(VCPU,MEMORY_MB)NUMA_CN(DISK_GB) +NUMA2(VCPU,MEMORY_MB)
root_required 查询参数的语法与 required[$S] 相同:可以指定多个特性字符串,用逗号分隔,每个字符串都可以选择性地以 ! 为前缀,以表示它是禁止的。
注意
root_required 不能加后缀,并且只能指定一次,因为它仅适用于根提供者。
注意
当共享提供者参与请求时,root_required 仅应用于非共享提供者树的根。
注意
虽然 required 参数支持带有 in: 前缀语法的任何特性查询,但 root_required 参数目前不支持它。
按相同子树过滤¶
如果您想表达在单独的请求组中分配之间的亲和性,请使用 same_subtree 查询参数。 它接受以逗号分隔的请求组后缀字符串 ($S) 列表。 每个字符串必须与请求中的某个地方的细粒度组上的后缀完全匹配。 如果提供了此参数,则至少有一个满足指定请求组的资源提供者必须是其余资源的祖先。
例如,给定如下模型
+---------------------------+
| Compute Node (CN) |
+-------------+-------------+
|
+--------------------+-------------------+
| |
+-----------+-----------+ +-----------+-----------+
| NUMA NODE (NUMA0) | | NUMA NODE (NUMA1) |
| VCPU: 4 | | VCPU: 4 |
| MEMORY_MB: 2048 | | MEMORY_MB: 2048 |
| traits: | | traits: |
| HW_NUMA_ROOT | | HW_NUMA_ROOT |
+-----------+-----------+ +----+-------------+----+
| | |
+-----------+-----------+ +----------------+-----+ +-----+----------------+
| FPGA (FPGA0_0) | | FPGA (FPGA1_0) | | FPGA (FPGA1_1) |
| ACCELERATOR_FPGA:1 | | ACCELERATOR_FPGA:1 | | ACCELERATOR_FPGA:1 |
| traits: | | traits: | | traits: |
| CUSTOM_TYPE1 | | CUSTOM_TYPE1 | | CUSTOM_TYPE2 |
+-----------------------+ +----------------------+ +----------------------+
要请求位于同一 NUMA 节点上的 FPGA 和 VCPU 与 MEMORY,请求可能如下所示
GET /allocation_candidates
?resources_COMPUTE=VCPU:1,MEMORY_MB:256
&resources_ACCEL=ACCELERATOR_FPGA:1
&group_policy=none
&same_subtree=_COMPUTE,_ACCEL
这将产生包括
NUMA0(VCPU,MEMORY_MB) +FPGA0_0(ACCELERATOR_FPGA)NUMA1(VCPU,MEMORY_MB) +FPGA1_0(ACCELERATOR_FPGA)NUMA1(VCPU,MEMORY_MB) +FPGA1_1(ACCELERATOR_FPGA)
但不是
NUMA0(VCPU,MEMORY_MB) +FPGA1_0(ACCELERATOR_FPGA)NUMA0(VCPU,MEMORY_MB) +FPGA1_1(ACCELERATOR_FPGA)NUMA1(VCPU,MEMORY_MB) +FPGA0_0(ACCELERATOR_FPGA)
在 same_subtree 中指定的请求组不必具有 resources$S。 例如,要请求具有不同特性的 2 个 FPGA 位于同一 NUMA 节点上,请求可能如下所示
GET /allocation_candidates
?required_NUMA=HW_NUMA_ROOT
&resources_ACCEL1=ACCELERATOR_FPGA:1
&required_ACCEL1=CUSTOM_TYPE1
&resources_ACCEL2=ACCELERATOR_FPGA:1
&required_ACCEL2=CUSTOM_TYPE2
&group_policy=none
&same_subtree=_NUMA,_ACCEL1,_ACCEL2
这将产生包括
FPGA1_0(ACCELERATOR_FPGA) +FPGA1_1(ACCELERATOR_FPGA) +NUMA1
但不是
FPGA0_0(ACCELERATOR_FPGA) +FPGA1_1(ACCELERATOR_FPGA) +NUMA0FPGA0_0(ACCELERATOR_FPGA) +FPGA1_1(ACCELERATOR_FPGA) +NUMA1FPGA1_0(ACCELERATOR_FPGA) +FPGA1_1(ACCELERATOR_FPGA) +NUMA0
在第一个示例中,满足无资源请求组 ?required_NUMA=HW_NUMA_ROOT、NUMA1 的资源提供者将不在响应的 allocation_request 字段中,而显示在 mappings 字段中。
same_subtree 查询参数可以重复,并且每个重复组都被视为独立。