将子网分配添加到 IPAM

https://blueprints.launchpad.net/neutron/+spec/subnet-allocation

作者:

Carl Baldwin <carl.baldwin@hp.com>

联合作者:

Ryan Tidwell <ryan.tidwell@hp.com>

当前 IPAM 的实现方式没有提供设置地址空间以供子网分配的机制。为了能够自动分配子网地址,而不是在创建时需要子网详情,这将是必需的。

这在 IPv6 中变得非常重要,因为浮动 IP 没有实现。租户可能希望创建一个具有可路由地址的网络:不仅仅是地址全局唯一——因为所有 IPv6 地址都应该是——而是操作员实际上可以路由这些地址。

问题描述

Neutron 中的 IPAM 无法分配子网。子网详情必须由最终用户在创建子网时指定。

最终用户可能希望卸载跟踪子网和哪些地址正在使用的负担。在这种情况下,最终用户应该能够设置一个私有地址空间,从中自动分配这些地址。对于 IPv4,这通常是 RFC1918 地址空间的一部分,但不必如此。它可能是已委托给云的公司的地址空间的一部分。对于 IPv6,最终用户可能希望 Neutron 自动使用与 RFC4193 [1] 协调的伪随机算法来计算一个可用的 ULA 子网。

部署者将设置外部网络,并且可能拥有一段可租借或委托给租户在网络上使用的可路由地址。

Neutron 需要一个 API 来创建和管理地址空间,并使其可供租户使用。

提议的变更

概述

此蓝图的目的是启用子网分配池的创建和管理。这将需要对核心 API 进行更改,并且还需要修改子网创建以允许指定地址空间 ID 和前缀长度,而不是实际的子网地址详情。

将为这个新功能添加一个参考实现,并与包含的参考 IPAM 实现一起实现它。

子网池可以共享或不共享。只有管理员可以创建共享池。

将为共享池添加一个配额机制。配额将以最小原子可分配地址单元的数量来表示。为了使数学计算简单,单元大小将硬编码为 IPv4 的 /32 和 IPv6 的 /64。计算 IPv6 的总地址数会使事情变得繁琐,因为即使是一个无符号的 64 位整数也不足以表达这么大的数字。它还需要在表示方面进行额外的复杂性,以便以有意义的方式向用户呈现这些数字。该实现将在 IP 版本之间共享代码。唯一的区别是前缀大小常量。

资源配额应用于的不是 SubnetPool,而是 IP 地址。因此,当前的配额引擎无法执行此操作,因此管理和实施应以自定义方式进行。

操作员可能希望对分配收费(希望在 IPv6 中不需要),但他们可以做到这一点的方式超出了此蓝图的范围。

将使用一个配额机制来限制每个租户可以创建的 SubnetPool 的数量,以避免过度滥用 API。

地址范围

对于每个地址范围应该有一个 SubnetPool。池只是告诉我们哪些地址可以在该范围内分配。此蓝图的范围不包括实施更多内容。但是,将来可能还有更多用例允许跨范围路由。例如

  1. 即使没有外部网络,也可以在 IPv4 中使用 NAT。

  2. 两个范围所有者可以同意允许路由。当实施 RBAC 以允许租户交叉连接网络时,这可能很有用。

  3. 租户有一些全局可路由的地址,并希望与云操作员协商以将其外部路由。

Neutron 一直在隐式地使用每个租户的单个范围。在此范围内不会显式强制地址的唯一性。大多数租户可能已经在自行执行此操作。但是,Neutron 尚未强制执行租户地址范围内的唯一性。

对于 IPv4 池,将允许重叠的地址。默认情况下,池允许重叠。可以通过在创建池时设置一个标志来更改。在任何情况下,IPv6 池内都不允许重叠。但是,不会强制执行跨池的唯一性。

将允许使用来自不同池的子网的网络多播。

数据模型影响

将添加新的对象

SubnetPool

属性

类型

描述

id

UUID

池的唯一标识符。

name

字符串

池的名称

租户 ID

UUID

拥有该空间的租户。

共享

布尔值

池是否共享。

version

4 或 6

允许重叠

布尔值

池是否允许重叠

最小前缀长度

Integer

可以分配的最大子网。

默认前缀长度

Integer

要分配的默认子网大小

SubnetPoolRanges

属性

类型

描述

子网池

UUID

SubnetPool 的唯一标识符

第一个 IP

Integer

最后一个 IP

Integer

SubnetAllocation

属性

类型

描述

id

UUID

分配的唯一标识符。

子网池

UUID

SubnetPool 的唯一标识符

IP 版本

4 或 6

前缀

Integer

分配的网络地址前缀

前缀长度

Integer

前缀长度

pool_id 字段将添加到 Subnet

Subnet

属性

类型

描述

所有字段如当前实现

池 ID

UUID

子网从中分配的池的 ID

当子网未从池分配或在升级期间迁移时,pool_id 将为“null”。

不需要数据迁移。将提供一个标准脚本来创建初始空表。

预计不需要像现有地址 IPAM 那样的可用性表。这将动态计算。子网分配的频率远低于端口分配,并且在数据库中不会那么有争议。这是一个稍后可以解决的实现细节。可用性表或其他巧妙的解决方案可能最终是必要的。

与简单的 IP 地址分配相比,在参考实现中避免重叠会稍微复杂一些。它不能使用数据库上的简单唯一约束,因为我们希望支持分配不同大小的子网,尤其是在 IPv4 中。它可以以最小分配大小为单位存储分配。因此,较大的子网分配将在数据库中使用多行存储。如果 SubnetPools 始终是合理的大小,则通过预填充整个表来在同一表中存储可用性和分配可能是可行的。这是一个可以在代码审查期间解决的实现细节。

如果在池创建后更新了范围,则不会对碰巧落在新范围之外的现有子网分配做任何处理。

REST API 影响

子网详情在 subnet-create 中变为可选。相反,可以选择一个地址空间以及指示所需子网大小的前缀长度。下表总结了对子网创建 API 的更改。

属性名称

类型

访问

默认值

验证转换

描述

cidr

自动分配

地址池

字符串 (UUID)

与 cidr 相同

必须存在并且租户必须具有访问权限

要分配的池

分配池

-使用 0.0.0.0/NN

网关 IP

使用 0.0.0.0

与当前子网创建一样,仍然可以指定分配池和网关 IP。由于不知道实际的子网地址,因此必须使用 0 作为通配符前缀 (0.0.0.0/NN) 指定它们,其中 NN 是所选的前缀长度。实际的网络前缀将在分配后填充。例如,如果我在一个成功的子网创建调用中发送这个

cidr = 0.0.0.0/25
address pool = <some id>
gateway_ip = 0.0.0.1
allocation_pool = 0.0.0.64 - 0.0.0.126

我可能会收到这个

cidr = 10.10.10.128/25
address pool = <some id>
gateway_ip = 10.10.10.129
allocation_pool = 10.10.10.192 - 10.10.10.254

在某些情况下,租户完全满足于由池确定的默认前缀长度。这在 IPv6 中很有用,因为租户只需要分配一个 /64。在这种情况下,池配置了默认前缀长度,并且租户不需要在从池请求子网时提供前缀长度。例如,使用池的默认前缀长度 (/25 在这种情况下) 的子网创建调用如下所示

请求

cidr = <not specified>
address pool = <some id>
gateway_ip = 0.0.0.1
allocation_pool = 0.0.0.192 - 0.0.0.254

分配

cidr = 10.10.10.128/25
address pool = <some id>
gateway_ip = 10.10.10.129
allocation_pool = 10.10.10.192 - 10.10.10.254

以下说明了如何一起使用 cidr 和地址池。基本规则是 cidr 和前缀是互斥的,并且必须指定一个。如果指定了前缀长度,则也必须指定池。除非在 neutron.conf 中定义了全局默认池,否则例外。

cidr

地址池

操作

未定义全局默认池时出错

否则使用默认前缀长度分配子网

指定

使用池的默认前缀长度分配

指定特定的 CIDR

与之前相同。使用隐式租户地址池。

指定特定的 CIDR

指定

尝试从池分配指定的子网。

指定通配符 CIDR

指定

从池分配具有请求前缀长度的子网。

指定通配符 CIDR

未定义全局默认池时出错

否则从全局池分配子网

API 可能出现新的错误:SubnetPoolNotFound、PrefixLengthTooBig/Small、NoAddressesAvailable。

需要添加新的方法来创建和操作 SubnetPools。

属性

访问

类型

必需

CRUD

默认值

验证约束

注意事项

id

RO,全部

字符串 (UUID)

N/A

R

生成

N/A

表示地址空间的 UUID

name

RW,所有者

string

CR

N/A

池的名称

共享

RO,全部(如果为 True);RW,管理员

bool

CRU

False

True/False

其他租户是否可以看到它

version

RW,所有者

integer

CR

N/A

4/6

IP 版本

允许重叠

RW,管理员

bool

CR

如果 version=4 为 True

如果 version=6 为 False

True/False

允许重叠的子网

最小前缀长度

RW,所有者

integer

CRU

N/A

IP 版本可行的前缀长度

IP 版本

默认前缀长度

RW,所有者

integer

CRU

由 min_prefix_len 和版本确定

> min_prefix_len & < max 版本前缀

默认前缀分配长度

范围

RW,所有者

(2 元组或 CIDR 的列表)

CRU

N/A

有效的非重叠范围

基本上,如果 shared 为 True,则所有租户可以看到所有字段。如果不是,则只有所有者才能看到池。无论如何,只有所有者才能写入字段。只有管理员才能写入 shared 字段。

对于 IPv4,前缀长度应在 8 到 30 之间。对于 IPv6,可能在 32 到 64 之间。

IPv6 地址空间的一些部分根本没有指定任何类型的用途(即,在 2000::/3、fc00:/7 用于 ULA 以及其他指定的范围之外)[2]。需要进行一些验证。应允许以下地址空间

地址

描述

2000::/3

全局单播

fc00::/7

ULA 地址,可以在站点内路由。

如果更新了范围,现有子网分配将不会受到影响,这些分配碰巧落在新的范围之外。

此蓝图将从我们现在为网络所拥有的相同共享模型开始。但是,可以稍后添加一个类似于为网络提出的 RBAC 机制[3]

安全影响

存在一个新的 API。有了任何新的 API,就存在对系统进行新的攻击的潜力。例如,如果有人可以控制一个地址空间,他们可以将其缩小到没有东西并阻止进一步的分配。

只要只有管理员可以创建共享池并且共享池上有配额,就不应该引入新的漏洞。尽管如此,在代码审查期间应特别注意防止引入新的漏洞。

拥有对地址空间无限控制的人可能会将其填满作为阻止进一步分配的另一种方式。

通知影响

其他最终用户影响

性能影响

分配在子网创建时执行。这可能涉及几个重要的数据库查询。子网创建不如端口创建常见,因此预计不会成为问题。使用乐观锁技术应减轻影响。

创建和更新池的新 API 方法预计不会被调用得足够频繁以产生任何重大影响。

除了典型用例外,我们还应考虑非典型用例。如果实现性能非常差,可能会被用作拒绝服务攻击,并带来安全风险。这应在代码审查期间解决。

IPv6 影响

此新功能必须对 IPv6 和 IPv4 同样有效。这旨在增强 Neutron 中的 IPv6 体验。它不会对 Neutron 中现有的 IPv6 功能产生任何影响。

其他部署者影响

默认情况下,云系统将像今天一样工作,只是租户将能够创建自己的池,而无需部署者采取任何操作。

部署者可以使用共享池功能创建可供租户在其网络上使用的地址池,但这不是必需的。如果他们希望全局或在数据中心内路由到租户网络,他们可能会希望使用此功能。

可以使用外部 IPAM 与此新 API 配合使用。外部 IPAM 驱动程序的开发不在此蓝图的范围内。

开发人员影响

社区影响

此更改在 Kilo 设计峰会的插拔式 IPAM 会议上进行了讨论。它也与 IPv6 子团队进行了讨论。社区已经认识到这是一种需求,特别是对于 IPv6 路由。有了此 API,IPv6 子团队可以仅使用前缀委派作为一种分配机制,在用户向此 API 发出请求后。

备选方案

N/A

实现

负责人

主要负责人

ryan-tidwell

其他贡献者

carl-baldwin L3 子团队

工作项

  • 子网池 REST API 和相应的数据库支持

  • 子网 API 和数据库模式的调整

  • 最小化 Horizon 支持,以支持基本的子网分配(v4 和 v6)

  • Tempest 测试

  • 功能测试

  • API 测试

依赖项

此蓝图依赖于 neutron-ipam [4] 中的工作。该蓝图添加了一些必要的框架来实现此新功能。有关更多信息,请参见 Etherpad [5]

测试

当然,对所有新代码进行单元测试。这意味着代码结构必须可测试。将使用 TDD。

Tempest 测试

  • 创建 v4 子网池

  • 创建 v6 子网池

  • 从子网池分配 v4 子网

  • 从子网池分配 v6 子网

功能测试

  • 验证配额执行

  • 降低租户配额,验证先前分配的资源完好无损,验证新值的执行

  • 断言适用的子网分配详细信息不会在使用共享池时跨租户泄露

  • 创建 allow_overlap=True 和 allow_overlap=False 的子网池,验证子网的分配

API 测试

  • 验证 v4 池子网池创建时的默认值

  • 验证 v6 池子网池创建时的默认值

  • 验证 allow_overlap 约束为 v6 池的 False

  • 创建 v4 子网池,验证共享和 allow_overlap 值

  • 创建 v6 子网池,验证共享和 allow_overlap 值

  • 从子网池分配 v4 子网,断言成功和子网详细信息

  • 从子网池分配 v6 子网,断言成功和子网详细信息

文档影响

用户文档

更新网络 API 参考 更新管理指南

开发人员文档

N/A

参考资料