Nova 中的统一限制集成

https://blueprints.launchpad.net/nova/+spec/unified-limits-nova

该规范是关于采用 Keystone 的统一限制。包括使用 oslo.limit 来强制在 Keystone 中设置的 Nova 相关限制。

本规范建议在至少一个周期内并行使用统一限制和现有的配额系统,以便操作员可以从通过 Nova 设置配额过渡到通过 Keystone 设置与 Nova API 端点相关的限制。

所有每个用户的配额支持都将被放弃,转而采用统一限制支持的分层强制执行。

只有服务器数量限制以及在 flavor 中请求的资源类资源的限制将受统一限制的支持。所有其他现有的配额将不再支持每个项目或每个用户的限制。

鉴于这种以放置为重点的方法,我们将依赖于此处完成的工作:https://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html

问题描述

虽然在简化 Nova 中配额实现方面已经做了很多工作,但当前系统对操作员仍然存在一些主要的可用性问题

  • 我们没有在整个 OpenStack 中对限制/配额层次结构提供一致的支持

  • 要求操作员在每个服务(例如 Cinder、Nova、Neutron 等)中单独设置限制

  • Nova 现有的配额与 Ironic 配合不好

  • 不支持自定义资源类配额(包括“每个 flavor”配额)

  • 当 API 定义的配额限制覆盖配置中所做的任何更改时,会产生混淆

  • 某些 Nova 配额与资源消耗无关,导致混淆

过渡到使用 Keystone 的统一限制,通过 oslo.limit,将有助于解决这些问题。

有关 Keystone 中统一限制的更多详细信息,请参见:https://docs.openstack.org/keystone/stein/admin/identity-unified-limits.html

用例

推动这项工作的主要用例是

  • API 用户试图了解为什么收到“超出配额”错误

  • 操作员从现有限制迁移到统一限制

  • 操作员通过 Keystone 为给定的端点设置默认限制。请注意,即使使用共享的 Keystone,每个区域也可以有不同的限制。

  • 操作员通过 Keystone 为给定的项目设置特定限制

  • 操作员通过非扁平强制执行(即正式称为分层配额的功能)定义一组项目的限制

我们将专注于添加与以下内容相关的统一限制

  • 服务器总数

  • flavor 中请求的每种资源类的数量

请注意,这包括 DISK_GB 之类的内容,这些内容今天不受支持,以及在额外规格中请求的自定义资源类资源(例如 Ironic flavor)。

现在,我们将查看通过 API 公开的所有配额以及在使用统一限制时它们映射到的内容:https://docs.openstack.org/api-ref/compute/?expanded=show-a-quota-detail#show-a-quota

以下现有的配额类型将移至统一限制,允许通过统一限制系统对每个端点设置默认值和每个项目的覆盖(以及分层限制)

  • cores -> class:VCPU

  • instances -> servers

  • ram -> class:MEMORY_MB

以下现有的配额将仅由统一限制系统中的注册(默认)限制定义,我们不再支持通过 API 进行的每个项目或用户的覆盖,我们只是报告 Keystone 中定义的现有限制。

  • key_pairs(按用户计算) -> server_key_pairs

  • server_groups(每个项目计数)

  • server_group_members(每个服务器组计数)

  • metadata_items(按服务器计算) -> server_metadata_items

以上纯粹是为了保护数据库膨胀(即阻止拒绝服务攻击,该攻击会填满数据库)。它们类似于可以附加到服务器的标签数量的硬编码限制。

虽然在 API 中已弃用,但我们将以与上述配额相同的方式处理这些配额,即它们现在将通过注册限制设置,且无法进行每个项目的覆盖。

  • injected_file_content_bytes -> server_injected_file_content_bytes

  • injected_file_path_length -> server_injected_file_path_bytes

  • injected_files -> server_injected_files

提议的变更

本规范有几个部分

  • 强制执行统一限制

  • 无每个用户限制

  • 无不可计数限制

  • 弃用 Nova 的配额 API

  • 操作员工具以协助迁移

强制执行统一限制

我们将支持以下限制

  • servers

  • class:<RESOURCE_CLASS>

  • server_group_members

  • server_groups

  • server_injected_files

  • server_injected_file_content_bytes

  • server_injected_file_path_bytes

  • server_key_pairs

  • server_metadata_items

所有资源类别的使用情况都将使用 placement 进行计算,但服务器数量将使用实例映射。只有在完成待删除数据迁移后才能实现这一点。由于没有基于用户的配额,我们不需要 user_id 迁移。如果操作员在完成迁移之前尝试使用统一限制,代码将阻止所有新使用,直到完成迁移。预计在默认启用统一限制之前,将添加一个阻塞迁移。有关此数据迁移的更多详细信息,请参阅现有配额代码中的此点:https://github.com/openstack/nova/blob/0d3aeb0287a0619695c9b9e17c2dec49099876a5/nova/quota.py#L1053

为了允许新系统与旧配额系统共存,我们使用现有的配额驱动程序系统。默认设置将保持不变,但操作员可以通过以下方式选择加入新系统

  • [quota]driver=nova.quota.UnifiedLimitsDriver

有关过渡的更多详细信息,请参见此规范的更新部分。请注意,新的统一限制代码将对通过 placement 计数使用量具有硬依赖性;因此,它将忽略 CONF.quota.count_usage_from_placement 的值。

查看现有的配额,instances 变为 serverscores 变为 class:VCPUram 变为 class:MEMORY_MB

这项工作将重用许多新的逻辑来查询 placement 以获取资源使用量,并使用实例映射表来计算此规范中添加的服务器:https://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html

要确定服务器将声明哪些资源,我们重用此代码从任何给定的 flavor 中提取资源:https://github.com/openstack/nova/blob/2e85453879533af0b4d0e1178797d26f026a9423/nova/scheduler/utils.py#L387

对于服务器构建,我们使用上述函数获取请求 flavor 的资源类资源量。然后,这将使用 olso.limit 进行检查,以确保额外的使用不会使关联的项目超出其任何限制。oslo.limit 库负责使用我们提供的回调来计算所有当前资源使用量,该回调使用 placement 来计算当前资源使用量。

一旦资源在 placement 中被声明,我们选择性地重新检查限制,以查看我们是否与其他服务器构建争夺最后一点可用配额。唯一的改变是使用 oslo.limit 进行重新检查。也就是说,我们仍然会尊重配置:quota.recheck_quota 请注意:我们首先在 nova-api 中检查限制,然后在 placement 中成功分配资源后在 nova-conductor 中重新检查。

resize 的情况类似。但是,在这种情况下,我们检查是否可以同时声明新 flavor 和旧 flavor 的资源。请注意,这与当前配额系统即使通过 placement 计数使用量也大不相同。

有关与 placement 计数相关的语义变化的更多详细信息,请参见:https://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html

请注意,baremetal 实例不再声明任何 VCPU 或 MEMORY_MB 资源。使用这种方法,可以使用 flavor 中请求的自定义资源类资源来限制 baremetal 实例。

如果我们选择允许来自基于 hypervisor 的计算节点的其他自定义库存条目,例如 {‘CUSTOM_GPU_V100’:1},我们也将能够对这些资源应用配额。

oslo.limits 库可能会添加其他配置选项。特别是,操作员需要向 oslo.limit 指定 Nova API 的端点 uuid,以便它知道哪些统一限制适用于每个 Nova API 服务。

无每个用户限制

Nova 当前支持“每个用户”限制。当:[quota]driver=nova.quota.UnifiedLimitsDriver 时,它们将不再受支持。

没有迁移工具的计划,但是预计需要类似模型的用户可以测试使用统一限制支持的分层限制,并反馈可以帮助其他人迁移的内容。

注意:密钥对仍然具有最大限制,并且该最大限制仍然按用户强制执行。但是,现在 Keystone 中只有一个默认注册限制值来设置每个用户允许的最大密钥对数量。

无不可计数限制

如上所述,统一限制的重点是 placement 中的实例计数和资源类别分配。

nova-network 有特定限制。这些都已经弃用了。没有计划在启用统一限制时支持这些限制

  • fixed_ips

  • floating_ip

  • security_group_rules

  • networks

其余限制主要用于保护数据库,防止恶意用户占用数据库中的所有可用空间和/或滥用 API 作为某种存储系统。因此,预计操作员不需要对这些限制进行每个项目的覆盖。

以下限制将更改为仅通过统一限制系统中的注册限制进行设置,该系统平等地适用于所有项目

  • server_metadata_items

  • server_injected_files

  • server_injected_file_content_bytes

  • server_injected_file_path_bytes

  • server_key_pairs(按用户计算)

  • server_groups(每个项目计数)

  • server_group_members(每个服务器组计数)

请注意,server_group_members 当前按用户计数,但坦率地说,这非常令人困惑,因此我们上面建议更简单的限制服务器在服务器组中。这似乎与删除所有其他项目拥有的资源的每个用户限制一致。

仅使用注册限制意味着

  • 无每个项目覆盖

  • 无每个用户覆盖

这些是可以在各种 Nova 数据库中存储的数据量的限制。无法显示项目对这些限制的使用情况,这进一步证明了这些限制与统一限制设计用于的资源限制不同。

当前我们对所有这些配额都尊重 quota.recheck_quota。这增加了显著的代码复杂性,但是大多数用户从不达到这些限制,并且它们都是非常宽松的限制。因此,当我们过渡到所有这些配额的单个默认注册限制值时,我们也将停止进行任何重新检查。

总而言之,对配置选项的影响是

  • quota.recheck_quota 将更新描述,说明在 [quota]driver=nova.quota.UnifiedLimitsDriver 时会丢失哪些功能。

  • quota.floating_ipsquota.fixed_ipsquota.security_groupssecurity_group_rules:仍然已弃用,并且在 [quota]driver=nova.quota.UnifiedLimitsDriver 时将被忽略。

  • quota.metadata_itemsquota.injected_filesquota.injected_file_content_bytesquota.injected_file_path_lengthquota.server_groupsquota.server_group_membersquota.key_pairs:这些都将被保留,但描述将被更新,以说明如果 [quota]driver=nova.quota.UnifiedLimitsDriver,则所有通过 API 的更新都将被忽略。

限制的执行

为了保持一致性,所有配额限制都将使用 oslo.limit Enforcer.enforce API 进行强制执行。在这种模式下,将初始化一个 Enforcer 对象,该对象将回调以计算正在强制执行的资源的现有使用情况。但是,某些资源仅从 Nova API 请求有效负载中计算,这些资源是在其中指定的。我们称这些资源限制为“API 限制”

  • server_metadata_items

  • server_injected_files

  • server_injected_file_content_bytes

  • server_injected_file_path_bytes

例如,当在 Nova API 中收到服务器创建请求并且元数据项包含在请求中时,我们将比较请求的元数据项数量与 server_metadata_items 的配额限制,并且我们不会在数据库或 placement 中计算任何内容作为使用情况。oslo.limit 配额限制强制执行涉及一个限制、一个增量和一个当前使用情况。对于 API 限制,我们只有限制和增量。在这种情况下,当前使用情况始终为零。因此,我们使用始终返回零使用情况的回调来初始化 API 限制的 Enforcer 对象。这样,oslo.limit 就可以仅使用配额限制和提供的增量来正确执行强制执行。

注意

使用统一限制,VCPU 和 PCPU 配额使用情况的行为将更改为独立计算 VCPU 资源和 PCPU 资源,这与它们在 placement 服务中的表示方式一致。

旧版配额行为将 PCPU 视为 VCPU 并返回 VCPU + PCPU 使用量的总和作为 VCPU 的使用情况计数。将提供一个配置选项 [workarounds]unified_limits_count_pcpu_as_vcpu,供需要旧版配额使用行为(其中 VCPU = VCPU + PCPU)的操作员使用。请注意,如果 class:PCPU 在 flavor 中明确指定,则预计它将拥有自己的统一限制注册,并且即使将此选项设置为 True,PCPU 使用量也不会合并到 VCPU 使用量中。

弃用 Nova 的配额 API

要查询和设置限制,应使用 Keystone 的 API。要查询用户的用量,应使用 Placement API,假设 placement 乐于更改默认策略以允许用户查询其用量。

唯一的例外是服务器计数当前无法通过 Placement 检查。当 placement 实现消费者记录或类似功能时,所有用量都可以通过 Placement 查询。为了避免使用代理 API,用户可以执行服务器列表 API 并计算返回的服务器数量。

[quota]driver=nova.quota.UnifiedLimitsDriver 时,将尽最大努力使旧版微版本工作,方法是根据需要将 API 调用代理到 Keystone 和 Placement。当 [quota]driver=nova.quota.UnifiedLimitsDriver 时,将不会访问任何与配额相关的数据库表。

这包括以下 API 资源

  • /limits

  • /os-quota-sets

  • /os-quota-class-sets

现有的设置配额的工具应继续运行,只要它仅更改与实例、核心和内存相关的配额即可。更改任何其他配额的请求将被静默忽略。例如,这应该允许 Horizon 在过渡期间正常运行。

这种方法有一些权衡

  • 代理 API 很糟糕,但 horizon 必须继续工作,因此所有当前操作员围绕这些现有 API 的工具。

  • 我们不需要微版本来启用/禁用此配额 API 的代理,因为它实际上并没有更改 API。

  • 在未来的版本中,当统一限制成为默认值时,我们应该弃用 API /os-quota-sets/os-quota-class-sets,并告诉用户与 Keystone API 交互。基于 API 的发现 Nova 正在强制执行 Keystone 中设置的限制的时间留待未来的规范。

  • 预计上述 API 弃用将遵循 nova-network 代理 API 使用的模式,即 API 在新的微版本中返回 404,但在旧的微版本中继续工作。在更遥远的未来,API 可能会通过返回 410 错误来删除。

  • 拒绝我们先前能够设置的配额的更新将是行为上的破坏性更改,并且需要一个微版本。如果我们不打算弃用 API 以支持调用 Keystone,那么添加一个新的 API 微版本,该版本为不受支持的配额返回 BadRequest 将是一个不错的补充。

  • 理想情况下,我们还应该弃用 /limits,以支持一个跨项目一致的方向,该方向了解扁平和分层限制执行。但是,我们尚未就采取什么方向达成共识。对于此规范,我们保留 /limits 的当前形式,即使它未报告我们现在支持具有限制的所有类型的资源使用情况,并且即使它列出了现在只能通过注册的 Keystone 统一限制进行更改的限制。

  • 当添加分层限制时,/limits 中的每项目使用信息不会提及任何父限制。因此,配额 API 可能会声称资源可用,但您将无法构建任何新资源。用户可以采取什么行动来构建这些新资源尚不清楚。操作员可以通过不超配配额来避免这种混淆。我们可以扩展 API 以包含一个布尔值,指示是否在父项目中超出限制,因此即使自己的使用量未超出自己的限制,用户也无法消耗更多资源。我们可以考虑扩展 API 以包含整个树的用量

迁移到统一限制

所有用户迁移到统一限制正在分三个阶段进行

  • 启用统一限制作为选项,并提供从现有配额迁移的路径

  • 使统一限制成为默认值,弃用现有的配额系统

  • 删除现有的配额系统

为了帮助过渡,我们需要操作员工具来

  • 为 Keystone 中的每个 Nova 端点在 Keystone 中设置注册限制,基于数据库和/或配置中的当前限制

  • 将 Nova 中设置的每个项目配额复制到 Keystone 统一限制

  • 操作员确认统一限制对他们有效

  • 从数据库中删除所有配额信息,以表明操作员已完成过渡

  • 升级状态检查,以检查配额数据库表中是否没有剩余数据

请注意,将限制设置为 Keystone 将通过传递给 keystone-manage 的文件进行,这允许快速转发升级,在从 Nova 到 Keystone 迁移限制期间没有可用的 API。

将有一个新工具来设置 Keystone 中的注册限制。它将从 Nova 数据库和配置中读取,并生成一个文件。该文件可以由 keystone-manage 使用来注册 Keystone 中的当前端点默认值。

nova-manage limits generate_registered_limits --endpoint <endpoint-uuid>

以下工具将生成需要添加到 Keystone 中每个项目的统一限制覆盖(如果有)。同样,这也生成一个传递给 keystone-manage 以更新 keystone 的文件

nova-manage limits generate_project_limits [--project_id <project_id>]

一旦操作员设置 [quota]driver=nova.quota.UnifiedLimitsDriver,Nova DB 将被忽略,并且限制仅从 Keystone 访问。

为了完成迁移,有一个操作可以删除所有与配额覆盖相关的数据库条目。该工具仅在 [quota]driver=nova.quota.UnifiedLimitsDriver 时有效。它还会删除与每个项目关联的所有任何用户限制。

nova-manage limits remove_db_quota_entries [--project_id project_id]

请注意,最后两个工具允许操作员逐项目迭代,以限制正在运行的系统上的负载。如果这些工具在正在运行的系统上使用,建议操作员在过渡期间不要通过 API 更改配额。

nova status 命令将警告用户,这些用户未能从 DB 中删除所有配额信息。当 [quota]driver 默认为 nova.quota.UnifiedLimitsDriver 时,这将成为一个错误。

值得注意的是,Nova 数据库可能包含已在 keystone 中删除的项目条目。因此,建议从 keystone 获取活动项目列表,并仅为这些特定项目生成_project_limits。

此过渡使几个配置选项变得冗余,特别是以下选项将在统一限制打开后默认弃用

  • quota.instancesquota.coresquota.ram:弃用所有这些,因为限制现在来自统一限制的 keystone,如果没有 keystone 中的限制,则默认为无限。

将保留 quota.recheck_quota 设置,并将在与统一限制相同的方式中使用它,以避免在同时构建多个实例时出现竞争条件。

备选方案

理想情况下,我们不会添加任何更多的代理 API,但是,操作员在 Train Forum 会议上进行了反击,要求他们的工具在过渡期间继续工作。没有操作员报告使用实例、核心和内存限制以外的限制。

我们可以独立实现分层配额,而不采用统一限制。

我们可以限制我们限制的资源类型,但是很难过渡到支持不同类型的资源限制,以一种清晰且可互操作的方式。

数据模型影响

请参阅升级,由于同时具有旧的和新的配额系统,Victora 中没有更改。一旦我们删除旧的配额系统,我们就可以删除所有与配额相关的数据库表。

REST API 影响

[quota]driver=nova.quota.UnifiedLimitsDriver 时,Nova 将在可能的情况下将请求代理到 Keystone 的统一限制 API,目标是使 horizon 在过渡期间正常工作。

一旦使用统一限制,操作员应移动到使用 Keystone 的统一限制 API 来设置和查询限制。应通过 Placement 和服务器 API 查询使用信息。

安全影响

删除某些限制的配额重新检查略微降低了提供的保护,但实际上它鼓励了适当的 API 速率限制作为替代保护。

通知影响

其他最终用户影响

使用统一限制的配额错误将使用 oslo.limit 在此更改后的标准且一致的错误消息。

性能影响

可以使用分层配额来获得更复杂的配额计数,但该实现委托给 oslo.limit。

其他部署者影响

有几个工具可以帮助简化上述统一限制的过渡。尽管预计使用该功能将有助于告知最终方向。

开发人员影响

在过渡期间,将有几个系统需要维护。但这避免了长期维护复杂的层次配额代码的需要,同时仍然可以获得优势,例如能够清理 API 策略。

升级影响

为了获得最佳体验,操作员需要开始使用通过 Keystone 的统一限制 API。用户应该开始从 Placement 查询使用情况。

现有配额系统与统一限制之间的过渡在拟议的解决方案部分中详细说明。

预计 oslo.limit 将限制可以使用的 Keystone 版本为 Queens 及更高版本,预计这不会影响大多数用户。

实现

负责人

主要负责人

johnthetubaguy

其他贡献者

melwitt

功能联络人

功能联络人

melwitt

工作项

  • 添加对 oslo_limits 的调用,由配置保护以启用它

  • 当启用统一限制配额时,将配额 API 代理到 Keystone

  • 添加工具将默认和租户限制从 Nova 迁移到 Keystone

  • 升级检查以确保使用上述工具

依赖项

测试

Grenade 测试,运行配额设置的迁移(在添加一些配额后)。

功能测试,以确保正确强制执行基于统一限制的配额。

文档影响

在记录来自 placement 的配额使用情况的工作基础上,我们应该描述新系统如何运行。管理员指南需要详细说明如何平稳迁移到统一限制。

参考资料

历史

修订版

发布名称

描述

Ussuri

引入

Victoria

重新提出

Xena

重新提出

瑜伽

重新提出