路由提供商网络

注意

使用此功能需要 OpenStack 客户端版本 3.3 或更高版本。

在路由提供商网络出现之前,网络服务无法将多段层 3 网络作为一个实体呈现。因此,每个运营商通常选择以下架构之一

  • 单个大型层 2 网络

  • 多个小型层 2 网络

单个大型层 2 网络在扩展时会变得复杂,并涉及显著的故障域。

多个小型层 2 网络扩展性更好,缩小了故障域,但将网络选择留给用户。在没有额外信息的情况下,用户很难区分这些网络。

路由提供商网络使单个提供商网络能够表示多个层 2 网络(广播域)或段,并使运营商能够向用户呈现一个网络。但是,实例可用的特定 IP 地址取决于特定计算节点上可用的网络段。Neutron 端口只能与一个网络段关联,但 OVN 分布式服务(如 OVN Metadata)除外。

与传统的网络一样,层 2(交换)处理同一段上端口之间的流量传输,层 3(路由)处理段之间的流量传输。

每个段至少需要一个明确属于该段的子网。段与子网之间的关联将路由提供商网络与其他类型的网络区分开来。网络服务强制执行特定网络上的所有子网要么零个,要么全部与一个段关联。例如,尝试在包含具有段的子网的网络上创建一个没有段的子网会生成错误。

网络服务不提供段之间的层 3 服务。相反,它依赖于物理网络基础设施来路由子网。因此,网络服务和物理网络基础设施都必须包含路由提供商网络的配置,类似于传统的提供商网络。将来,动态路由协议的实施可能会简化路由网络的配置。

先决条件

路由提供商网络比传统的提供商网络需要额外的先决条件。我们建议使用以下步骤

  1. 从段开始。网络服务使用以下组件定义一个段

    • 唯一的物理网络名称

    • 分段类型

    • 分段 ID

    例如,provider1VLAN2016。有关更多信息,请参阅 API 参考

    在网络中,为每个段使用唯一的物理网络名称,这使得在子网之间重用相同分段细节成为可能。例如,在特定提供商网络的各个段上使用相同的 VLAN ID。与传统的提供商网络类似,运营商必须相应地配置层 2 物理网络基础设施。

  2. 实现段之间的路由。

    网络服务不提供段之间的路由。运营商必须实现提供商网络段之间的路由。每个段上的子网必须包含该特定子网上的路由器接口的网关地址。例如

    版本

    地址

    网关

    segment1

    4

    203.0.113.0/24

    203.0.113.1

    segment1

    6

    fd00:203:0:113::/64

    fd00:203:0:113::1

    segment2

    4

    198.51.100.0/24

    198.51.100.1

    segment2

    6

    fd00:198:51:100::/64

    fd00:198:51:100::1

  3. 将段映射到计算节点。

    路由提供商网络意味着计算节点位于不同的段上。运营商必须确保每个应该参与路由器提供商网络的计算主机都直接连接到其段之一。

    主机

    机架

    物理网络

    compute0001

    机架 1

    segment 1

    compute0002

    机架 1

    segment 1

    compute0101

    机架 2

    segment 2

    compute0102

    机架 2

    segment 2

    compute0102

    机架 2

    segment 2

  4. 部署 DHCP 代理。

    与传统的提供商网络不同,DHCP 代理无法支持网络中的多个段。运营商必须为每个段部署至少一个 DHCP 代理。考虑在包含段的计算节点上部署 DHCP 代理,而不是一个或多个网络节点,以减少节点数量。

    主机

    机架

    物理网络

    network0001

    机架 1

    segment 1

    network0002

    机架 2

    segment 2

  5. 配置网络服务与计算调度器之间的通信。

    具有 IPv4 地址的实例的接口,必须由计算调度器放置在具有可用 IPv4 地址的段的某个主机上。为了使之成为可能,网络服务将与每个路由提供商网络段关联的 IPv4 地址清单传达给计算调度器。运营商必须配置网络服务将用于与计算调度器的放置 API 通信的身份验证凭据。以下是一个示例配置。

    注意

    由于其大的地址空间,网络服务与计算调度器之间的协调对于 IPv6 子网来说是不必要的。

    注意

    网络服务与计算调度器之间的协调需要以下最低 API 微版本。

    • 计算服务 API:2.41

    • 放置 API:1.1

示例配置

控制器节点

  1. 通过将 segments 附加到所有运行 neutron-server 服务的节点上的 neutron.conf 文件中的 service_plugins 列表中,启用段服务插件

    [DEFAULT]
    # ...
    service_plugins = ...,segments
    
  2. neutron.conf 文件中添加一个 placement 部分,其中包含用于计算服务放置 API 的身份验证凭据

    [placement]
    www_authenticate_uri = http://192.0.2.72/identity
    project_domain_name = Default
    project_name = service
    user_domain_name = Default
    password = apassword
    username = nova
    auth_url = http://192.0.2.72/identity_admin
    auth_type = password
    region_name = RegionOne
    
  3. 重新启动 neutron-server 服务。

  4. (可选)配置 Nova 调度器以基于路由网络主机聚合进行过滤。如果未设置此选项,则在将端口附加到实例并分配 IP 地址后,Nova 可能会将实例调度到没有访问所需段的主机上。有关更多信息,请参阅 Nova 配置参考

网络或计算节点

  • 配置每个节点上的层 2 代理,以将一个或多个段映射到适当的物理网络桥接或接口,并重新启动代理。

创建一个路由提供商网络

以下步骤创建一个具有两个段的路由提供商网络。每个段包含一个 IPv4 子网和一个 IPv6 子网。

  1. 获取管理项目凭据。

  2. 创建一个 VLAN 提供商网络,其中包括一个默认段。在此示例中,网络使用 provider1 物理网络和 VLAN ID 2016。

    $ openstack network create --share --provider-physical-network provider1 \
      --provider-network-type vlan --provider-segment 2016 multisegment1
    +---------------------------+--------------------------------------+
    | Field                     | Value                                |
    +---------------------------+--------------------------------------+
    | admin_state_up            | UP                                   |
    | id                        | 6ab19caa-dda9-4b3d-abc4-5b8f435b98d9 |
    | ipv4_address_scope        | None                                 |
    | ipv6_address_scope        | None                                 |
    | l2_adjacency              | True                                 |
    | mtu                       | 1500                                 |
    | name                      | multisegment1                        |
    | port_security_enabled     | True                                 |
    | provider:network_type     | vlan                                 |
    | provider:physical_network | provider1                            |
    | provider:segmentation_id  | 2016                                 |
    | revision_number           | 1                                    |
    | router:external           | Internal                             |
    | shared                    | True                                 |
    | status                    | ACTIVE                               |
    | subnets                   |                                      |
    | tags                      | []                                   |
    +---------------------------+--------------------------------------+
    
  3. 将默认段重命名为 segment1

    $ openstack network segment list --network multisegment1
    +--------------------------------------+----------+--------------------------------------+--------------+---------+
    | ID                                   | Name     | Network                              | Network Type | Segment |
    +--------------------------------------+----------+--------------------------------------+--------------+---------+
    | 43e16869-ad31-48e4-87ce-acf756709e18 | None     | 6ab19caa-dda9-4b3d-abc4-5b8f435b98d9 | vlan         |    2016 |
    +--------------------------------------+----------+--------------------------------------+--------------+---------+
    
    $ openstack network segment set --name segment1 43e16869-ad31-48e4-87ce-acf756709e18
    

    注意

    此命令不会产生任何输出。

  4. 在提供商网络上创建一个第二个段。在此示例中,该段使用 provider2 物理网络和 VLAN ID 2017。

    $ openstack network segment create --physical-network provider2 \
      --network-type vlan --segment 2017 --network multisegment1 segment2
    +------------------+--------------------------------------+
    | Field            | Value                                |
    +------------------+--------------------------------------+
    | description      | None                                 |
    | headers          |                                      |
    | id               | 053b7925-9a89-4489-9992-e164c8cc8763 |
    | name             | segment2                             |
    | network_id       | 6ab19caa-dda9-4b3d-abc4-5b8f435b98d9 |
    | network_type     | vlan                                 |
    | physical_network | provider2                            |
    | revision_number  | 1                                    |
    | segmentation_id  | 2017                                 |
    | tags             | []                                   |
    +------------------+--------------------------------------+
    
  5. 验证网络是否包含 segment1segment2 段。

    $ openstack network segment list --network multisegment1
    +--------------------------------------+----------+--------------------------------------+--------------+---------+
    | ID                                   | Name     | Network                              | Network Type | Segment |
    +--------------------------------------+----------+--------------------------------------+--------------+---------+
    | 053b7925-9a89-4489-9992-e164c8cc8763 | segment2 | 6ab19caa-dda9-4b3d-abc4-5b8f435b98d9 | vlan         |    2017 |
    | 43e16869-ad31-48e4-87ce-acf756709e18 | segment1 | 6ab19caa-dda9-4b3d-abc4-5b8f435b98d9 | vlan         |    2016 |
    +--------------------------------------+----------+--------------------------------------+--------------+---------+
    
  6. segment1 段上创建子网。在此示例中,IPv4 子网使用 203.0.113.0/24,IPv6 子网使用 fd00:203:0:113::/64。

    $ openstack subnet create \
      --network multisegment1 --network-segment segment1 \
      --ip-version 4 --subnet-range 203.0.113.0/24 \
      multisegment1-segment1-v4
    +-------------------+--------------------------------------+
    | Field             | Value                                |
    +-------------------+--------------------------------------+
    | allocation_pools  | 203.0.113.2-203.0.113.254            |
    | cidr              | 203.0.113.0/24                       |
    | enable_dhcp       | True                                 |
    | gateway_ip        | 203.0.113.1                          |
    | id                | c428797a-6f8e-4cb1-b394-c404318a2762 |
    | ip_version        | 4                                    |
    | name              | multisegment1-segment1-v4            |
    | network_id        | 6ab19caa-dda9-4b3d-abc4-5b8f435b98d9 |
    | revision_number   | 1                                    |
    | segment_id        | 43e16869-ad31-48e4-87ce-acf756709e18 |
    | tags              | []                                   |
    +-------------------+--------------------------------------+
    
    $ openstack subnet create \
      --network multisegment1 --network-segment segment1 \
      --ip-version 6 --subnet-range fd00:203:0:113::/64 \
      --ipv6-address-mode slaac multisegment1-segment1-v6
    +-------------------+------------------------------------------------------+
    | Field             | Value                                                |
    +-------------------+------------------------------------------------------+
    | allocation_pools  | fd00:203:0:113::2-fd00:203:0:113:ffff:ffff:ffff:ffff |
    | cidr              | fd00:203:0:113::/64                                  |
    | enable_dhcp       | True                                                 |
    | gateway_ip        | fd00:203:0:113::1                                    |
    | id                | e41cb069-9902-4c01-9e1c-268c8252256a                 |
    | ip_version        | 6                                                    |
    | ipv6_address_mode | slaac                                                |
    | ipv6_ra_mode      | None                                                 |
    | name              | multisegment1-segment1-v6                            |
    | network_id        | 6ab19caa-dda9-4b3d-abc4-5b8f435b98d9                 |
    | revision_number   | 1                                    |
    | segment_id        | 43e16869-ad31-48e4-87ce-acf756709e18                 |
    | tags              | []                                                   |
    +-------------------+------------------------------------------------------+
    

    注意

    默认情况下,提供商网络上的 IPv6 子网依赖于物理网络基础设施进行无状态地址自动配置 (SLAAC) 和路由器通告。

  7. segment2 段上创建子网。在此示例中,IPv4 子网使用 198.51.100.0/24,IPv6 子网使用 fd00:198:51:100::/64。

    $ openstack subnet create \
      --network multisegment1 --network-segment segment2 \
      --ip-version 4 --subnet-range 198.51.100.0/24 \
      multisegment1-segment2-v4
    +-------------------+--------------------------------------+
    | Field             | Value                                |
    +-------------------+--------------------------------------+
    | allocation_pools  | 198.51.100.2-198.51.100.254          |
    | cidr              | 198.51.100.0/24                      |
    | enable_dhcp       | True                                 |
    | gateway_ip        | 198.51.100.1                         |
    | id                | 242755c2-f5fd-4e7d-bd7a-342ca95e50b2 |
    | ip_version        | 4                                    |
    | name              | multisegment1-segment2-v4            |
    | network_id        | 6ab19caa-dda9-4b3d-abc4-5b8f435b98d9 |
    | revision_number   | 1                                    |
    | segment_id        | 053b7925-9a89-4489-9992-e164c8cc8763 |
    | tags              | []                                   |
    +-------------------+--------------------------------------+
    
    $ openstack subnet create \
      --network multisegment1 --network-segment segment2 \
      --ip-version 6 --subnet-range fd00:198:51:100::/64 \
      --ipv6-address-mode slaac multisegment1-segment2-v6
    +-------------------+--------------------------------------------------------+
    | Field             | Value                                                  |
    +-------------------+--------------------------------------------------------+
    | allocation_pools  | fd00:198:51:100::2-fd00:198:51:100:ffff:ffff:ffff:ffff |
    | cidr              | fd00:198:51:100::/64                                   |
    | enable_dhcp       | True                                                   |
    | gateway_ip        | fd00:198:51:100::1                                     |
    | id                | b884c40e-9cfe-4d1b-a085-0a15488e9441                   |
    | ip_version        | 6                                                      |
    | ipv6_address_mode | slaac                                                  |
    | ipv6_ra_mode      | None                                                   |
    | name              | multisegment1-segment2-v6                              |
    | network_id        | 6ab19caa-dda9-4b3d-abc4-5b8f435b98d9                   |
    | revision_number   | 1                                                      |
    | segment_id        | 053b7925-9a89-4489-9992-e164c8cc8763                   |
    | tags              | []                                                     |
    +-------------------+--------------------------------------------------------+
    
  8. 验证每个 IPv4 子网是否与至少一个 DHCP 代理关联。

    $ openstack network agent list --agent-type dhcp --network multisegment1
    +--------------------------------------+------------+-------------+-------------------+-------+-------+--------------------+
    | ID                                   | Agent Type | Host        | Availability Zone | Alive | State | Binary             |
    +--------------------------------------+------------+-------------+-------------------+-------+-------+--------------------+
    | c904ed10-922c-4c1a-84fd-d928abaf8f55 | DHCP agent | compute0001 | nova              | :-)   | UP    | neutron-dhcp-agent |
    | e0b22cc0-d2a6-4f1c-b17c-27558e20b454 | DHCP agent | compute0101 | nova              | :-)   | UP    | neutron-dhcp-agent |
    +--------------------------------------+------------+-------------+-------------------+-------+-------+--------------------+
    
  9. 验证计算服务放置 API 中已为每个段 IPv4 子网创建了清单(为简洁起见,在此示例中仅显示一个段)。

    $ SEGMENT_ID=053b7925-9a89-4489-9992-e164c8cc8763
    $ openstack resource provider inventory list $SEGMENT_ID
    +----------------+------------------+----------+----------+-----------+----------+-------+
    | resource_class | allocation_ratio | max_unit | reserved | step_size | min_unit | total |
    +----------------+------------------+----------+----------+-----------+----------+-------+
    | IPV4_ADDRESS   |              1.0 |        1 |        2 |         1 |        1 |    30 |
    +----------------+------------------+----------+----------+-----------+----------+-------+
    
  10. 验证计算服务中已为每个段创建了主机聚合(为简洁起见,在此示例中仅显示一个段)。

    $ openstack aggregate list
    +----+---------------------------------------------------------+-------------------+
    | Id | Name                                                    | Availability Zone |
    +----+---------------------------------------------------------+-------------------+
    | 10 | Neutron segment id 053b7925-9a89-4489-9992-e164c8cc8763 | None              |
    +----+---------------------------------------------------------+-------------------+
    
  11. 启动一个或多个实例。每个实例根据其使用的计算节点上的段获取 IP 地址。

    注意

    如果用户在端口创建请求中指定了固定 IP,则该 IP 立即分配给端口。但是,将端口传递给实例的行为与传统网络不同。如果未在端口创建请求中指定固定 IP,则网络服务会延迟将 IP 地址分配给端口,直到出现特定的计算节点。例如

    $ openstack port create --network multisegment1 port1
    +-----------------------+--------------------------------------+
    | Field                 | Value                                |
    +-----------------------+--------------------------------------+
    | admin_state_up        | UP                                   |
    | binding_vnic_type     | normal                               |
    | id                    | 6181fb47-7a74-4add-9b6b-f9837c1c90c4 |
    | ip_allocation         | deferred                             |
    | mac_address           | fa:16:3e:34:de:9b                    |
    | name                  | port1                                |
    | network_id            | 6ab19caa-dda9-4b3d-abc4-5b8f435b98d9 |
    | port_security_enabled | True                                 |
    | revision_number       | 1                                    |
    | security_groups       | e4fcef0d-e2c5-40c3-a385-9c33ac9289c5 |
    | status                | DOWN                                 |
    | tags                  | []                                   |
    +-----------------------+--------------------------------------+
    

将非路由网络迁移到路由

只有当网络上只有一个段和一个子网时,才能迁移现有的非路由网络。要迁移候选网络,请更新子网并将现有网络段的 id 设置为 segment_id

注意

在存在多个子网或段的情况下,无法安全迁移。原因是,在非路由网络中,子网的分配池中的地址分配给端口,而不会考虑端口绑定到哪个网络段。

示例

以下步骤将现有的具有一个子网和一个段的非路由网络迁移到路由网络。

  1. 获取管理项目凭据。

  2. 获取要迁移的网络上当前网络段的 id

    $ openstack network segment list --network my_network
    +--------------------------------------+------+--------------------------------------+--------------+---------+
    | ID                                   | Name | Network                              | Network Type | Segment |
    +--------------------------------------+------+--------------------------------------+--------------+---------+
    | 81e5453d-4c9f-43a5-8ddf-feaf3937e8c7 | None | 45e84575-2918-471c-95c0-018b961a2984 | flat         | None    |
    +--------------------------------------+------+--------------------------------------+--------------+---------+
    
  3. 获取网络的当前子网的 idname

    $ openstack subnet list --network my_network
    +--------------------------------------+-----------+--------------------------------------+---------------+
    | ID                                   | Name      | Network                              | Subnet        |
    +--------------------------------------+-----------+--------------------------------------+---------------+
    | 71d931d2-0328-46ae-93bc-126caf794307 | my_subnet | 45e84575-2918-471c-95c0-018b961a2984 | 172.24.4.0/24 |
    +--------------------------------------+-----------+--------------------------------------+---------------+
    
  4. 验证当前子网的 segment_id 是否为 None

    $ openstack subnet show my_subnet --c segment_id
    +------------+-------+
    | Field      | Value |
    +------------+-------+
    | segment_id | None  |
    +------------+-------+
    
  5. 更新子网的 segment_id

    $ openstack subnet set --network-segment 81e5453d-4c9f-43a5-8ddf-feaf3937e8c7 my_subnet
    
  6. 验证子网现在是否与所需的网络段关联。

    $ openstack subnet show my_subnet --c segment_id
    +------------+--------------------------------------+
    | Field      | Value                                |
    +------------+--------------------------------------+
    | segment_id | 81e5453d-4c9f-43a5-8ddf-feaf3937e8c7 |
    +------------+--------------------------------------+
    

路由提供商网络作为租户路由网络的外部网络

注意

本节仅适用于传统路由器,不适用于 DVR 或 HA 路由器。传统路由器具有在单个主机上托管的单个实例。

此功能的一个后果是路由操作的外部化。段之间的通信是通过底层网络基础设施完成的,不由 Neutron 管理。

用户可能需要将通信拆分到多个主机。可以创建租户网络并使用路由器连接它们。要访问路由提供商网络,应将其连接为路由器网关。

Tenant net1  ┌─────────────────────┐
─────────────┤                                                        Routed provided network
                          GW port ├────────────────────────
Tenant net2                       │
─────────────┤                                  └─────────────────────┘

充当路由器网关的路由提供商网络包含与所有段关联的所有子网。在没有路由提供商网络的部署中,网关端口具有与所有子网 CIDR 的 L2 连接。在这种情况下,网关端口仅具有与附加段子网及其 L2 广播域的连接。

L3 代理将在路由器命名空间内,在网关端口固定 IP CIDR 中创建一个默认路由。对于不属于端口固定 IP 地址的其他每个子网,将创建一个 onlink 路由。这些路由使用网关端口作为路由设备,并允许通过此端口路由具有这些 CIDR 目标地址的任何数据包。

将网关端口连接到路由提供商网络的问题在于,它仅对属于主机段的那些子网具有广播连接

  • 其中一个子网将提供端口 IP 地址。此子网的网关 IP 地址将是默认路由,通过网关端口。

  • 属于此段的任何其他子网都将创建一个 onlink 路由,使用网关端口作为路由设备。

例如,考虑以下配置

  • 两个租户网络,CIDR 为 10.1.0.0/24 和 10.2.0.0/24。

  • 一个 RPN,具有两个段;每个段有两个子网:段 1 具有 10.51.0.0/24 和 10.52.0.0/24,段 2 具有 10.53.0.0/24 和 10.54.0.0/24。

  • 路由器连接到第一个段,网关端口具有 10.51.0.0/24 范围内的 IP 地址。这就是为什么默认路由使用此范围内的 IP 地址。

不考虑网关网络是路由器提供商网络,这是在路由器命名空间中设置的路由表

$ ip netns exec $r ip r
default via 10.51.0.1 dev qg-gwport proto static
10.1.0.0/24 dev qr-tenant1 proto kernel scope link src 10.1.0.1
10.2.0.0/24 dev qr-tenant2 proto kernel scope link src 10.2.0.1
10.51.0.0/24 dev qg-gwport proto kernel scope link src 10.100.0.15
10.52.0.0/24 dev qg-gwport proto static scope link
10.53.0.0/24 dev qg-gwport proto static scope link  <-- should be removed, belongs to segment 2
10.54.0.0/24 dev qg-gwport proto static scope link  <-- should be removed, belongs to segment 2

发送到 10.53.0.0/24 和 10.54.0.0/24(第二个 RPN 子网 CIDR)的数据包没有 L2 连接,并且 ARP 数据包不会收到回复。在具有 RPN 作为网关网络的情况下,通过网关发出的所有数据包都必须发送到网关 IP 地址,在本例中为 10.51.0.1。这就是为什么 L3 插件在

  • 网络是路由器网关。

  • 启用了“segments”插件;此插件是路由提供商网络所必需的。

  • 网络连接到段。

每个主机上的多个路由提供商段

从 2023.1(Antelope)开始,路由提供商网络的支持已得到增强,可以处理每个主机上的多个段。主要后果是运营商可以在不创建多个网络和/或增加广播域的情况下扩展 IP 池。

注意

目前仅支持 OVS 代理。

  1. 在给定的提供商网络上,创建一个第二个段。在此示例中,第二个段使用 provider1 物理网络和 VLAN ID 2020。

    $ openstack network segment create --physical-network provider1 \
      --network-type vlan --segment 2020 --network multisegment1 segment1-2
    +------------------+--------------------------------------+
    | Field            | Value                                |
    +------------------+--------------------------------------+
    | description      | None                                 |
    | headers          |                                      |
    | id               | 333b7925-9a89-4489-9992-e164c8cc8764 |
    | name             | segment1-2                           |
    | network_id       | 6ab19caa-dda9-4b3d-abc4-5b8f435b98d9 |
    | network_type     | vlan                                 |
    | physical_network | provider1                            |
    | revision_number  | 1                                    |
    | segmentation_id  | 2020                                 |
    | tags             | []                                   |
    +------------------+--------------------------------------+
    
  2. segment1-2 段上创建子网。在此示例中,IPv4 子网使用 203.0.114.0/24。

     $ openstack subnet create \
      --network multisegment1 --network-segment segment1-2 \
      --ip-version 4 --subnet-range 203.0.114.0/24 \
      multisegment1-segment1-2
    +-------------------+--------------------------------------+
    | Field             | Value                                |
    +-------------------+--------------------------------------+
    | allocation_pools  | 203.0.114.2-203.0.114.254            |
    | cidr              | 203.0.114.0/24                       |
    | enable_dhcp       | True                                 |
    | gateway_ip        | 203.0.114.1                          |
    | id                | c428797a-6f8e-4cb1-b394-c404318a2762 |
    | ip_version        | 4                                    |
    | name              | multisegment1-segment1-2             |
    | network_id        | 6ab19caa-dda9-4b3d-abc4-5b8f435b98d9 |
    | revision_number   | 1                                    |
    | segment_id        | 333b7925-9a89-4489-9992-e164c8cc8764 |
    | tags              | []                                   |
    +-------------------+--------------------------------------+
    

考虑到,对于给定的提供商网络 provider1 耗尽可用 IP 地址时,Neutron 将自动切换到子网 multisegment1-segment1-2