支持 IPv6 网络的多重 IPv6 前缀和地址

Launchpad蓝图

https://blueprints.launchpad.net/neutron/+spec/multiple-ipv6-prefixes

IPv6 标准允许将多个 IPv6 前缀和地址与给定的接口关联。本蓝图定义了 OpenStack 中 Neutron 端口如何支持多个 IPv6 前缀和/或地址,并描述了这与 IPv4 实现的不同之处。

一些可能的用例包括

  • 允许在租户网络上混合使用公共(全局单播地址,或 GUA)和私有(例如,唯一本地地址,或 ULA)IPv6 地址。

  • IPv6 重编号:支持重叠间隔,在此期间旧的和新的 IPv6 前缀共存(例如,在路由器端口上)。

  • 类似浮动 IP 的支持:允许租户从预先确定的公共 IPv6 地址池中分配地址,并将该地址与 VM 或一组 VM 关联。注意:与 IPv4 浮动 IP 功能不同,IPv6 支持不涉及从固定 IP 到浮动 IP 的 NAT 转换。此设计规范是 IPv6 浮动 IP 的先决条件;更多详细信息将在单独的蓝图中介绍。

问题描述

  • IPv6 的考虑事项

    在决定如何在 Neutron 中配置和支持多个 IPv6 前缀和地址,以及 IPv6 实现将如何紧密遵循 IPv4 范例时,需要考虑 IPv6 和 IPv4 之间的一些差异

    • IPv6 地址更加丰富。这意味着

      • 我们可以承担在网络中的每个子网中为端口分配地址时更加保守。

      • 无需进行 NAT 转换。可以直接将全局可访问的地址分配给端口。

    • IPv6 提供了两种主要的 IP 地址分配机制

      • SLAAC(无状态地址自动配置):此机制 [Ref-2] 需要最少的宿主和路由器配置。使用 SLAAC,路由器会通过组播定期向该链路上的所有 IPv6 使能的宿主发送路由器通告 (RA) 消息。(在 OpenStack 中,虚拟路由器生成 RA 消息由路由器通告守护程序或 radvd 进程提供。)RA 消息包含一个或多个前缀,用于标识与该链路关联的子网。链路上的宿主然后根据 SLAAC 子网和链路上的每个接口,通过形成唯一的“接口标识符”(通常基于接口的 MAC 地址),并将该接口标识符与每个前缀组合来生成唯一的 IPv6 地址。为了快速获得路由器通告,链路上的宿主还可以通过发送路由器请求消息 [Ref-3] 来提示路由器。

      • DHCPv6:类似于 DHCPv4,可以配置 DHCP 服务器为链路上的每个节点分配特定的 IPv6 地址。

      在当前的 Neutron 实现中,当在创建子网时通过设置 subnet-create API 调用中的“ipv6_ra_mode”和“ipv6_address_mode”属性来配置子网的 SLAAC 与 DHCPv6 有状态/无状态地址模式时,子网被配置为 SLAAC 或 DHCPv6 状态。这些属性是在 [Ref-4] 列出的蓝图中添加的。属性值在 [Ref-5] 中描述。

      为了本设计规范的目的,术语“SLAAC 使能”子网将用于指配置为 SLAAC 或 DHCPv6 无状态地址模式的子网。

      SLAAC 寻址的重要方面是 RA 消息是组播的(在所有节点组播通道上),发送到链路上的所有 IPv6 功能节点。这意味着在 OpenStack 实例中,每当使用 SLAAC 地址生成模式创建子网时,在该网络上创建的所有 IPv6 功能宿主/VM 都将收到定期 RA 消息,其中包括与该子网关联的前缀(以及网络上所有其他 SLAAC 使能子网的前缀)。因此,宿主将使用该子网/前缀生成地址,无论该端口的关联 port-create API 调用(以及任何后续 port-update API 调用)是否指定应将该子网与该端口关联。

      从理论上讲,可以通过配置 radvd,以便 RA 消息通过单播按子网传递来选择性地启用/禁用 RA 前缀分配的传递,但这种实现将相当复杂,并且由于所需的额外消息和处理,在大型网络中将无法很好地扩展,并且会违背 SLAAC 的自动特性。

  • 当前实现

    • 使用显式固定 IP 列表创建端口

      在当前的 Neutron 实现中,当使用显式固定 IP 列表创建端口时,以下子网上的 IP 将与端口关联

      • 显式列出的所有子网/IP

      缺少的是,即使 IPv6 使能的 VM 将根据收到的 RA 消息自动生成这些子网的 SLAAC 地址,SLAAC 使能的子网也不会隐式包含在与端口关联中。

    • 不使用显式固定 IP 列表创建端口

      在当前的 Neutron 实现中,当不使用显式固定 IP 列表创建端口时,以下子网上的 IP 将与端口关联

      • 所有 IPv4 子网的一个子网

      • 所有 IPv6 DHCPv6 有状态子网的一个子网

      • 所有 SLAAC 使能的子网

      可以考虑的是,是否也应隐式包含所有 DHCPv6 有状态子网以进行分配并与端口关联(以及 SLAAC 使能的子网),因为 IPv6 地址更加丰富。但是,这将与 IPv4 模型有很大的不同,因此保持当前实现会更安全,更不容易混淆。

    • 端口更新

      在当前的 Neutron 实现中,当更新端口时,以下子网上的 IP 将与端口关联

      • 可选的 fixed_ips 列表中显式列出的所有子网/IP

      可以说,这里存在的问题是,未显式包含在端口更新请求的 fixed_ips 列表中,与 SLAAC 使能子网关联的任何现有关联将被忘记(删除),即使端口将继续使用 SLAAC 地址,只要 IPv6 RA 消息的来源(radvd 进程)继续通过所有节点组播通道向所有 IPv6 使能的宿主发送 RA 消息。

    • 路由器接口创建

      L3 代理将最初与内部路由器接口(网关端口)关联的 IP 地址数量限制为每个系列最多一个 IP 地址(即,最多一个 IPv4 地址和最多一个 IPv6 地址)。

      对于面向外部的网关端口,IP 地址的数量进一步限制为单个 IP 地址,可以是 IPv4 或 IPv6 [Ref-1]

      [Ref-1] 中描述的更改,目前已被放弃,是尝试放宽此限制,以便允许每个外部网关端口最多一个 IPv4 地址和最多一个 IPv6 地址。

      本蓝图将包含 [Ref-1] 中描述的更改,还将通过允许每个内部路由器端口上的多个 IPv6 地址来放宽内部路由器端口的限制。

提议的变更

  • 端口创建 API 调用

    本蓝图不会更改 Neutron port-create API 请求/响应消息的定义/语法。但是,此 API 调用将被使用的方式,以及当 IPv6 子网包含在关联网络中时,Neutron 处理此调用的方式,将代表与 IPv4 模型的小幅转变。行为的变化将围绕这样一个概念:如果网络包含 SLAAC 使能的子网,那么网络上的所有端口都将自动从该子网获取地址。可以总结如下

    • 当前 IPv4 行为不会更改。

    • 使用显式固定 IP 列表的端口创建操作:如果包含显式固定 IP 列表(通过 fixed_ips 字典),则将应用以下更改

      • 网络上所有 SLAAC 使能的子网现在将隐式与端口关联,无论这些子网是否显式包含在 fixed_ips 列表中。(DHCPv6 有状态的子网仅在显式包含在 fixed_ips 中时才继续包含在此案例中。)

      • 端口创建请求可以选择显式列出 SLAAC 使能的子网在 fixed_ips 中,但这些条目是多余的。

    • 不使用显式固定 IP 列表的端口创建操作:与当前设计相比,不会有任何更改。当端口创建操作不包含显式固定 IP 列表时,网络上的以下子网将与端口关联

      • 所有 IPv4 子网的一个子网

      • 所有 IPv6 DHCPv6 有状态子网的一个子网

      • 所有 SLAAC 使能的子网

    • API 调用响应将列出与端口关联的所有固定 IP,无论关联是隐式还是显式包含在端口创建请求中。

  • 端口更新 API 调用

    与 port-create API 调用类似,Neutron port-update API 请求/响应消息的定义/语法不会更改,但是 IPv6 子网/地址的 API 调用使用方式和 Neutron 处理这些请求的方式将发生变化。行为的变化将围绕这样一个概念:如果网络包含 SLAAC 使能的子网,那么网络上的所有端口都将自动从该子网获取地址。将应用以下更改

    • 当 port-update 操作不显式将 SLAAC 使能的子网包含在 fixed_ips 列表中时,与关联网络上的每个 SLAAC 使能的子网关联的 IP 地址/子网的关联现在将隐式保留(保留)。

    • API 调用的响应将在 fixed IPs 列表中包含网络上所有 SLAAC 使能的子网的地址,无论关联是隐式还是显式包含在 port-update 请求中。

  • 子网创建 API 调用

    当在端口已在给定网络上创建后创建 SLAAC 使能的子网时,并且该子网依赖于提供商源来获取 RA 消息(而不是 OpenStack 参考 RADVD 进程;这通过 subnet-create API 调用中的“ipv6_ra_mode”和“ipv6_address_mode”属性选择),那么网络上的关联 IPv6 功能宿主预计将根据提供商的 RA 消息自动生成 SLAAC 地址。为了与这些生成的地址保持同步,子网创建处理需要修改,以便为网络上所有现有端口添加 IPAllocations 表中的条目,以便将端口与 SLAAC 使能的子网上的地址关联。

  • 路由器接口每端口 IP 地址数量限制

    • 面向外部的网关端口:如问题定义部分所述,本蓝图将通过允许每个端口最多一个 IPv4 地址和最多一个 IPv6 地址来放宽 Neutron L3 代理对面向外部的网关端口施加的限制。

    • 内部路由器端口:本蓝图将通过允许每个内部路由器端口上的多个 IPv6 地址来放宽对内部路由器端口施加的限制。对于 IPv4 子网,不会进行任何更改,也就是说,需要为每个需要网关 IP 地址的 IPv4 子网创建单独的路由器接口。

      路由器接口创建 API 调用的处理方式将更改为,给定网络上的 IPv6 子网将与连接到它们的路由器的单个内部路由器端口共享。也就是说,当为 IPv6 子网调用路由器接口创建 API 时,将检查是否已经存在该路由器上的内部路由器接口,该接口支持网络中其他 IPv6 子网之一的网关地址。如果是这样,新的 IPv6 网关 IP 地址将添加到该现有接口,而不是创建新的路由器接口。

数据模型影响

预计不会进行任何数据模型更改。

REST API 影响

如前几节所述,port-create、port-update 和 subnet-delete API 调用的定义/语法不会更改,但是这些 API 调用的使用方式以及 Neutron 处理这些 API 调用的方式将针对 IPv6 子网与 IPv4 子网进行修改。特别是,端口将在端口创建和端口更新操作期间自动与所有 SLAAC 使能的子网关联,并且端口创建和端口更新响应将自动在 fixed_ips 列表中包含这些 SLAAC 地址。

安全影响

向 OpenStack 云开放 IPv6 RA 消息可能存在一些风险(例如,欺骗的 RA 消息可能会修改网络),但这对于基本的 SLAAC 实现是一个问题,而不是本蓝图引入的问题。

通知影响

预计不会进行任何更改。

其他最终用户影响

与“REST API 影响”部分中讨论的没有什么不同。

性能影响

预计没有显著的性能影响。

IPv6 影响

是,这会影响 Neutron 参考 IPv6 实现。

其他部署者影响

部署者需要了解,对于网络中的每个 SLAAC 使能的子网,每个端口上的 IPv6 地址将自动且隐式生成。这不应令人惊讶,因为 SLAAC 是一种自动配置机制。

开发人员影响

L3 服务的开发人员可能需要在涉及 IPv6 子网时,结合本蓝图提出的行为更改,以确保管理平面行为正确反映 SLAAC 的工作方式。此蓝图的实现将合并到通用的框架数据库类中,因此从这些类派生的服务将自动继承此行为。

社区影响

本蓝图是向 Neutron 参考设计添加 RADVD 和 IPv6 SLAAC 支持的自然进展。它试图调和 SLAAC 的工作方式与当前设计中在不使用显式固定 IP 列表的情况下创建端口时隐式关联的 IP 地址之间的一些不一致之处。

这尚未在邮件列表中讨论过,但蓝图和相关的补丁集自 Juno 中期以来一直处于审查中。这作为 etherpad 议程项目添加到亚特兰大峰会期间 IPv6 设计环节中进行讨论,但不幸的是,在到达此项目之前设计环节就结束了。

备选方案

作为对当前方案的替代方案,可以通过配置 radvd,以单播方式在每个端口、每个子网的基础上发送 RA 消息,从而避免 RA 前缀分配的自动性。明确包含给定 SLAAC 启用子网的端口将收到包含该子网广告的 RA 单播消息,而不明确包含 SLAAC 子网的端口将不会收到 RA 单播消息(或者收到不包含该子网的 RA)。然而,这种方法会相当复杂且容易出错,并且会违背 SLAAC 的自动性。此外,鉴于 IPv6 地址已经可以通过使用 DHCPv6-stateful 在子网上进行选择性分配,因此这种方法不会增加太多价值。

实现

负责人

主要负责人

Dane LeBlanc launchpad-id: leblancd

其他贡献者

Robert (Bao) Li launchpad-id: baoli

工作项

  • 端口创建 API 处理编码和单元测试

  • 端口更新 API 处理编码和单元测试

  • 子网删除 API 处理编码和单元测试

  • 路由器/网关接口编码和单元测试

  • Tempest 测试创建

依赖项

测试

Tempest 测试

API 行为的测试将被合并到 Neutron 树内的 API 测试中,因此不会添加树外的 Tempest API 测试。

将添加一个 Tempest 网络场景测试,以检查在每个端口使用多个地址时的 dataplane 连接性

  • 创建一个包含 1 个 IPv4、1 个 SLAAC 和 1 个 DHCPv6 子网的内部路由器端口。

  • 使用所有三个子网创建一个实例。

  • 从实例 ping 每个子网的网关 IP 地址。

  • 从实例 ping 一个外部网关端口。

功能测试

不需要功能测试。

API 测试

  • 在包含 1 个 IPv4 和 1 个 SLAAC 地址/子网的网络上进行端口创建的 API 测试。

  • 在包含 1 个 IPv4 和 1 个 DHCPv4 地址/子网的网络上进行端口创建的 API 测试。

  • 在包含 2 个 DHCPv4 和 2 个 SLAAC 地址/子网的网络上进行端口创建的 API 测试。

  • API 测试端口更新:从 SLAAC 地址开始,添加 DHCPv4 地址。

文档影响

用户文档

Neutron API v2 参考文档可能需要修改,以反映与端口创建、端口更新和子网删除相关的隐式 IPv6 地址分配的预期行为(尽管文档没有深入探讨这些细节)

https://wiki.openstack.org/wiki/Neutron/APIv2-specification#Create_Port https://wiki.openstack.org/wiki/Neutron/APIv2-specification#Update_Port https://wiki.openstack.org/wiki/Neutron/APIv2-specification#Delete_Subnet

开发人员文档

除了上述 Neutron API v2 文档更改外,不需要其他内容。

参考资料