将子网分配添加到 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。池只是告诉我们哪些地址可以在该范围内分配。此蓝图的范围不包括实施更多内容。但是,将来可能还有更多用例允许跨范围路由。例如
即使没有外部网络,也可以在 IPv4 中使用 NAT。
两个范围所有者可以同意允许路由。当实施 RBAC 以允许租户交叉连接网络时,这可能很有用。
租户有一些全局可路由的地址,并希望与云操作员协商以将其外部路由。
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]。需要进行一些验证。应允许以下地址空间
http://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml
地址 |
描述 |
|---|---|
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
实现¶
负责人¶
- 主要负责人
- 其他贡献者
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