允许路由器上使用多个外部网关¶
RFE: https://bugs.launchpad.net/neutron/+bug/1905295
本文档提出允许 Neutron 路由器拥有多个外部网关,以便表示路由器设计,其中路由器具有多个通往外部世界的接口,以提高容量(通常在这些接口之间进行负载均衡)和可用性(容忍路由器上行链路或路由器网关端口故障)。
问题描述¶
下面我们描述了一个云设计,它要求我们允许单个路由器上使用多个外部网关。但是本文档中提出的功能绝不特定于此设计,本文档仅致力于允许任何需要它的设计使用多个外部网关。
Neutron 路由器可以是主动-主动 HA 路由器。计算节点通过 MLAG 连接到 Neutron 路由器,路由器的两侧向计算节点呈现单个 IP。在 Neutron 路由器和数据中心网关之间有一步逻辑路由器(从这里开始:数据中心网关),它也是一个主动-主动 HA 路由器。Neutron 路由器和数据中心网关通过 2x2 点对点链路互连(从每一侧到每一侧)。在此设置中,Neutron 路由器具有 4 个通往外部世界的链路。
+--+ +--+
|R3| |R4| Datacenter gateway
+--+ +--+
| \ / |
| \ / |
| X | 2x2 point-to-point links
| / \ |
| / \ |
+--+ +--+
|R1| |R2| Neutron router
+--+ +--+
| \ / |
| \ / |
| X | MLAG
| / \
| /
+--+
|C1| ... Compute hosts
+--+
提议的变更¶
总体图景¶
在 external_gateway_info 结构中的信息用于创建网关端口。网关端口是路由器的腿,除了数据包转发之外,我们还执行 SNAT(如果启用)和 DNAT(用于浮动 IP 和端口转发),并影响该路由器的默认路由。鉴于多个 external_gateway_info 结构,我们可以直接创建多个网关端口。我们也可以直接安装其他外部网关的直接连接路由。
仅使用一个外部网关时 - 针对数据包转发 - 自然只有内部-内部和内部-外部方向。但是,使用多个外部网关,外部-外部方向也成为可能。我们没有外部-外部转发的用例。但是,为了简化实现,本文档建议支持该功能,即允许从一个外部网关到另一个外部网关的数据包转发。如果需要,后续文档可以提出对外部-外部数据包转发的更精细控制。
但是,不能在不产生复杂后果的情况下(例如,在多个下一跳之间进行负载均衡)将路由器的默认路由倍增。因此,为了简化起见,对于每个路由器,我们保留一个外部网关作为特殊网关。特殊网关用于设置路由器的默认路由,而其他外部网关不会影响默认路由。
可以像往常一样为每个外部网关执行 NAT 和浮动 IP 的预留,但请参阅“范围之外”部分。
首次实现针对 l3-agent 上的集中式路由器。
对于特殊的第一个网关端口,我们继续添加与之前相同的路由。
Neutron 路由器中通常的一组隐式管理的路由是
每个路由器接口的每个子网的一个直接连接路由。
每个网关端口的每个子网的一个直接连接路由。
指向单个网关端口子网的
gateway_ip的一个默认路由。
遵循此逻辑,当我们添加更多网关端口时,我们还为每个其他网关端口的每个子网添加一个直接连接路由。因此,目的地为这些子网的流量将直接通过各自的网关端口发送。流量也可以从外部到达网关端口。但是,大多数流量将通过默认路由发送。
超出范围¶
首先,此处并未针对 l3-agent 整体支持主动-主动 HA 路由器。
我们仅有意为第一个特殊网关端口(的子网的 gateway_ip)添加默认路由。我们不会为其他网关端口(的子网的 gateway_ip)添加默认路由。对其他路由的进一步管理(以实际使用其他外部网关)留给
通过 extraroutes API 管理其他路由。
neutron-dynamic-routing 的未来改进,以便 Neutron 路由器也可以接收(而不仅仅是通告)其他路由。[1]
由于 extraroutes API 已经可用,我们相信在合并此功能后就可以实现多个外部网关的一些使用。
使用新引入的附加外部网关作为下一跳(用于租户网络或浮动 IP)通告任何路由也超出本文档的范围。我们认为通过路由协议通告此类路由显然是有意义的,但是
这可以在 neutron-dynamic-routing 中的后续文档中涵盖,并且
无需路由协议即可基本使用此处提出的更改。
向后兼容性¶
我们建议以略微冗余的方式存储和公开外部网关,以便更容易实现向后兼容性。尽可能地(API、DB、RPC),保持路由器的当前标量外部网关(或网关端口)属性不变。但也要添加一个新的路由器属性用于复数形式:外部网关或网关端口,其中包含(不仅是其余部分,而且)所有这些对象的列表。因此,标量属性中的对象也存在于此列表中 - 最好是列表的第一个元素。
这只是一个高级方法,旨在在只需要保持向后兼容行为时,不更改任何代码。
数据库影响¶
当前的 DB 模式以某种冗余的方式包含路由器 - 外部网关关系。
首先,在 routerports 表中,没有约束限制属于一个路由器的类型为 network:router_gateway 的端口数量。今天,我们每个路由器最多存储一个 network:router_gateway 端口,但 DB 模式允许更多。[2]
其次,routers 表的 gw_port_id 列是一个标量。今天,它存储与 routerports 表中相同的端口 UUID。[3]
我们建议
保持 SQL 模式不变,但在
routerports表中开始存储多个network:router_gateway端口。也保持
routers.gw_port_id标量,并在其中存储一个特殊的、向后兼容的外部网关(因此,它同时存在于routerports表和routers.gw_port_id中)。将
neutron.db.models.l3.Router类扩展为新的属性gw_ports,该属性映射到routerports表中存储的所有相关network:router_gateway端口。
REST API 影响¶
引入一个新的 API 扩展,名为 multiple-external-gateways。
此扩展添加一个新的路由器属性:external_gateways。它是一个 external_gateway_info 结构的列表,例如
[
{"network_id": ...,
"external_fixed_ips": [{"ip_address": ..., "subnet_id": ...}, ...],
"enable_snat": ...},
...
]
列表中的第一个元素是特殊的
它始终与原始
external_gateway_info相同。它是设置 Neutron 路由器默认路由的网关。
列表的其余部分的顺序无关紧要且被忽略。列表中不允许重复(即,具有相同 network_id 的多个外部网关)。
更新 external_gateway_info 也会更新 external_gateways 的第一个元素,并且保持 external_gateways 的其余部分不变。将 external_gateway_info 设置为空值也会将 external_gateways 重置为空列表。
不能在 POST /v2.0/routers 或 PUT /v2.0/routers/{router_id} 请求中设置 external_gateways 属性,而是可以通过子方法进行管理
PUT /v2.0/routers/{router_id}/add_external_gateways接受
external_gateway_info结构的列表。将外部网关添加到已经存在一个的网络会引发错误。PUT /v2.0/routers/{router_id}/update_external_gateways接受
external_gateway_info结构的列表。要更新的外部网关由 PUT 请求中找到的network_ids标识。可以更新external_fixed_ips和enable_snat字段。不能更新network_id字段。PUT /v2.0/routers/{router_id}/remove_external_gateways接受潜在的部分
external_gateway_info结构的列表。仅使用external_gateway_info结构中的network_id字段。可以存在external_fixed_ips和enable_snat键,但其值将被忽略。
add/update/remove PUT 子方法响应整个路由器对象,就像 POST/PUT/GET /v2.0/routers 一样。
RPC 影响¶
sync_routers 消息已经有一个 gw_port 字段。扩展该消息以包含 gw_ports 字段,其中包含所有网关端口。升级此 RPC 消息的版本。
升级影响¶
sync_routers RPC 消息将具有新版本。
客户端影响¶
osc 和 openstacksdk 中的相关更改。
测试¶
单元测试。
l3-agent 的完整堆栈测试。
neutron-tempest-plugin 中的 Tempest 测试。
负责人¶
Bence Romsics <bence.romsics@gmail.com>
参考资料¶
[1] https://review.opendev.org/c/openstack/neutron-specs/+/783791 [2] https://opendev.org/openstack/neutron/src/commit/b7c4a11158786431c262cfcc2fc4bc46ab6bacd2/neutron/db/models/l3.py#L24 [3] https://opendev.org/openstack/neutron/src/commit/b7c4a11158786431c262cfcc2fc4bc46ab6bacd2/neutron/db/models/l3.py#L54