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 -> resource:VCPU

  • instances -> server_count

  • ram -> resource:MEMORY_MB

以下现有的配额将仅由配置选项定义,我们不再支持通过 API 进行每个项目或用户的覆盖,我们仅报告配置中定义的现有限制

  • key_pairs(按用户计数)

  • server_groups(每个项目计数)

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

  • metadata_items(按服务器计数)

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

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

  • injected_file_content_bytes

  • injected_file_path_bytes

  • injected_files

提议的变更

本规范有几个部分

  • 强制执行统一限制

  • 无每个用户限制

  • 无不可计数限制

  • 弃用 Nova 的配额 API

  • 操作员工具以协助迁移

强制执行统一限制

我们将支持以下限制

  • server_count

  • resource:<RESOURCE_CLASS>

所有资源类别的使用情况都将使用 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 变为 server_countcores 变为 resource:VCPUram 变为 resource: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.enforce_unified_limits = True 时,它们将不再受支持

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

注意:密钥对仍然会有最大限制,并且该最大限制仍然会针对每个用户强制执行。但是,现在 Nova 中只有一个全局配置值来设置每个用户允许的最大密钥对数量。

无不可计数限制

如上所述,统一限制的重点是 placement 中的实例计数和资源类别的分配。不会将其他限制移动到统一限制,这是与 Train Forum 会议的操作员达成的协议。

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

  • fixed_ips

  • floating_ip

  • security_group_rules

  • networks

剩余的限制主要用于保护数据库,防止恶意用户占用数据库中所有可用空间和/或滥用 API 作为某种存储系统。因此,预计操作员不需要对这些限制进行每个项目的覆盖。因此,我们建议放弃通过 API 更改限制的支持,而是仅允许通过适用于系统所有项目的单个配置选项更改限制。

以下限制将更改为仅通过适用于所有项目的单个配置选项进行设置

  • server metadata

  • injected_files

  • injected_file_content_bytes

  • injected_file_path_bytes

  • key_pairs(按用户计数)

  • server_groups(每个项目计数)

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

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

仅使用全局配置选项意味着

  • 无每个项目覆盖

  • 无每个用户覆盖

  • 无法通过 API 更改限制

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

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

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

  • quota.recheck_quota 将更新描述,说明当 quota.enforce_unified_limits = True 时会丢失哪些功能。

  • quota.floating_ipsquota.fixed_ipsquota.security_groupssecurity_group_rules:仍然弃用,当 quota.enforce_unified_limits = True 时将被忽略。

  • quota.metadata_itemsquota.injected_filesquota.injected_file_content_bytesquota.injected_file_path_lengthquota.server_groupsquota.server_groups_membersquota.key_pairs:这些都将被保留,但将更新描述,说明如果 quota.enforce_unified_limits = True,所有通过 API 的更新都将被忽略。

弃用 Nova 的配额 API

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

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

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

这包括以下 API 资源

  • /limits

  • /os-quota-sets

  • /os-quota-class-sets

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

当您列出不受新系统支持的配额的限制时,它们将显示替换数据库和 API 基于限制的基于配置的限制,例如,对于密钥对,您始终看到基于配置的值,当 quota.enforce_unified_limits = True 时,API 上的任何更新都不会反映回来。

这种方法有一些权衡

  • 代理 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 保持其当前形式,即使它没有报告我们现在支持具有限制的所有类型的资源使用情况,即使它列出了现在只能通过配置文件更改的限制。

  • 当添加分层限制时,/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.enforce_unified_limits = True,Nova 数据库将被忽略,并且仅从 Keystone 访问限制。

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

nova-manage limits remove_db_quota_entries [--project_id project_id]

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

nova 状态命令会警告用户,他们未能从数据库中删除所有配额信息。这将在 quota.enforce_unified_limits 默认为 True 的版本中成为一个错误。

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

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

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

  • quota.driverquota.enforce_unified_limits = True 时被忽略并硬编码为无操作驱动程序。

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

备选方案

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

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

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

数据模型影响

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

REST API 影响

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

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

安全影响

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

通知影响

其他最终用户影响

配额错误在更改前后应相同。

性能影响

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

其他部署者影响

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

开发人员影响

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

升级影响

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

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

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

实现

负责人

主要负责人

johnthetubaguy

其他贡献者

(待定)

功能联络人

功能联络人

melwitt

工作项

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

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

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

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

依赖项

测试

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

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

文档影响

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

参考资料

历史

修订版

发布名称

描述

Victora

引入

Xena

重新提出