Node Traits

https://bugs.launchpad.net/ironic/+bug/1722194

通过允许操作员为每个节点设置一系列关联的特性,从而实现更精细的 Ironic 节点 Nova 调度。

问题描述

虽然最近为每个节点添加的资源类已经帮助改进了 Nova 中 Ironic 资源的调度方式,使用新的 Placement API,但许多用例需要更精细的控制。

一个示例用例是为特定项目专门分配一个 Ironic 节点池。 另一个是允许最适合可用硬件的 flavor,如果缺少较小的机器,你可能希望在较大的机器上构建较小的 flavor。

类似地,你可能有一组硬件,它们都相同,除了所选的 RAID 配置。 从长远来看,当你通过 Nova boot 预置节点时,能够自动使用所选的 RAID 配置重新配置硬件会很好。 目前这被认为超出范围。

提议的变更

Placement API 能够使用特性标记资源提供者:https://specs.openstack.org/openstack/nova-specs/specs/pike/approved/resource-provider-traits.html

nova ironic driver 目前确保为每个 Ironic 节点存在一个资源提供者。 它已经使用正确的定量资源(即资源类)填充了库存。

为了获得更精细的调度,我们依赖于将特性添加到资源提供者,以及以下 Nova specs 的实现,以确保调度过程尊重 flavor 中请求的特性

当前提案是让 Ironic 存储每个节点的特性列表。 然后,该列表可以同步到 Placement API 中的适当资源提供者,由 Nova 的 ironic virt driver 以类似于今天报告每个 ironic 节点的 RESOURCE_CLASS 的方式进行同步。

我们来讨论一下为仅由特定项目集使用的专用 Ironic 节点用例。 其余主机供通用使用。 如果用户拥有专用的资源池,他们可以选择在专用池或通用池中创建实例。 其他用户只能在通用池中构建。 一种像这样划分节点的方法是为适当的 ironic 节点分配诸如 CUSTOM_IRONIC_NODE_PROJECT_BCUSTOM_IRONIC_NODE_GENERAL_USE 等特性。 然后,有一个公共 flavor 用于定位通用主机池,以及一个私有项目特定 flavor 用于定位其专用池。 通过这种方法,很容易为其他项目集添加额外的节点池。 这样做更容易,因为你在添加额外的节点池时不需要修改任何现有节点和 flavor。

请注意,检查规则可用于设置节点的初始资源类。 预计节点的初始特性集可以以相同的方式设置。

注意

已经有一个 Nova spec 提出讨论了 Nova 方面的内容,即我们如何将特性分配给资源提供者,以及在 Nova boot 时将选择的特性发送回 ironic

在预置节点时,Nova 中的 Ironic virt driver 现在会将额外的 flavor extra_specs 发送到 Ironic。 目前,只有以 capabilities 开头的 extra_specs 存储在 instance_info 中。 在上述 spec 之后,ironic virt driver 还会包含定义了请求特性的 flavor extra specs,并将它们存储在 instance_info['traits'] 中。

注意

请注意,这不会改变 capabilities 的使用方式。

Ironic 需要验证 instance_info['traits'] 与当前与 Ironic 节点关联的特性列表一致,即我们必须检查 instance_info['traits'] 仅包含已存在于 Ironic 节点上特性列表中的特性。 这对于防止由于 Ironic 节点特性列表的更新与 Ironic virt driver 将该列表复制到 Placement API 之间的竞争条件而导致的奇怪行为非常有用。 此验证最好集成到 driver.deploy.validate 或类似内容中,以确保它由调用部署节点和调用节点验证触发。

注意

Nova 中的 ironic virt driver 将同步每个 Ironic 节点报告的特性列表到 Nova 的 Placement API,类似于今天完成资源类的方式。 如果操作员直接与 Placement 交互以调整特性,则此过程将在下一次同步时删除所有这些修改。 操作员必须使用 Ironic API 更改给定节点的特性列表。 假设 Ironic 是代表 Ironic 节点的资源提供者关联的特性列表的事实来源。

备选方案

将来,预计驱动程序可能需要验证一些众所周知的特性,以查看它们是否受支持。 此外,某些驱动程序可能会自动报告某些特性。 紧随其后的是,驱动程序可能会读取 instance_info 中指定的特性以重新配置节点。 所有这些都超出本文档的范围。

着眼于范围之内的情况,还有其他方法

  • 让操作员(和 ironic-inspector)直接与 Placement API 交互以设置节点特性。 这将非常奇怪,因为 Nova 使用 ComputeNode uuid 作为资源提供者的 uuid 同步资源提供者。 在同步完成之前,你无法设置特性。 目前 placement 主要是内部 API,很少有策略控制,因此所有这些都需要改变才能允许上述情况。 这一切看起来都非常混乱。

  • 将特性 API 保留在 Ironic 中,但使其成为 Placement 的穿透代理。 这将使 Ironic 难以依赖 placement,这对于 Bifrost 来说将是一个奇怪的要求,并且会使升级复杂化。

当前方法使 Ironic 无需以任何方式依赖 placement,这效果很好。

下面描述的 REST API 允许对设置特性进行细粒度控制,遵循 API-WG 和现有 placement API 的模式。 相反,我们可以扩展现有的 ironic 节点 PATCH 接口。

下面建议的 CLI 方法遵循新的 API,但作为替代,我们可以扩展现有的 CLI 接口围绕 PATCH API 调用。 它看起来更像

  • openstack baremetal node set –trait CUSTOM_FOO <node-uuid>

  • openstack baremetal node unset –trait CUSTOM_FOO <node-uuid>

数据模型影响

与现有标签表类似,我们需要添加一个新的表来存储与节点关联的特性

CREATE TABLE node_traits (
    node_id INT(11) NOT NULL,
    trait VARCHAR(255) CHARACTER SET utf8 NOT NULL,
    PRIMARY KEY (node_id, trait),
    KEY (trait),
    FOREIGN KEY (node_id)
      REFERENCES nodes(id)
      ON DELETE CASCADE,
)

将添加一个新的 ironic.objects.traits.NodeTraitList 对象到对象模型中。 python 对象模型中的 ironic.objects.traits.NodeTraitList 字段将在需要时填充(即不急切加载)。

特性应定义为与 placement API 定义匹配的方式,即不超过 255 个字符的 Unicode 字符串。

状态机影响

没有影响。

REST API 影响

placement API 在 os-traits 库中定义了一组标准特性。 任何未在该库中定义的特性都必须以 CUSTOM_ 前缀开头。 在 Ironic 中设置的任何特性都必须遵循这些规则,否则 ironic Nova virt driver 将无法在 Placement 中添加这些特性。 出于类似的原因,任何节点上的特性限制为 50 个,以匹配 Placement 中的限制。 请求添加格式错误的特性应收到状态码为 400 的响应。

请注意,Ironic 在任何时候都不会与 Placement API 交互。 上述验证仅依赖于访问 python 库 os-traits。 因此,此验证对如何在独立 Ironic 中使用特性来分配任意特性给特定的 Ironic 节点几乎没有限制。 任何非标准特性只需要添加 CUSTOM_ 前缀。 有关 os-traits 的更多详细信息,请参见:https://docs.openstack.org/os-traits/latest

为了方便起见,将能够通过以下方式扩展现有的 API 来获取所有节点及其关联特性的完整列表(在请求包含这些详细信息的足够高的微版本时)

GET /v1/nodes/detail

{
  "nodes": [
    {
      ...
      "traits": ['CUSTOM_FOO', 'CUSTOM_BAR', 'CUSTOM_BAZ'],
      ...
    }
  ]
}

与其它字段类似,我们还将支持仅请求此字段(部分是为了使 Nova virt driver 轮询更有效)

GET /v1/nodes/?fields=uuid,traits

{
  "nodes": [
    {
      "uuid": "uuid-1",
      "traits": ['CUSTOM_FOO', 'CUSTOM_BAR', 'CUSTOM_BAZ']
    },
    ...
  ]
}

节点特性的操作将遵循 placement API 和 API WG 标签规范建立的模式

首先将有一个新的特性资源,它遵循上述模式。

请求所有节点特性的示例

GET /nodes/{node_ident}/traits

响应

{
    "traits": ['CUSTOM_FOO', 'CUSTOM_BAR', 'CUSTOM_BAZ']
}

将所有节点特性设置为给定列表的示例请求

PUT /nodes/{node_ident}/traits
{
    "traits": ['CUSTOM_FOO', 'CUSTOM_BAR', 'CUSTOM_BAZ']
}

响应

{
    "traits": ['CUSTOM_FOO', 'CUSTOM_BAR', 'CUSTOM_BAZ']
}

成功时的响应是状态码 200。 在验证失败(使用 os-traits 库)时,我们返回状态码 400(错误请求),与 API-WG 的 HTTP 指南相符。

请注意,与资源类不同,我们允许随时更新特性。 这主要是因为 placement 允许进行此类更新,并且虽然资源类和 Ironic 节点用于 placement 中的分配,但特性不用于分配。

类似地,以下 API 删除所有特性

DELETE /nodes/{node_ident}/traits

成功时的响应是状态码 204,带有空正文。

要添加或删除单个特性,请使用

PUT /nodes/{node_ident}/traits/CUSTOM_FOO
<no body>

DELETE /nodes/{node_ident}/traits/CUSTOM_FOO

按特性过滤节点列表应该可以按预期工作

GET /nodes?traits=CUSTOM_RED,CUSTOM_BLUE
GET /nodes?not-traits=CUSTOM_RED,CUSTOM_BLUE&traits=CUSTOM_FOO
GET /nodes?traits-any=CUSTOM_RED,CUSTOM_BLUE
GET /nodes?not-traits-any=CUSTOM_RED,CUSTOM_BLUE

如上所述,最终的更改是确保 instance_info/traits 是 Ironic 节点上设置的特性的子集。 这应该作为现有的 driver.deploy.validate() 调用(或类似调用)的一部分,以便在启动部署之前和显式节点验证调用时检查特性。

客户端 (CLI) 影响

“ironic” CLI

无更改,已弃用。

“openstack baremetal” CLI

你可以列出节点上的特性

  • openstack baremetal node list –fields uuid name traits

  • openstack baremetal node show <node-ident> –fields uuid name traits

  • openstack baremetal node trait list <node-ident>

你可以更新节点上的特性列表

  • openstack baremetal node add trait <node-ident> CUSTOM_FOO CUSTOM_BAR

  • openstack baremetal node remove trait <node-ident> CUSTOM_FOO CUSTOM_BAR

  • openstack baremetal node remove trait –all <node-ident>

这大致复制了一致性组的命令语法:https://docs.openstack.org/python-openstackclient/latest/cli/command-objects/consistency-group.html#consistency-group-add-volume

通常使用 set 和 unset 来表示键值对,但 add 和 remove 更适合于对列表进行就地修改。 它消除了 set 含义是添加特性列表还是替换整个特性列表的任何歧义。 另一种选择是将特性操作添加到现有的 openstack baremetal node set 操作中,但我们而是遵循 API 的结构。

你可以使用特性查询节点列表

  • openstack baremetal node list –trait CUSTOM_RED –not-trait CUSTOM_BLUE

  • openstack baremetal node list –trait-any CUSTOM_RED CUSTOM_BLUE

  • openstack baremetal node list –not-trait-any CUSTOM_RED CUSTOM_BLUE

RPC API 影响

没有影响。

驱动程序 API 影响

没有影响。

Nova 驱动程序影响

需要确保在启动节点时传递回正确的 flavor extra specs。

Ramdisk 影响

安全影响

将对任何节点设置一个硬编码的限制为 50 个特性,以防止滥用 API。 这可以防止拒绝服务攻击,恶意用户通过设置大量特性来填充数据库。 实际上,该限制是为了匹配 placement API 中应用的限制。

其他最终用户影响

可扩展性影响

性能影响

其他部署者影响

开发人员影响

实现

负责人

主要负责人

John Garbutt (johnthetubaguy)

其他贡献者

Dmitry Tantsur (dtantsur) Mark Goddard

工作项

  • 添加用于存储节点特性的表

  • 添加用于公开该表的对象

  • 添加新的特性 API

  • 添加对新 API 的 openstack cli 支持

  • 后续进行 Nova driver 工作

依赖项

以下 nova spec 依赖于此 spec

测试

Nova 功能测试计划覆盖集成的调度方面。 作为此 spec 的一部分,我们将专注于确保 API 能够正确地持久化给定节点的特性,并使用特性查询资源。

升级和向后兼容性

从长远来看,某些功能和其它 API 可能会被逐步淘汰。但这不在本次规范的考虑范围内。在旧调度机制和新调度机制之间实现功能对等性之前,还需要做很多工作。

文档影响

需要更新 API-REF 和管理文档,以涵盖如何使用新的 API。

参考资料