嵌套配额驱动API

https://blueprints.launchpad.net/nova/+spec/nested-quota-driver-api

嵌套配额驱动程序将使 OpenStack 能够强制执行嵌套项目中的配额。

https://specs.openstack.org/openstack/keystone-specs/specs/juno/hierarchical_multitenancy.html

问题描述

OpenStack 正在朝着支持项目层级所有权的方向发展。在这方面,Keystone 将改变 Openstack 的组织结构,创建嵌套项目

Nova 中现有的配额驱动程序,名为 DbQuotaDriver,在项目和项目用户级别强制执行配额非常有用,前提是所有项目都在同一级别(即,层级级别不能大于 1)。

建议开发一个新的配额驱动程序,名为 NestedQuotaDriver,通过扩展现有的 DbQuotaDriver 来实现,这将允许在 Openstack 中的嵌套项目中强制执行配额。嵌套项目具有层级结构,每个项目可能包含用户和项目(可以称为子项目)。

用户可以在每个项目内拥有不同的角色:普通用户可以使用项目的资源。项目管理员,例如,可以是一个除了被允许创建子项目、将资源配额分配给这些子项目以及将项目管理员角色分配给子项目的各个用户之外,还具有其他权限的用户。根项目的资源配额只能由根项目的管理员设置。用户角色可以设置为继承,如果设置了继承,则项目的管理员会自动成为该项目下所有项目的管理员。

用例

参与者

  • Martha - 云管理员(即角色:cloud-admin) of ProductionIT

  • George - 经理(即角色:project-admin) of Project CMS

  • John - 经理(即角色:project-admin) of Project ATLAS

  • Peter - 经理(即角色:project-admin) of Project Operations

  • Sam - 经理(即角色:project-admin) of Project Services

  • Paul - 经理(即角色:project-admin) of Project Computing

  • Jim - 经理(即角色:project-admin) of Project Visualisation

项目的嵌套结构如下。

{
   ProductionIT: {
                  CMS  : {
                            Computing,
                            Visualisation
                        },
                  ATLAS: {
                            Operations,
                            Services
                      }
               }
 }

Martha 是一个基础设施提供商,为 George 的 Project CMS 和 John 的 Project ATLAS 提供云服务。CMS 在其下方有两个子项目,名为 Visualisation 和 Computing,分别由 Jim 和 Paul 管理。ATLAS 有两个子项目,名为 Services 和 Operations,分别由 Sam 和 Peter 管理。

  1. Martha 需要能够设置 CMS 和 ATLAS 的配额,并管理整个项目(包括根项目 ProductionIT)的配额。

  2. George 应该能够更新 Visualisation 和 Computing 的配额。

  3. George 应该能够查看 CMS、Visualisation 和 Computing 的配额。

  4. George 不应该能够更新 CMS 的配额,尽管他是它的经理。只有 Martha 才能做到。

  5. George 不应该能够查看 ATLAS 的配额。只有 John 和 Martha 才能做到。

  6. Jim,Visualisation 的经理,不应该能够查看 CMS 的配额。Jim 应该能够仅查看 Visualisation 的配额,以及在 Visualisation 下创建的任何子项目的配额。

  7. 关于不同项目中实例数量的配额信息如下:

名称

hard_limit

used

reserved

ProductionIT

1000

100

100

CMS

300

25

15

Computing

100

50

50

Visualisation

150

25

25

ATLAS

400

25

25

Services

100

25

25

Computing

200

50

50

  1. 假设 Martha(根项目或云管理员的管理员)将 CMS 中实例的 hard_limit 增加到 400

  2. 假设 Martha 将 CMS 中实例的 hard_limit 增加到 500

  3. 假设 Martha 删除 CMS 的配额

  4. 假设 Martha 将 CMS 中实例的 hard_limit 减少到 350

  5. 假设 Martha 将 CMS 中实例的 hard_limit 减少到 200

  6. 假设 George(CMS 的经理)将 CMS 中实例的 hard_limit 增加到 400

  7. 假设 George 尝试查看 ATLAS 的配额

  8. 假设 Jim 尝试将 CMS 中实例的 hard_limit 减少到 400。

  9. 假设 Martha 尝试将 ProductionIT 中实例的 hard_limit 增加到 2000。

  10. 假设 Martha 删除 Visualisation 的配额。

  11. 假设 Martha 删除项目 Visualisation。

  1. 假设公司不希望使用嵌套结构,并希望重构为只有四个项目,即 Visualisation、Computing、Services 和 Operations。

项目优先级

提议的变更

  1. 任何新创建项目的默认配额(硬限制)设置为 0。零的默认值确保在多个项目由管理员同时创建时数据的一致性。假设 RAM 的默认值为 1024,A 是根项目。并且管理员正在创建 B,A 的子项目,以及另一个管理员正在创建 C,同样是 A 的子项目。现在,B 和 C 的 RAM 默认值的总和超过了 A 的默认值。为了避免这种情况,默认配额设置为零。

  2. 项目只有在将配额设置为非零值后才能创建 VM(因为默认值为 0)。创建新项目后,必须通过 Nova API 调用显式设置配额值,以确保可用配额,然后才能在项目中声明资源。

  3. 在根项目中具有“cloud-admin”角色的用户,并且具有继承的角色被称为 Cloud-Admin,允许在整个层级结构中执行配额操作,包括顶级项目。Cloud-Admin 是唯一允许设置树中根项目配额的用户。

  4. 项目中具有“project-admin”角色的用户被允许对其子项目和层级中的用户进行配额操作。如果在 Keystone 中将项目的“project-admin”角色设置为可继承,则具有此角色的用户被允许从其直接子项目到项目层级下最后一个项目/用户的配额操作。

    注意:像“cloud-admin”和“project-admin”这样的角色不是硬编码的。它在本 BP 中仅用于演示目的。

  5. 一个项目的总资源消耗分为

    1. 已用配额 - VM 在项目中使用的资源。

      (不包括子项目)

    2. 保留配额 - 项目为将来保留的资源

    3. 包括后代。

      分配配额 - 立即子项目的配额 hard_limit 值之和

  6. 项目内可用的 free 配额计算如下

    free quota = hard_limit - (used + reserved + allocated)

    空闲配额不存储在数据库中;它是为每个项目动态计算的。

  7. 只有在父项目有足够的空闲配额可用时,才允许增加项目的配额值。如果父项目有空闲配额可用,则配额更新操作将导致项目 hard_limit 值及其父项目的 allocated 值更新。因此,应该注意的是,更新项目的配额需要令牌在父级别作用域内。

    • 项目层级为 A->B->C(A 是根项目)

      名称

      hard_limit

      used

      reserved

      allocated

      A

      100

      0

      50

      50

      B

      50

      20

      0

      10

      C

      10

      10

      0

      0

      项目的空闲配额将是

      A:Free Quota = 100 {A:hard_limit} - ( 0 {A:used} + 0 {A:reserved} +

      50 {A: 分配给 B})

      A: 剩余配额 = 50

      B:Free Quota = 50 {B:hard_limit} - ( 20 {B:used} + 0 {B:reserved} +

      10 {B: 分配给 C})

      B: 剩余配额 = 20

      C:Free Quota = 10 {C:hard_limit} - ( 10 {C:used} + 0 {C:reserved} +

      0 {C: 分配})

      C: 剩余配额 = 0

      如果项目 C hard_limit 增加 10,则此更改将导致

      名称

      hard_limit

      used

      reserved

      allocated

      A

      100

      0

      50

      50

      B

      50

      20

      0

      20

      C

      10

      10

      0

      0

      如果项目 C hard_limit 需要进一步增加 20,则此操作将被中止,因为其父项目即项目 B 的可用空闲配额仅为 10。因此,A 的项目管理员应首先增加项目 B 的 hard_limit(使用作用域到项目 A 的令牌,因为在 A 级别执行操作),然后增加项目 C 的 hard_limit(同样作用域到项目 B 的令牌)。

      请考虑上述用例。各种项目的配额信息,包括分配的配额如下,

      ProductionIT : hard_limit=1000, used=100, reserved=100, allocated=700
      CMS : hard_limit=300, used=25, reserved=15, allocated=250
      Computing : hard_limit=100, used=50, reserved=50, allocated=0
      Visualisation : hard_limit=150, used=25, reserved=25, allocated=0
      ATLAS : hard_limit=400, used=25, reserved=25, allocated=300
      Services : hard_limit=100, used=25, reserved=25, allocated=0
      Computing : hard_limit=200, used=50, reserved=50, allocated=0
      • 假设 Martha 尝试将 CMS 中的实例配额增加到 400。由于 Martha 具有 ProductionIT 中管理员的角色,而 ProductionIT 是 CMS 的父级,因此她可以增加 CMS 的配额,前提是令牌限定为 ProductionIT。这是必需的,因为在 CMS 中增加配额限制会导致 ProductionIT 中剩余配额相应减少。

        使用上述公式,ProductionIT 的剩余配额为:

        ProductionIT:hard_limit 减去
        ProductionIT:已用 减去
        ProductionIT:保留 减去
        ProductionIT:分配 =
        1000 - 100 - 100 - (300 + 400) = 100.

        因此 CMS 的最大允许配额为 300 + 100 = 400

        注意:ProductionIT:allocated = CMS:hard_limit + ATLAS:hard_limit

        CMS 的最小配额为,CMS:used + CMS:reserved + CMS:allocated = 25 + 15 + 250 = 290

        注意: CMS:allocated = Visualisation:hard_limit + Computing:hard_limit

        由于 290 <= 400 <=400,配额操作将成功。更新后,ProductionIT 和 CMS 的配额如下:

        ProductionIT : hard_limit=1000, used=100, reserved=100, allocated=800
        CMS : hard_limit=400, used=25, reserved=15, allocated=250
      • 假设 Martha 尝试将 CMS 中的实例配额增加到 500。那么它将不成功,因为 CMS 可用的最大配额是 400。

      • 假设 George,CMS 的经理,将 CMS 中的实例配额增加到 400,那么它将不成功,因为 George 没有 ProductionIT 的管理员或项目管理员角色,而 ProductionIT 是 CMS 的父级。

      • 假设 Martha 尝试将 ProductionIT 的配额增加到 2000,那么它将成功。由于 ProductionIT 是根项目,因此 ProductionIT 的最大配额没有限制。而且,Martha 具有 ProductionIT 中的管理员角色。

  8. 只有在项目有可用空闲配额的情况下,才允许减少项目的配额值,空闲配额 > 0(零),因此配额值的最大减少限制为空闲配额值。

  • 项目层级为 A->B->C,其中 A 是根项目

    项目 A(hard_limit = 100,used = 0,reserved = 0,allocated = 50)项目 B(hard_limit = 50,used = 20,reserved = 0,allocated = 10)项目 C(hard_limit = 10,used = 10,reserved = 0,allocated = 0)

    如果项目 B hard_limit 减少 10,则此更改将导致项目 A(hard_limit = 100,used = 0,reserved = 0,allocated = 40)项目 B(hard_limit = 40,used = 20,reserved = 0,allocated = 10)项目 C(hard_limit = 10,used = 10,reserved = 0,allocated = 0)

    如果项目 B 的 hard_limit 需要进一步减少 20,则此操作将被中止,因为项目 B 的空闲配额应大于或等于(20+0+10)。

    • 假设 Martha 尝试将 CMS 中的实例配额减少到 350,它将成功,因为 CMS 所需的最小配额是 290。

    • 假设 Martha 尝试将 CMS 的实例配额减少到 200,那么它将不成功,因为它违反了最小配额标准。

  1. 删除配额等同于将配额更新为零值。如果分配的配额为零,它将成功。身份验证逻辑与更新逻辑相同。

  • 假设 Martha 尝试删除 CMS 的配额,那么它将不成功,因为 CMS 的分配配额不为零。

  • 假设 Martha 删除 Visualisation 的配额,那么它将成功,因为 Visualisation 的分配配额为零。删除的 Visualisation 配额将添加到 CMS 的 free_quota。CMS 的配额将为 CMS :hard_limit=300, used=25, reserved=15, allocated=100。

  • 假设 Martha 删除项目 Visualisation,Visualisation 的配额应释放给其父级 CMS。但在当前的设置中,Nova 不会知道项目何时从 keystone 中删除。这是因为 Keystone 服务与包括 nova 在内的其他服务没有同步。因此,即使项目已从 keystone 中删除,配额信息仍然保留在 nova 数据库中。这个问题存在于 OpenStack 当前的运行模型中。一旦 Keystone 服务同步,这将自动得到处理。目前,Martha 必须在删除该项目之前删除 Visualisation 的配额。Keystone 与其他 OpenStack 服务的同步超出了此蓝图的范围。

  1. 假设 George,CMS 的经理,尝试查看 ATLAS 的配额,它将不成功,因为 George 在 ATLAS 或 ATLAS 的父级中没有角色。

  2. 假设 Jim,Visualisation 的经理,尝试更新 CMS 的配额,它将不成功,因为他没有 CMS 的父级的管理员或项目管理员角色。

  3. 假设组织不希望使用嵌套结构,并希望只有四个项目,即 Visualisation、Computing、Services 和 Operations,那么设置将像当前设置一样,只有一个级别的项目。所有四个项目都将被视为根项目。

备选方案

对于项目的配额更新和删除操作,令牌可以限定到项目本身,而不是其父项目。 但是,我们避免这样做,因为子项目的配额更改会导致父项目的可用配额发生变化。 因此,根据此 bp,对于配额更新和删除操作,令牌限定到父项目。

数据模型影响

在表 quotas 中创建一个名为 allocated 的新列,默认值为 0。

REST API 影响

安全影响

通知影响

其他最终用户影响

性能影响

其他部署者影响

开发人员影响

实现

负责人

主要负责人
  • sajeesh

其他贡献者
  • vishy

  • schwicke

  • raildo

  • vinod

  • nirbhay

  • nirupma

  • morganfainberg

  • tellesnobrega

  • rodrigods

  • afaranha

工作项

  1. 将创建一个名为“cloud-admin”的角色,并将其分配给根项目中一个用户,并使其可继承。

  2. 将创建一个名为“project-admin”的角色。 在项目中具有“project-admin”角色的用户将能够在从其直接子项目到项目下最后一个级别项目/用户中的项目执行配额操作,前提是它是可继承的。

    注意:像“cloud-admin”和“project-admin”这样的角色不是硬编码的。它在本 BP 中仅用于演示目的。

  3. 将通过扩展现有的 DbQuotaDriver 来实现一个新的配额驱动程序,名为 NestedQuotaDriver,以在 OpenStack 中强制执行分层多租户中的配额。

  4. 将添加一个迁移脚本,以在表 quotas 中创建名为 allocated 的新列,默认值为 0。

依赖项

依赖于 bp 分层多租户

测试

  • 将为所有 REST API 调用添加单元测试。

  • 添加与其它服务集成的单元测试。

文档影响

参考资料