The Traits API - Manage Traits with ResourceProvider¶
https://blueprints.launchpad.net/nova/+spec/resource-provider-traits
本规范旨在在 placement API 中提出一个新的 REST 资源 traits,以管理 ResourceProvider 的定性部分。通过使用 Traits API,placement 服务可以通过 Traits 管理资源提供程序的特征,然后帮助调度器做出更好的放置决策,以匹配启动请求。
问题描述¶
ResourceProvider 拥有一系列 Inventory 和 Allocation 对象来管理启动请求的定量方面:当实例使用来自 ResourceProvider 的资源时,Inventory 中相应的资源数量会被 Allocation 扣除。除了定量方面,ResourceProvider 也需要不可消耗的定性方面来区分它们的特征。
一个经典的例子是从不同的提供程序请求磁盘:用户可能请求实例的 80GB 磁盘空间(定量),但也可能期望磁盘是 SSD 而不是机械磁盘(定性)。能够标记存储提供程序(它可以是共享存储或计算节点连接的存储)是 SSD 或机械磁盘,这正是我们所关注的。
许多 traits 由 OpenStack 以标准方式定义,例如 Intel CPU 指令集扩展。这些都是以编程方式报告的,并且将在所有 OpenStack 云中保持一致。但是,部署者可能还有一些其他的自定义 traits,placement 服务需要支持这些 traits。
用例¶
管理员用户想要知道云可以识别的有效 traits。
其他 OpenStack 服务想要知道用户输入的 traits 在云中是否有效。
其他 OpenStack 服务想要一种指示 ResourceProviders 的 traits 的方式(例如,Nova 想要指示计算节点提供的 CPU 功能)。
云提供商管理员想要一种指示资源提供程序 traits 的方式。(例如,云提供商管理员想要指示某些存储提供程序的性能优于其他存储提供程序)。
提议的变更¶
我们建议在 placement API 中使用一个新的 REST 资源 trait 来管理资源提供程序的定性信息。 trait 只是一个字符串,它与 Tags API-WG guideline 中定义的 Tags 非常相似。
有两种类型的 Traits:标准 traits 和自定义 traits。
标准 traits 在不同的 OpenStack 云部署中是可互操作的。标准 traits 的定义来自 os-traits 库。标准 traits 在 placement API 中是只读的,这意味着用户不能通过 API 修改任何标准 traits。所有 traits 都被分类到不同的命名空间中。命名空间也由 os-traits 定义。 os-traits 中 traits 的定义将在单独的提案中讨论。下面示例中使用的所有 traits 仅用于演示目的。
自定义 traits 由管理员用户用来管理 ResourceProviders 的非标准定性信息。管理员用户可以从 placement API 定义自定义 traits。自定义 trait 必须以命名空间 CUSTOM_ 为前缀。命名空间 CUSTOM_ 在 os-traits 中定义。
用户只能在请求中使用有效的 traits。有效的 traits 包括标准 traits 和自定义 traits。
Traits API 的使用场景如下
场景 1:单个 Resource Provider¶
在此场景中,Nova 为每个计算节点创建一个 ResourceProvider。每个计算节点然后报告其定性信息,这些信息被标记为一组 Traits。这些信息将定期更新,尽管我们不期望资源提供程序的定性信息经常变化。
将 os-traits 值同步到 Placement¶
Placement API 被设计为验证部署中哪些 traits 有效的唯一事实来源。服务升级之间没有硬依赖链,但操作员必须记住,只有 Placement API os-traits 版本将在部署中成为主版本。
将添加一个新的命令 placement-manage os-traits sync。它用于将标准 traits 从 os-traits 同步到 placement DB。部署者应在 os-traits 升级后调用此命令。
Traits API 与 Aggregate metadata API¶
以前,部署者会通过使用 Aggregate metadata 来管理定性信息。他们会通过为具有他们希望跟踪的特定 trait 的主机创建聚合,然后在该聚合上设置 metadata 来标识该 trait 来执行此操作。这种做法可扩展性有限且难以管理。例如,如果部署中存在多种 trait 组合:这需要间接管理聚合,而不是直接管理 traits。这会在 traits 和主机之间创建非常复杂的映射。确定特定主机可能具有哪些 traits 也不是一件简单的事情。最后,这种方法仅适用于计算节点,而不适用于所有潜在的资源提供程序。
建议的 traits REST API 端点将取代使用聚合来跟踪和管理定性信息。给定资源提供程序的 traits 将是一个扁平列表,并且可以通过 API 轻松管理。
一旦 Traits API 投入使用,将弃用聚合 metadata 的使用。当然,聚合本身仍然存在,因为它们用于 metadata 目的之外的更多目的。聚合 metadata 的弃用将在单独的规范中讨论。
备选方案¶
在之前的提案中,将此新的 REST 资源命名为 Tags 的替代方案。但是,目前,os-traits 库对标准 traits 进行了验证。API 需要区分标准 traits 和自定义 traits,它们不再是一些通用的 tags。因此,“Traits”是正确的术语。
另一种替代方案是向 traits 添加属性。例如,在创建命名空间时:与其用命名空间字符串作为前缀,不如向表示其命名空间的 trait 添加一个属性。这将消除在上述示例中添加“HW”和“HV”部分 trait 名的需要。属性的另一个用途是区分系统生成的 traits 和自定义 traits。另一个潜在用途是定义 traits 的类别,例如用户可查询的 traits。因此,虽然这通过使这些 traits 的方面可查询来简化某些事情,但这意味着我们必须将 trait 视为一个对象,而不仅仅是一个简单的字符串。
另一种替代方案是为每种具有无限库存的 capability 创建一个特殊的 ResourceClass。在这种方法中,对 SSD 的请求将“消耗”一个 SSD,但由于库存是无限的,因此它永远不会耗尽。这将具有无需创建任何新表的优点,并且只需要对现有类进行小的更改即可实现无限库存。它确实会受到概念上的脱节,因为我们实际上并没有消耗任何东西。它也会使查询 capability 变得更加复杂。关于这个想法的更多解释在博客 Simple Resource Provision 上。
受到上述想法的启发,另一种替代方案是使用 ResourceProviderTraits 而不是 ResourceClass。原因是 ResourceClass 和 Traits 非常相似,都是字符串。实际上,我们只需要对定量和定性的管理有一个指示。通过这种方式,我们可以实现上述替代想法的目标,并且没有无限库存。关于这个想法的更多解释在邮件列表中 Use ResourceProviderTraits instead of ResourceClass。
数据模型影响¶
将向 API 数据库添加一个新的表。对于数据库模式,以下表就足够了
CREATE TABLE traits (
id INT NOT NULL,
name VARCHAR(255) NOT NULL,
PRIMARY KEY (id),
UNIQUE INDEX (name)
);
CREATE TABLE resource_provider_traits (
resource_provider_id INT NOT NULL
trait_id INT NOT NULL,
PRIMARY KEY (resource_provider_id, trait_id),
);
REST API 影响¶
Traits API 附加到 Placement API 端点。Traits API 包括两个新的 REST 资源:/traits 和 /resource_providers/{uuid}/traits。
/traits:这用于管理云中的 traits,也是查询云中现有和关联 traits 的唯一位置。这有助于使 traits 在云中的所有服务中保持一致。所有用户都可以读取 traits,只有管理员用户才能修改 traits。
/resource_providers/{uuid}/traits:这用于查询/编辑 traits 和 resource_providers 之间的关联。此端点只能由管理员和/或服务用户使用。
Trait 对象的通用 json-schema 如下
TRAIT = {
"type": "string",
'minLength': 1, 'maxLength': 255,
"pattern": "^[A-Z0-9_]+$"
}
自定义 trait 必须以 CUSTOM_ 为前缀,json-schema 如下
CUSTOM_TRAIT = {
"type": "string",
'minLength': 1, 'maxLength': 255,
"pattern": "^CUSTOM_[A-Z0-9_]+$"
}
添加的 API 端点是
GET /traits 根据指定参数列出所有现有的 trait 字符串
GET /traits/{trait} 检查 trait 是否存在于云中
PUT /traits/{trait} 将一个新的自定义 trait 创建到 placement 服务
DELETE /traits/{trait} 从 placement 服务删除一个自定义 trait
GET /resource_providers/{rp_uuid}/traits 列出与特定 resource provider 关联的 traits
PUT /resource_providers/{rp_uuid}/traits 设置特定 resource provider 的所有 traits
DELETE /resource_providers/{rp_uuid}/traits 删除特定 resource provider 的任何现有 trait 关联
添加的端点的详细信息如下
GET /traits¶
根据指定的参数返回有效的 trait 字符串列表。
响应体必须符合以下 JSONSchema 文档
{
"type": "object",
"properties": {
"traits": {
"type": "array",
"items": TRAIT,
}
},
'required': ['traits'],
'additionalProperties': False
}
默认操作是查询 placement 服务中的所有标准和自定义 traits
GET /traits
响应
200 OK
Content-Type: application/json
{
"traits": [
"HW_CPU_X86_3DNOW",
"HW_CPU_X86_ABM",
...
"CUSTOM_TRAIT_1",
"CUSTOM_TRAIT_2"
]
}
以下 3 个部分指定此 GET 请求的 3 个不同参数。
GET /traits?name=starts_with:{prefix}¶
要查询名称以特定前缀开头的 traits,请使用查询参数 name 使用 starts_with 运算符。例如,您可以通过使用 CUSTOM 前缀过滤 traits 来查询所有自定义 traits。
示例
GET /traits?name=starts_with:CUSTOM
响应
200 OK
Content-Type: application/json
{
"traits": [
"CUSTOM_TRAIT_1",
"CUSTOM_TRAIT_2"
]
}
GET /traits?associated={True|False}¶
要查询已与 placement 服务中的至少一个 resource provider 关联的 traits,请使用参数 associated 将它们过滤掉。
GET /traits?name=in:a,b,c¶
返回使用 in: 参数列出的存在于此云中的 traits。
例如,当 admin-user 创建指定 trait 字符串的 flavor 时,Nova 可以使用以下示例获取云中定义的这些 traits 的列表
GET /traits?name=in:HW_CPU_X86_AVX,HW_CPU_X86_SSE,HW_CPU_X86_INVALID_FEATURE
其响应
200 OK
Content-Type: application/json
{
"traits": [
"HW_CPU_X86_AVX",
"HW_CPU_X86_SSE"
]
}
注意
HW_CPU_X86_INVALID_FEATURE 不是云中的有效 trait,因此它不会包含在响应中。Nova 从而可以意识到无效的 traits 并向用户提供信息丰富的响应。
GET /traits/{trait_name}¶
此 API 用于检查 trait 名称是否存在于此云中。
返回的响应将是以下之一
204 No Content 如果 trait 名称存在。
404 Not Found 如果 trait 名称不存在。
PUT /traits/{trait_name}¶
此 API 用于插入单个自定义 trait,而无需发送整个 trait 列表
PUT /traits/CUSTOM_TRAIT_1
其响应包括 Location 标头中的新 trait 的 URL
Location: traits/CUSTOM_TRAIT_1
返回的响应将是以下之一
201 Created 如果插入成功。
204 No Content 如果 trait 已经存在。
400 BadRequest 如果 trait 名称没有以 CUSTOM_ 前缀开头。
409 Conflict 如果 trait 名称与标准 trait 名称冲突。
DELETE /traits/{trait_name}¶
此 API 用于删除指定的 trait。请注意,只能删除自定义 traits。
返回的响应将是以下之一
204 No Content 如果删除成功。
400 BadRequest 如果要删除的名称是标准 trait。
404 Not Found 如果不存在这样的 trait。
409 Conflict 如果要删除的名称与任何 ResourceProvider 具有关联。
GET /resource_providers/{uuid}/traits¶
返回特定 resource provider 提供的 trait 列表。
响应格式与 GET /traits 类似,但主体包含 resource_provider_generation。
示例
200 OK
Context-Type: application/json
{
"traits": [
"HW_CPU_X86_3DNOW",
"HW_CPU_X86_ABM",
...
"CUSTOM_TRAIT_1",
"CUSTOM_TRAIT_2"
],
"resource_provider_generation": 3
}
返回的响应将是以下之一
200 OK 如果查询成功。
404 Not Found 如果由 {uuid} 标识的 resource provider 未找到。
PUT /resource_providers/{uuid}/traits¶
此 API 用于将 traits 与指定的 resource provider 关联。所有关联的 traits 都将替换为请求主体中指定的 traits。Nova-compute 将通过此 API 报告计算节点的 traits。
请求体必须符合以下 JSONSchema 文档
{
"type": "object",
"properties": {
"traits": {
"type": "array",
"items": CUSTOM_TRAIT
},
"resource_provider_generation": {
"type": "integer"
}
},
'required': ['traits', 'resource_provider_generation'],
'additionalProperties': False
}
示例
PUT /resource_providers/508f3973-8e1a-4241-afec-ee3e21be0611/traits
Content-type: application/json
{
"traits": [
"CUSTOM_TRAIT_1",
"CUSTOM_TRAIT_2"
],
"resource_provider_generation": 112
}
成功的 HTTP 将以 GET 响应的相同格式列出更改的 traits。返回的响应将是以下之一
200 OK 如果更新成功。
400 Bad Request 如果指定的任何 traits 无效。可以通过 GET /traits 查询有效的 traits。
404 Not Found 如果由 {uuid} 标识的 resource provider 未找到。
409 Conflict 如果 resource_provider_generation 与服务器端不匹配。
DELETE /resource_providers/{uuid}/traits¶
此 API 用于取消关联特定 resource provider 的所有 traits。
返回的响应将是以下之一
204 No Content 如果删除成功。
404 Not Found 如果由 {uuid} 标识的 resource provider 未找到。
安全影响¶
无
通知影响¶
无
其他最终用户影响¶
将有一组 CLI 命令供用户查询和管理 Traits。
openstack trait list [–starts-with {prefix}] [–name-in {name1},{name2}]
openstack trait remove $TRAIT
openstack trait add $TRAIT
性能影响¶
无
其他部署者影响¶
部署者需要为 OpenStack 不管理的资源(例如计算节点存储使用的共享存储池)设置特性,因为这些特性不会由任何 OpenStack 服务自动完成。
部署者需要开始使用特性,而不是聚合元数据来管理定性信息,以应对聚合元数据即将被弃用的情况。
Placement 服务中的 os-traits 库需要在云环境中保持最新版本,否则来自其他 OpenStack 服务的新的特性将无法被 Placement 服务识别。因此,当升级云环境以包含新的特性时,Placement 服务中的 os-traits 库需要首先升级。
部署者需要在启动 Placement 或发布新的 os-traits 之前运行命令 placement-manage os-trait sync,以确保新的特性被导入到 Placement 数据库中。
开发人员影响¶
只有从事 Scheduler 和/或 Placement API 开发的开发人员才需要了解这些更改。
实现¶
负责人¶
- 主要负责人
Alex Xu <hejie.xu@intel.com>
- 其他贡献者
Cheng, Yingxin <yingxin.cheng@intel.com> Jin, Yuntong <yuntong.jin@intel.com> Tan, Lin <lin.tan@intel.com> Ed Leafe <ed@leafe.com>
工作项¶
为特性添加数据库模式
重构 ResourceClassCache 以供特性使用
添加与特性相关的对象
实现用于管理自定义特性的 API
启用将特性附加到对象中的资源提供程序
实现用于在资源提供程序上设置特性的 API
添加新的命令 placement-manage os-traits sync
依赖项¶
此提案还依赖于 os-traits 库。此提案使用 os-traits 库来确定哪些特性是标准特性,哪些特性不是标准特性。
测试¶
应添加单元测试和功能测试,以确保特性 API 正常工作。
文档影响¶
应添加特性 API 的 API 文档。应添加管理员文档,以说明如何使用特性 API 来管理功能。
参考资料¶
邮件列表讨论:http://lists.openstack.org/pipermail/openstack-dev/2016-July/099032.html
Tags API-WG 指南:https://specs.openstack.org/openstack/api-wg/guidelines/tags.html
简单资源配置:https://anticdent.org/simple-resource-provision.html
使用 ResourceProviderTraits 代替 ResourceClass http://lists.openstack.org/pipermail/openstack-dev/2016-August/100634.html
历史¶
发布名称 |
描述 |
|---|---|
Ocata |
引入 |