统一限制¶
许多 OpenStack 服务都有某种机制来确保单个用户或项目不会占用整个云,并使其他用户无法使用。 这需要每个服务
在项目中对资源编码一些默认限制
在项目/用户限制被覆盖时,跟踪与 project_id / user_id 相关的数据。
提供一个 REST API 来更改这些限制,并实现一个 CLI 来执行相同的操作。
确保存储的项目/用户限制对于有效项目/用户是有效的(通常实际上并没有这样做) [1]
清理已删除项目/用户的孤立数据(通常实际上并没有这样做) [2]
这只是限制定义方面的问题。 一旦定义了限制。
计算已分配的资源。
强制已分配的资源不超过系统中的限制。
由于超过限制而半途而废的请求将被回滚,并且不会留下垃圾数据。
这仅仅适用于扁平的项目结构。 一旦引入了分层项目结构,所有这些操作都可能需要在当前项目、以及考虑祖先、兄弟和子项目的限制和使用情况的上下文中完成。
什么是限制?¶
限制包含以下信息
project_id
API 服务类型(例如,计算、网络、对象存储)
区域
资源类型(例如,ram_mb、vcpus、security-groups)
默认限制(如果没有项目特定的覆盖,则允许的最大资源)
项目特定的限制
user_id(可选,并且希望可以弃用)
注意
当前的一些配额实现今天会对某些类型的资源强制执行 user_id 而不是 project_id。 在这次过渡中,最好能够弃用它。
为了使任何配额计算有效,这些信息必须准确且一致。 如果我们谈论分层配额的概念,这一点就更加重要,因为如果限制中存储的数据违反了系统的基本约束(例如,项目 A 有子项目 B,并且子项目 B 的 vcpu 配额 > A 的 vcpu 配额),那么服务将以错误且复杂的方式计算使用情况和配额的所有逻辑。
这应该放在哪里?¶
当前限制的方法将所有这些数据放在服务级别(即,在 nova 的 API 数据库中)。 服务类型是已知的,因为它就是所讨论的 API 服务器。 资源类型是强制执行的,因为它们在代码中。 默认限制在配置中。 每个项目的允许值在数据库中,并且 project_id/user_id 在 API 上被接受且未经过验证,并且可能不是有效的项目或用户。 这对于分层情况来说变得非常复杂。 最终结果是,许多团队,例如 Nova 团队,推迟了解决这个问题。 [3]
另一种方法是将这些移动到 keystone。 Keystone 是 project_id 和 user_id 信息的权威来源。 它是项目之间任何分层关系的权威来源。 它是 API 服务类型和系统区域的权威机构。
因此,所有需要的都是以通用方式教导 keystone,每个服务类型都有哪些资源类型和默认限制(可能每个区域不同),以及可能存在的项目特定覆盖。
这可以通过新的管理 API 调用来 keystone 设置这些来实现。
一种创建、读取、更新和删除资源类型、默认限制以及相关服务和区域的机制。 这创建了云中所有允许限制的强大定义,以便可以严格验证限制覆盖(不能在应该为
disk时为disc设置限制)。一种创建、读取、更新和删除项目/用户对资源类型的限制覆盖的机制。 这将针对现有的服务类型、区域、项目/用户、预注册的资源类型以及限制是整数进行严格验证。
假设资源类型默认定义将在服务安装/升级期间通过类似于定义服务和端点的方式进行管理命令来发生。
在分层情况下,在创建/更新/删除项目覆盖时,在进行更改之前将强制执行分层限制的规则。 我们希望保证分层限制结构始终保持一致。
限制与使用情况强制执行¶
当我们谈论配额系统时,我们实际上是在谈论两个系统。 一个用于设置和维护限制的系统,即理论上的最大使用量,以及一个用于强制执行使用量不超过限制的系统。 虽然它们是耦合的,但它们是不同的。
在本提案中,Keystone 维护限制。 Keystone 的责任是确保对限制的任何更改与 Keystone 中当前存储的相关限制一致。
各个服务维护和强制执行使用情况。 服务在特定用户请求资源分配时,会检查是否强制执行当前限制。 使用情况反映了消费者对特定资源的实际分配。
鉴于以上情况,以下是一个可能的合法流程。
用户 Jane 在项目 Baobab 中
项目 Baobab 有 20 的默认 CPU 限制
用户 Jane 在项目 Baobab 中分配了 18 个 CPU
管理员 Kelly 将项目 Baobab CPU 限制设置为 10
用户 Jane 无法在项目 Baobab 中分配实例资源,直到她(或项目中的其他人)删除至少 9 个 CPU 以低于新限制
这是大多数管理员想要的行为,因为它允许他们方便地设置未来的策略,并防止这些项目创建任何超出限制的更多资源。 请注意,今天有些项目会阻止将限制设置为低于现有分配值。 此 API 行为将不会在此新系统中得到尊重。 [4]
项目中的用户可以通过减少项目的使用量到有剩余空间的地方来自行解决此问题。 如果他们不这样做,那么在某个时候,管理员可以更积极地删除这些内容。
项目之间的常见行为¶
当我们进入 N 级项目层次结构时,这将变得很复杂。 对不同配额模型进行大致建模 [5] 表明,这有很多不同的建模方式。
因此,假设我们需要一个公共库,既要检查对现有层次结构的限制更改是否有效,又要检查资源分配不超过配额。 虽然有效的限制检查将仅在 keystone 中进行,并且配额检查仅在项目中进行,但在公共代码中拥有相同的算法将确保对 Garbutt 模型 的限制更改与对 Garbutt 模型 的配额更改一致。
确切的接口需要在实施过程中敲定。
访问限制¶
限制信息应通过 REST API 调用访问。 这可能是极其可缓存的信息。 仅通过 Keystone API 进行的对限制的显式更新才会使此信息失效。 Keystone 应该能够为该信息实现高效的 HTTP 缓存。
项目中的用户将能够查看所有项目限制以及子项目中的限制。 根据使用的配额系统模型,他们也可能能够查看更高层次的层次结构(尤其是在他们的分配只有在高层次的分配上下文中才有意义的情况下) [5]。 应该有一个自助服务的原则,即项目中的用户应该始终能够弄清楚为什么该项目超出了配额。
服务/管理用户将对所有项目具有此读取访问权限。
每次需要配额计算时,将获取此信息。 强制执行配额的服务应始终假设它正在调用 keystone 以获取限制,即使这只是从 keystone 获得快速的 304 HTTP NOT MODIFIED。
超出范围的项目¶
在 Pike PTG 的限制讨论期间,还对另一种类型的系统限制感兴趣,即确保健康环境的速率限制。 Swift 团队表示他们对项目级别限制不感兴趣,而更感兴趣的是限制以确保集群的健康。 这些指标中的大多数都包含一个时间组件(例如 iops)。
虽然这是一个非常有趣的问题,并且显然是关于公平性和集群健康的未来需求,但当我们谈论本工作中的限制时,我们只谈论固定、整数数量的资源。
具体的后续步骤¶
以下是我对前进道路的最佳估计。
Pike
获得对 Keystone 拥有限制的一般协议
定义 keystone 获取/设置限制接口(单独的规范)
创建 os-quotas 库,其中包含平面和严格的帐户分层限制
实施 Keystone 获取/设置限制接口
Queens
将统一限制支持连接到一个或多个服务项目(Nova 率先采用)。 默认情况下开始使用,包括 API 切入(很多错误将会出现,我们应该考虑整个周期)
Revelstoke
将其余服务项目转换为新的限制模型。
在 os-quotas 库中以实验方式实施超额预订算法。
参考资料¶
这些是关于分层限制和配额的现有信息来源。 仅供参考,不意味着这些也将实施。
现有的 Keystone 规范 - https://review.openstack.org/#/c/363765/。
这是一个较低级别的规范(带有 POC 代码),其中包括将限制信息放在 Token 中。 过度使用 Token 是一个主要问题。 Token 按照定义是陈旧的信息,并且可能很长,因此管理员更改限制时不知道系统何时开始强制执行它们。 Token 膨胀也是依赖于 RPC 的具有 worker daemons 的项目的关注点,因为它意味着 RPC 总线上的负载更高。
该规范在亚特兰大 PTG 上提出,是上述协议的精神基础。
提出的 Nova 配额规范 - https://review.openstack.org/#/c/429678。
这是一个概述规范,其中包括将限制放在 keystone 中的理由。 配额类的使用。 一些关于超额预订的示例。 此规范的元素已纳入此统一规范。 Nova 规范被认为已失效。
邮件列表线程 - http://lists.openstack.org/pipermail/openstack-dev/2017-March/113099.html
脚注