细粒度资源请求语法

https://blueprints.launchpad.net/nova/+spec/granular-resource-requests

随着 通用嵌套资源提供者 逐渐完善并得到应用,能够表达

  • 需求 1:请求分配特定资源类,并带有特定的一组特征;以及请求分配相同资源类,但带有不同的一组特征。

  • 需求 2:确保某些资源的请求从相同的资源提供者处分配。

  • 需求 3:在高度饱和的情况下,能够在多个资源提供者之间分散有效相同资源的分配。

本规范尝试通过在 flavor extra_specs 和 GET /allocation_candidates Placement API 中的资源和特征键上使用编号语法来解决这些需求。

注意

本文档在全文中使用“RP”作为“资源提供者”的缩写。

问题描述

到目前为止,对于通用和嵌套资源提供者以及特征,只能请求具有单个特征块的单个资源块。更具体地说

  • 资源只能表示为单个资源类的整数计数。无法表达第二个resource_class:count 与相同的资源类。

  • 所有指定的特征都适用于所有请求的资源。无法将某些特征应用于某些资源。

  • 给定资源类的所有资源都从同一个 RP 分配。

下面的 用例 举例说明了在这些限制下无法表达的场景。

用例

考虑以下硬件表示(“接线图”)

+-----------------------------------+
|                CN1                |
+-+--------------+-+--------------+-+
  |     NIC1     | |     NIC2     |
  +-+---+--+---+-+ +-+---+--+---+-+
    |PF1|  |PF2|     |PF3|  |PF4|
    +-+-+  +-+-+     +-+-+  +-+-+
       \      \__   __/      /
        \        \ /        /
        |         X         |
        |    ____/ \____    |
        |   /           \   |
      +-+--+-+         +-+--+-+
      | NET1 |         | NET2 |
      +------+         +------+

假设这在 Placement 中建模为

RP1 (represents PF1):
{
    SRIOV_NET_VF=16,
    NET_EGRESS_BYTES_SEC=1250000000,  # 10Gbps
    traits: [CUSTOM_NET1, HW_NIC_ACCEL_SSL]
}
RP2 (represents PF2):
{
    SRIOV_NET_VF=16,
    NET_EGRESS_BYTES_SEC=1250000000,  # 10Gbps
    traits: [CUSTOM_NET2, HW_NIC_ACCEL_SSL]
}
RP3 (represents PF3):
{
    SRIOV_NET_VF=16,
    NET_EGRESS_BYTES_SEC=125000000,  # 1Gbps
    traits: [CUSTOM_NET1]
}
RP4 (represents PF4):
{
    SRIOV_NET_VF=16,
    NET_EGRESS_BYTES_SEC=125000000,  # 1Gbps
    traits: [CUSTOM_NET2]
}

用例 1

作为 Operator,我需要能够表达一个实例的启动请求,该请求具有在物理网络 NET1 上的一个 SR-IOV VF,以及在物理网络 NET2 上的第二个 SR-IOV VF

我期望调度器接收到以下分配候选:

  • [RP1(SRIOV_NET_VF:1), RP2(SRIOV_NET_VF:1)]

  • [RP1(SRIOV_NET_VF:1), RP4(SRIOV_NET_VF:1)]

  • [RP3(SRIOV_NET_VF:1), RP2(SRIOV_NET_VF:1)]

  • [RP3(SRIOV_NET_VF:1), RP4(SRIOV_NET_VF:1)]

这展示了在单个请求中从不同提供者处获取相同资源类的不同分配的能力(需求 1)。

用例 2

请求:一个具有 10000 字节/秒出站带宽的 VF。(不,我不关心我在哪个 physnet 上 – 如果这让你困扰,请将 NET 替换为 SWITCH。)

期望:

  • [RP1(SRIOV_NET_VF:1), RP1(NET_EGRESS_BYTES_SEC:10000)]

  • [RP2(SRIOV_NET_VF:1), RP2(NET_EGRESS_BYTES_SEC:10000)]

  • [RP3(SRIOV_NET_VF:1), RP3(NET_EGRESS_BYTES_SEC:10000)]

  • [RP4(SRIOV_NET_VF:1), RP4(NET_EGRESS_BYTES_SEC:10000)]

这展示了确保不同资源类的分配可以从相同资源提供者处进行的能力(需求 2)。

用例 3

请求

  • NET1 上的一个 VF,带宽为 10000 字节/秒

  • NET2 上的一个 VF,带宽为 20000 字节/秒,具有 SSL 加速的 NIC(这个应该始终落在 RP2 上)。

期望:

* [RP1(SRIOV_NET_VF:1, NET_EGRESS_BYTES_SEC:10000),
RP2(SRIOV_NET_VF:1, NET_EGRESS_BYTES_SEC:20000)]
* [RP3(SRIOV_NET_VF:1, NET_EGRESS_BYTES_SEC:10000),
RP2(SRIOV_NET_VF:1, NET_EGRESS_BYTES_SEC:20000)]

这展示了同时满足 需求 1需求 2

用例 4

作为 Operator,我需要能够表达一个请求,请求多个 VF,即使我的 PF 几乎饱和,请求也能成功。对于此用例,假设每个 PF 资源提供者只有两个未分配的 VF。我需要能够表达一个在 NET1 上请求四个 VF 的请求。

期望:[RP1(SRIOV_NET_VF:2), RP3(SRIOV_NET_VF:2)]

这展示了 需求 3

提议的变更

编号请求组

使用现有的语法(一旦 依赖项 落地),资源请求可以逻辑地表示为

resources = { resource_classA: rcA_count,
              resource_classB: rcB_count,
              ... },
required = [ TRAIT_C, TRAIT_D, ... ]

语义上,每个生成的分配候选将由 resource_classN: rcN_count 资源任意地分布在同一树(即单个分配候选中的所有资源提供者将具有相同的 root_provider_uuid)内的资源提供者之间。每个结果候选中的每个资源提供者都将拥有列出的所有 required 特征。

注意

当共享资源提供者完全实现时,上述内容将变为,“... 任意地分布在同一树或聚合内的资源提供者之间”。

此外,不支持重复资源类或特征。

提出的更改是通过在 flavor extra_specs 和 GET /allocation_candidates Placement API 中的资源和特征键上使用编号资源分组来增强。

逻辑表示

resources = { resource_classA: rcA_count,
              resource_classB: rcB_count,
              ... },
required = [ TRAIT_C, TRAIT_D, ... ],

resources1 = { resource_class1A: rc1A_count,
               resource_class1B: rc1B_count,
               ... },
required1 = [ TRAIT_1C, TRAIT_1D, ... ],

resources2 = { resource_class2A: rc2A_count,
               resource_class2B: rc2B_count,
               ... },
required2 = [ TRAIT_2C, TRAIT_2D, ... ],

...,

resourcesX = { resource_classXA: rcXA_count,
               resource_classXB: rcXB_count,
               ... },
requiredX = [ TRAIT_XC, TRAIT_XD, ... ],

语义

以下术语“结果”用于指 GET /allocation_candidates 响应中 allocation_requests 列表中的一个项目的内容。

  • (单个)未编号分组的语义未更改。也就是说,它仍然可以从同一树(或者,当“共享”完全实现时,相同的聚合)中的不同 RP 返回结果。

  • 但是,编号组将始终从相同的 RP 返回结果。这是为了满足 需求 2

  • 单独的组(编号或未编号)可以从相同的 RP 返回结果。也就是说,通过分隔组并不能保证 RP 的排他性。(如果您想保证这种排他性,您需要使用特征。)

  • 仍然不支持在给定的(编号或未编号)resources 分组中重复资源类,但从一个分组到另一个分组重复资源类没有限制。同样适用于特征。这是为了满足 需求 1

  • 给定的 requiredN 列表仅适用于其匹配的 resourcesN 列表。这同样适用于未编号的 required/resources

  • 数字后缀是任意的。除了将 resourcesN 绑定到 requiredN 之外,它们没有隐含的含义。特别是,它们不需要是顺序的;并且它们的顺序没有语义意义。

  • 对于编号和未编号的 resources,单个resource_class:count 将永远不会在多个 RP 之间拆分。虽然对于例如 VF 来说,这种拆分可能被认为是合理的,但对于例如 DISK_GB 来说,显然是无效的。如果您想能够拆分,请使用单独的编号组。这满足了 需求 3

  • 指定 resources(编号或未编号)而不提供相应的 required 会返回未经过滤的特征的结果。

  • 指定 required(编号或未编号)而不提供相应的 resources 是一个错误。

Flavor 中的语法

参考 逻辑表示,现有(一旦 依赖项 落地)实现是在 flavor extra_specs 中指定 resourcesrequired 特征如下

  • 每个 resources 的成员被指定为单独的 extra_specs 条目,形式为

resources:resource_classA=rcA_count
  • 每个 required 的成员被指定为单独的 extra_specs 条目,形式为

trait:TRAIT_B=required

例如

resources:VCPU=2
resources:MEMORY_MB=2048
trait:HW_CPU_X86_AVX=required
trait:CUSTOM_MAGIC=required

提出: 允许通过将数字附加到 resourcestrait 关键字来使用相同的语法进行编号资源和特征分组

resourcesN:resource_classC=rcC_count
traitN:TRAIT_D=required

可以重复给定的编号 resourcestrait 键,以在同一分组中指定多个资源/特征,就像使用未编号的语法一样。

例如

resources:VCPU=2
resources:MEMORY_MB=2048
trait:HW_CPU_X86_AVX=required
trait:CUSTOM_MAGIC=required
resources1:SRIOV_NET_VF=1
resources1:NET_EGRESS_BYTES_SEC=10000
trait1:CUSTOM_PHYSNET_NET1=required
resources2:SRIOV_NET_VF=1
resources2:NET_EGRESS_BYTES_SEC:20000
trait2:CUSTOM_PHYSNET_NET2=required
trait2:HW_NIC_ACCEL_SSL=required

Placement API 中的语法

参考 逻辑表示,现有(一旦 依赖项 落地)Placement API 实现是通过 GET /allocation_candidates 查询字符串如下

  • resources 分组在一个名为 resources 的单个键下,其值为以逗号分隔的 resource_classN:rcN_count 列表。

  • 将特征分组在一个名为 required 的单个键下,其值为以逗号分隔的TRAIT_Y 列表。

例如

GET /allocation_candidates?resources=VCPU:2,MEMORY_MB:2048
    &required=HW_CPU_X86_AVX,CUSTOM_MAGIC

提出: 允许通过将数字附加到 resourcesrequired 关键字来使用相同的语法进行编号资源和特征分组。在以下示例中,组 1 和 2 表示 用例 3

GET /allocation_candidates?resources=VCPU:2,MEMORY_MB:2048
    &required=HW_CPU_X86_AVX,CUSTOM_MAGIC
    &resources1=SRIOV_NET_VF:1,NET_EGRESS_BYTES_SEC:10000
    &required1=CUSTOM_PHYSNET_NET1
    &resources2=SRIOV_NET_VF:1,NET_EGRESS_BYTES_SEC:20000
    &required2=CUSTOM_PHYSNET_NET2,HW_NIC_ACCEL_SSL

响应有效负载语法没有变化。

备选方案

  • 需求 2 也可以通过将每个 RP 与唯一的聚合关联来表达,一旦共享资源提供者完全实现。但是,完成共享资源提供者的工作不在 Queens 的范围内。

  • 我们可以允许“数字”后缀是任意字符串。但是,使用整数易于理解和验证,并避免了对特殊字符进行转义/编码的担忧等问题。

  • 一直以来都有关于需要基于 JSON 有效负载的 API 以实现更丰富的表达来请求分配候选的讨论。虽然这仍然是未来的可能性,但在这种情况下,被认为是不必要的,因为当前的需求可以通过对现有 GET /allocation_candidates API 的查询字符串语法进行提出的(相对简单的)增强来满足。

  • 有人建议包含(或至少保持开放)允许用户表达资源(反)亲和力的语法。本规范提出的更改留下了一个与亲和力相关的用例的细小缺口未得到满足。这些用例的范围和确切形式,以及现实世界的需求,目前尚不清楚,因此本规范未解决这些问题。

数据模型影响

无。

REST API 影响

参见 Placement API 中的语法。总而言之,GET /allocation_candidates Placement API 被修改为接受格式为 resourcesNrequiredN 的任意查询参数键,其中 N 可以是任何整数。这些参数值的格式与 resourcesrequired 的格式相同。

否则,没有 REST API 影响。

安全影响

通知影响

其他最终用户影响

Operator 需要理解 Flavor 中的语法语义 的更改,以便创建利用新功能的 flavor。参见 文档影响

对 nova 或 openstack CLI 没有影响。现有的 CLI 语法足以表达新支持的 extra_specs 键。

性能影响

使用新的语法会导致 GET /allocation_candidates Placement API 实际上在每次请求中执行多个查找。这可能会通过一个因子 N+1 影响数据库性能,其中 N 是给定请求中指定的编号资源分组的数量。巧妙的 SQL 表达式可以减少或消除这种影响。

不应有数据库之外的影响,因为此功能不应导致 GET /allocation_candidates API 返回的记录数量显著增加(如果任何,增加的特异性将减少结果数量)。

其他部署者影响

开发人员影响

开发提供资源提供者表示的模块(例如 virt 驱动程序)的开发人员需要了解此功能,以便适当地建模他们的 RP。

实现

负责人

  • jaypipes

  • efried

工作项

调度器

  • Placement API 协商微版本功能。

  • 识别并解析新的 风味语法

  • 如果识别出新的风味 extra_specs 语法,并且 Placement API 不具备相应的微版本,则报错。

  • 根据风味 extra_specs 构建 GET /allocation_candidates 查询字符串。

  • GET /allocation_candidates 请求发送到 Placement,如果使用了新的语法,则指定适当的微版本。

Placement

  • 发布一个新的微版本。

  • 如果在新微版本下调用,则识别并解析新的 GET /allocation_candidates 查询字符串键格式。

  • 构建适当的数据库查询/查询。

  • 其他内容保持不变。

依赖项

这项工作建立在以下规范之上,并依赖于它们的批准和实施

测试

将添加功能测试,包括 gabbits,以测试新的语法。可能需要新的 fixtures 来表达一些更复杂的配置,特别是涉及嵌套资源提供商的配置。将设计测试用例来证明 语义 中列出的项目的各种组合和排列。例如,使用编号和未编号分组的 GET /allocation_candidates 请求,针对包含多个嵌套资源提供商树(三级或更多)且涉及特性传播的 Placement 服务。

文档影响

参考资料

历史

修订版

发布名称

描述

Queens

引入