用例:租户网络的全局 IPv6 连接性

动机

在 IPv6 中,强烈不推荐使用 NAT,目的是允许主机之间的直接端到端连接。因此,Neutron 实现不提供创建浮动 IPv6 地址的机制。

因此,项目希望直接连接到其实例的全局路由 IPv6 地址。如果继续允许项目选择自己喜欢的地址范围,这将很难实现,因此有两种可能的解决方案

  1. 设置一个共享网络,您的实例将直接连接到该网络,并使用公共 IPv6 前缀配置此网络(提供商网络)。这样,实例将获得一个可以无限制使用的公共 IPv6 地址。

  2. 配置一个包含公共 IPv6 前缀范围的子网池,以便项目可以通过请求该子网池中的切片而不是选择自己的方式来配置自己的网络。

选项 1 有一些缺点,但

  • 它将所有项目置于单个共享网络中,使诸如每个项目的防火墙规则或 rDNS 管理之类的操作变得复杂。

  • 如果您想为您的实例提供双栈(即同时提供 IPv4 和 IPv6 连接),则需要使用两个不同的网络并将您的实例连接到这两个网络,或者您需要为每个实例分配一个公共 IPv4 地址,这可能被认为是一种浪费资源的方法来处理这种稀缺资源。

因此,本文档将描述如何通过部署动态路由来设置选项 2。

准备工作

地址范围

首先设置一个地址范围,BGP 代理将使用该地址范围来选择要在 BGP 会话中通告的前缀集合。本节中显示的所有命令都需要您使用管理员凭据

$ openstack address scope create --share --ip-version 6 ipv6-global
+------------+--------------------------------------+
| Field      | Value                                |
+------------+--------------------------------------+
| id         | ee2ee196-156c-424e-81e5-4d029c66190a |
| ip_version | 6                                    |
| name       | ipv6-global                          |
| project_id | 6de6f29dcf904ab8a12e8ca558f532e9     |
| shared     | True                                 |
+------------+--------------------------------------+

子网池

接下来,创建项目将用于配置其子网的子网池。对于实际部署,请使用全局可路由的网络前缀,而不是本示例中使用的文档前缀

$ openstack subnet pool create --address-scope ipv6-global --share --default \
>   --pool-prefix 2001:db8:1234::/48 --default-prefix-length 64 \
>   --min-prefix-length 64 --max-prefix-length 124 default-pool-ipv6
+-------------------+--------------------------------------+
| Field             | Value                                |
+-------------------+--------------------------------------+
| address_scope_id  | ee2ee196-156c-424e-81e5-4d029c66190a |
| created_at        | 2017-02-24T15:28:27Z                 |
| default_prefixlen | 64                                   |
| default_quota     | None                                 |
| description       |                                      |
| id                | 4c1661ba-b24c-4fda-8815-3f1fd29281af |
| ip_version        | 6                                    |
| is_default        | True                                 |
| max_prefixlen     | 124                                  |
| min_prefixlen     | 64                                   |
| name              | default-pool-ipv6                    |
| prefixes          | 2001:db8:1234::/48                   |
| project_id        | 6de6f29dcf904ab8a12e8ca558f532e9     |
| revision_number   | 1                                    |
| shared            | True                                 |
| updated_at        | 2017-02-24T15:28:27Z                 |
+-------------------+--------------------------------------+

公共网络

您的公共网络(项目路由器网关端口将连接到的网络)需要配置为

对于现有的部署,您通常已经定义了一个使用公共 IPv4 地址用于浮动 IP 和路由器网关端口的网络。这是需要添加 IPv6 子网的网络,使用与上述子网池相同的地址范围。

如果您还没有这样的网络,可以使用以下命令创建它:

$ openstack network create --provider-network-type flat --provider-physical-network public --external public
<output skipped>

您需要指定的具体参数取决于您的部署,超出本文档的范围,请参阅 Neutron 文档以获取更多详细信息。

现在有三种不同的选项可以确保您在公共网络上拥有一个 IPv6 子网,该子网与所需的地址范围相关联

使用共享子网池

从上述共享子网池在公共网络上创建 IPv6 子网

$ openstack subnet create --ip-version 6 --use-default-subnet-pool --network public public-ip6
+-------------------+----------------------------------------------------------+
| Field             | Value                                                    |
+-------------------+----------------------------------------------------------+
| allocation_pools  | 2001:db8:1234::2-2001:db8:1234:0:ffff:ffff:ffff:ffff     |
| cidr              | 2001:db8:1234::/64                                       |
| created_at        | 2017-02-27T10:23:00Z                                     |
| description       |                                                          |
| dns_nameservers   |                                                          |
| enable_dhcp       | True                                                     |
| gateway_ip        | 2001:db8:1234::1                                         |
| host_routes       |                                                          |
| id                | 77551166-fb97-4ea5-912a-c17c75a05eda                     |
| ip_version        | 6                                                        |
| ipv6_address_mode | None                                                     |
| ipv6_ra_mode      | None                                                     |
| name              | public-ip6                                               |
| network_id        | 28c08355-cb8f-4b1b-b5fd-f5442e531b28                     |
| project_id        | 6de6f29dcf904ab8a12e8ca558f532e9                         |
| revision_number   | 2                                                        |
| segment_id        | None                                                     |
| service_types     |                                                          |
| subnetpool_id     | 56a1b34b-7e0a-4a76-aac9-8893314ee2a4                     |
| updated_at        | 2017-02-27T10:23:00Z                                     |
+-------------------+----------------------------------------------------------+

使用专用子网池

创建一个包含您想要用于公共网络的特定前缀的第二个子网池

$ openstack subnet pool create --address-scope ipv6-global --pool-prefix 2001:db8:4321:42::/64 --default-prefix-length 64 public-pool
+-------------------+--------------------------------------+
| Field             | Value                                |
+-------------------+--------------------------------------+
| address_scope_id  | ee2ee196-156c-424e-81e5-4d029c66190a |
| created_at        | 2017-02-27T10:13:38Z                 |
| default_prefixlen | 64                                   |
| default_quota     | None                                 |
| description       |                                      |
| id                | 56a1b34b-7e0a-4a76-aac9-8893314ee2a4 |
| ip_version        | 6                                    |
| is_default        | False                                |
| max_prefixlen     | 128                                  |
| min_prefixlen     | 64                                   |
| name              | public-pool                          |
| prefixes          | 2001:db8:4321:42::/64                |
| project_id        | 6de6f29dcf904ab8a12e8ca558f532e9     |
| revision_number   | 1                                    |
| shared            | False                                |
| updated_at        | 2017-02-27T10:13:38Z                 |
+-------------------+--------------------------------------+

在公共网络上创建 IPv6 子网

$ openstack subnet create --ip-version 6 --subnet-pool public-pool --network public public-ip6
+-------------------+----------------------------------------------------------+
| Field             | Value                                                    |
+-------------------+----------------------------------------------------------+
| allocation_pools  | 2001:db8:4321:42::2-2001:db8:4321:42:ffff:ffff:ffff:ffff |
| cidr              | 2001:db8:4321:42::/64                                    |
| created_at        | 2017-02-27T10:23:00Z                                     |
| description       |                                                          |
| dns_nameservers   |                                                          |
| enable_dhcp       | True                                                     |
| gateway_ip        | 2001:db8:4321:42::1                                      |
| host_routes       |                                                          |
| id                | 77551166-fb97-4ea5-912a-c17c75a05eda                     |
| ip_version        | 6                                                        |
| ipv6_address_mode | None                                                     |
| ipv6_ra_mode      | None                                                     |
| name              | public-ip6                                               |
| network_id        | 28c08355-cb8f-4b1b-b5fd-f5442e531b28                     |
| project_id        | 6de6f29dcf904ab8a12e8ca558f532e9                         |
| revision_number   | 2                                                        |
| segment_id        | None                                                     |
| service_types     |                                                          |
| subnetpool_id     | 56a1b34b-7e0a-4a76-aac9-8893314ee2a4                     |
| updated_at        | 2017-02-27T10:23:00Z                                     |
+-------------------+----------------------------------------------------------+

使用子网入职

如果您已在 Neutron 部署中启用了 subnet_onboard 扩展,那么有一个更简单的选项,即简单地将公共网络上的现有 IPv6 子网入职到上述默认 IPv6 子网池

$ openstack network onboard subnets public default-pool-ipv6
$ # This command does not generate any output

验证地址范围

在使用上述选项之一创建公共 IPv6 子网后,验证公共网络的 IPv6 地址范围是否已设置

$ openstack network show public
+---------------------------+--------------------------------------+
| Field                     | Value                                |
+---------------------------+--------------------------------------+
| admin_state_up            | UP                                   |
| availability_zone_hints   |                                      |
| availability_zones        |                                      |
| created_at                | 2017-02-27T10:21:04Z                 |
| description               |                                      |
| dns_domain                | None                                 |
| id                        | 28c08355-cb8f-4b1b-b5fd-f5442e531b28 |
| ipv4_address_scope        | None                                 |
| ipv6_address_scope        | ee2ee196-156c-424e-81e5-4d029c66190a |
| is_default                | False                                |
| mtu                       | 1500                                 |
| name                      | public                               |
| port_security_enabled     | True                                 |
| project_id                | 6de6f29dcf904ab8a12e8ca558f532e9     |
| provider:network_type     | flat                                 |
| provider:physical_network | external                             |
| provider:segmentation_id  | None                                 |
| qos_policy_id             | None                                 |
| revision_number           | 6                                    |
| router:external           | External                             |
| segments                  | None                                 |
| shared                    | False                                |
| status                    | ACTIVE                               |
| subnets                   | 77551166-fb97-4ea5-912a-c17c75a05eda |
| updated_at                | 2017-02-27T10:23:00Z                 |
+---------------------------+--------------------------------------+

注意

公共子网和租户子网使用相同的地址范围至关重要。如果存在不匹配,BGP 通告将不会发生,并且连接将中断。

动态路由设置

现在您已经准备好了网络配置,下一步是配置动态路由部分。首先将服务插件添加到您的 neutron.conf 文件中。请注意,根据您的部署,可能已经配置了其他插件,请保持这些插件不变,只需添加 BGP 插件

[DEFAULT]
# You may have other plugins enabled here depending on your environment
# Important thing is you add the BgpPlugin to the list
service_plugins = neutron_dynamic_routing.services.bgp.bgp_plugin.BgpPlugin,neutron.services.l3_router.l3_router_plugin.L3RouterPlugin
# In case you run into issues, this will also be helpful
debug = true

您需要重新启动 Neutron 服务才能激活该插件。

现在您可以创建您的第一个 BGP 扬声器。将 IP 版本设置为 6,选择一个可用于此 POC 的私有 ASN,并禁用通告浮动 IP

$ openstack bgp speaker create --ip-version 6 --local-as 65000 --no-advertise-floating-ip-host-routes bgp1
+-----------------------------------+--------------------------------------+
| Field                             | Value                                |
+-----------------------------------+--------------------------------------+
| advertise_floating_ip_host_routes | False                                |
| advertise_tenant_networks         | True                                 |
| id                                | b9547458-7bdd-4738-bd57-a985055fc59c |
| ip_version                        | 6                                    |
| local_as                          | 65000                                |
| name                              | bgp1                                 |
| networks                          | []                                   |
| peers                             | []                                   |
| project_id                        | c67d6ba16ea2484597061245e5258c1e     |
+-----------------------------------+--------------------------------------+

将公共网络添加到此扬声器,指示您希望通告所有具有公共网络作为网关的路由器处的这些租户网络

$ openstack bgp speaker add network bgp1 public
$ # This command does not generate any output

假设您的外部路由器地址为 2001:db8:4321:e0::1,将其配置为 BGP 对等体并将其添加到 BGP 扬声器

$ openstack bgp peer create --peer-ip 2001:db8:4321:e0::1 --remote-as 65001 bgp-peer1
+------------+--------------------------------------+
| Field      | Value                                |
+------------+--------------------------------------+
| auth_type  | none                                 |
| id         | 0183260e-b1d0-40ae-994f-075668b99676 |
| name       | bgp-peer1                            |
| peer_ip    | 2001:db8:4321:e0::1                  |
| project_id | c67d6ba16ea2484597061245e5258c1e     |
| remote_as  | 65001                                |
| tenant_id  | c67d6ba16ea2484597061245e5258c1e     |
+------------+--------------------------------------+
$ openstack bgp speaker add peer bgp1 bgp-peer1
$ # This command does not generate any output

现在配置 Neutron BGP 代理,将以下数据添加到您的 bgp_dragent.ini 配置文件中

[BGP]
bgp_speaker_driver = neutron_dynamic_routing.services.bgp.agent.driver.os_ken.driver.OsKenBgpDriver

# 32-bit BGP identifier, typically an IPv4 address owned by the system running
# the BGP DrAgent.
bgp_router_id = 192.0.2.42

您将再次不得不重新启动代理才能使其获取新的配置。如果一切顺利,代理应该在您的设置中注册自身

$ openstack network agent list --agent-type bgp
+--------------------------------------+---------------------------+--------------+-------------------+-------+-------+---------------------+
| ID                                   | Agent Type                | Host         | Availability Zone | Alive | State | Binary              |
+--------------------------------------+---------------------------+--------------+-------------------+-------+-------+---------------------+
| 68d6e83c-db04-4711-b031-44cf3fb51bb7 | BGP dynamic routing agent | network-node | None              | :-)   | UP    | neutron-bgp-dragent |
+--------------------------------------+---------------------------+--------------+-------------------+-------+-------+---------------------+

作为最后一步,使用上述代理 ID 并告诉代理它应该托管我们的 BGP 扬声器

$ openstack bgp dragent add speaker 68d6e83c-db04-4711-b031-44cf3fb51bb7 bgp1
$ # This command does not generate any output

外部视角

最后一步是配置您的外部路由器以接受来自 Neutron 动态路由代理的 BGP 会话,以便它可以接收前缀通告并相应地转发流量。

在此示例中,我们假设一个运行 [BIRD](http://bird.network.cz/) 的系统,我们配置它作为 BGP 会话的远程端,如下所示

protocol bgp bgp1 {
  description "Neutron agent";
  passive on;
  local 2001:db8:4321:e0::1 as 65001;
  neighbor 2001:db8:4321:e0::42 as 65000;
}

验证会话是否按预期建立

bird> show proto bgp1
name     proto    table    state  since       info
bgp1     BGP      master   up     00:01:50    Established

租户网络

现在您已经准备好了管理端的一切,让我们看看您的用户应该如何配置他们的网络。本节中的命令应使用用户凭据执行

$ openstack network create mynet
+---------------------------+--------------------------------------+
| Field                     | Value                                |
+---------------------------+--------------------------------------+
| admin_state_up            | UP                                   |
| availability_zone_hints   |                                      |
| availability_zones        |                                      |
| created_at                | 2017-02-27T10:26:22Z                 |
| description               |                                      |
| dns_domain                | None                                 |
| id                        | 1f20da97-ddd4-40f8-b8d3-6321de8671a0 |
| ipv4_address_scope        | None                                 |
| ipv6_address_scope        | None                                 |
| is_default                | None                                 |
| mtu                       | 1500                                 |
| name                      | mynet                                |
| port_security_enabled     | True                                 |
| project_id                | 6de6f29dcf904ab8a12e8ca558f532e9     |
| provider:network_type     | None                                 |
| provider:physical_network | None                                 |
| provider:segmentation_id  | None                                 |
| qos_policy_id             | None                                 |
| revision_number           | 3                                    |
| router:external           | Internal                             |
| segments                  | None                                 |
| shared                    | False                                |
| status                    | ACTIVE                               |
| subnets                   |                                      |
| updated_at                | 2017-02-27T10:26:22Z                 |
+---------------------------+--------------------------------------+

为了添加 IPv6 前缀,只需从默认池请求一个

$ openstack subnet create --ip-version 6 --use-default-subnet-pool \
> --ipv6-address-mode slaac --ipv6-ra-mode slaac --network mynet mysubnet
+------------------------+--------------------------------------------------------+
| Field                  | Value                                                  |
+------------------------+--------------------------------------------------------+
| allocation_pools       | 2001:db8:1234:1::2-2001:db8:1234:1:ffff:ffff:ffff:ffff |
| cidr                   | 2001:db8:1234:1::/64                                   |
| created_at             | 2017-02-27T11:14:23Z                                   |
| description            |                                                        |
| dns_nameservers        |                                                        |
| enable_dhcp            | True                                                   |
| gateway_ip             | 2001:db8:1234:1::1                                     |
| host_routes            |                                                        |
| id                     | 193f7620-6c4c-4adc-9bb5-ff73c9b08d59                   |
| ip_version             | 6                                                      |
| ipv6_address_mode      | slaac                                                  |
| ipv6_ra_mode           | slaac                                                  |
| name                   | mysubnet                                               |
| network_id             | 1f20da97-ddd4-40f8-b8d3-6321de8671a0                   |
| project_id             | 6de6f29dcf904ab8a12e8ca558f532e9                       |
| revision_number        | 2                                                      |
| segment_id             | None                                                   |
| service_types          |                                                        |
| subnetpool_id          | 4c1661ba-b24c-4fda-8815-3f1fd29281af                   |
| updated_at             | 2017-02-27T11:14:23Z                                   |
| use_default_subnetpool | true                                                   |
+------------------------+--------------------------------------------------------+

为了外部连接,创建一个路由器,将一个接口添加到您的项目网络,并将网关设置为公共网络

$ openstack router create router1
+-------------------------+--------------------------------------+
| Field                   | Value                                |
+-------------------------+--------------------------------------+
| admin_state_up          | UP                                   |
| availability_zone_hints |                                      |
| availability_zones      |                                      |
| created_at              | 2017-02-27T12:59:06Z                 |
| description             |                                      |
| distributed             | False                                |
| external_gateway_info   | None                                 |
| flavor_id               | None                                 |
| ha                      | False                                |
| id                      | d2db0603-fda2-4305-a1de-e793a36c0770 |
| name                    | router1                              |
| project_id              | 6de6f29dcf904ab8a12e8ca558f532e9     |
| revision_number         | None                                 |
| routes                  |                                      |
| status                  | ACTIVE                               |
| updated_at              | 2017-02-27T12:59:06Z                 |
+-------------------------+--------------------------------------+
$ openstack router add subnet router1 mysubnet
$ openstack router set --external-gateway public router1

最后,启动一个实例并验证是否为其分配了 IPv6 地址

$ openstack server create --flavor c1 --image cirros vm1
$ openstack server list
+--------------------------------------+------+--------+-------------+--------------------------------------------+------------+
| ID                                   | Name | Status | Power State | Networks                                   | Image Name |
+--------------------------------------+------+--------+-------------+--------------------------------------------+------------+
| 17b2ac04-9a17-45ff-be30-401aa8331a66 | vm1  | ACTIVE | Running     | mynet=2001:db8:1234:1:f816:3eff:fe53:f89e  | cirros     |
+--------------------------------------+------+--------+-------------+--------------------------------------------+------------+
$ openstack console log show vm1 | grep -A1 -B1 2001
eth0      Link encap:Ethernet  HWaddr FA:16:3E:53:F8:9E
          inet6 addr: 2001:db8:1234:1:f816:3eff:fe53:f89e/64 Scope:Global
          inet6 addr: fe80::f816:3eff:fe53:f89e/64 Scope:Link

注意

大多数云镜像构建为坚持通过 DHCP 接收 IPv4 地址,因此在启动过程中会有相当大的延迟,等待它进入超时。为了避免由此产生的延迟,您可以将 IPv4 子网添加到您的项目网络。

注意

对于访问计算服务提供的元数据的访问,也有类似的担忧。虽然 Neutron 确实提供了通过 IPv6 访问元数据的选项,但这并非在所有部署中都可用,并且并非所有云镜像都支持。您可以添加 IPv4 子网(如上述)或使用 config drive 选项来为您的实例提供元数据来解决此问题。

验证

作为管理员,您现在可以验证租户网络是否已列出以进行通告

$ openstack bgp speaker list advertised routes bgp1
+----+--------------------+---------------------+
| ID | Destination        | Nexthop             |
+----+--------------------+---------------------+
|    | 2001:db8:1234::/64 | 2001:db8:4321:42::c |
+----+--------------------+---------------------+

并验证它是否在您的外部路由器上可见

bird> show route 2001:db8:1234:1::/64
2001:db8:1234:1::/64 via 2001:db8:4321:2::5 on ens3 [bgp1 12:06:50 from 2001:db8:4321:e0::42] * (100/0) [i]

作为额外的奖励,验证实例是否可以从路由器访问

router01:~$ ping6 -c3  2001:db8:1234:1:f816:3eff:fecd:6bf4
PING 2001:db8:1234:1:f816:3eff:fecd:6bf4(2001:db8:1234:1:f816:3eff:fecd:6bf4) 56 data bytes
64 bytes from 2001:db8:1234:1:f816:3eff:fecd:6bf4: icmp_seq=1 ttl=63 time=1.80 ms
64 bytes from 2001:db8:1234:1:f816:3eff:fecd:6bf4: icmp_seq=2 ttl=63 time=0.724 ms
64 bytes from 2001:db8:1234:1:f816:3eff:fecd:6bf4: icmp_seq=3 ttl=63 time=1.04 ms

--- 2001:db8:1234:1:f816:3eff:fecd:6bf4 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.724/1.190/1.803/0.454 ms
router01:~$ ssh -6 2001:db8:1234:1:f816:3eff:fe58:f80a -l cirros
cirros@2001:db8:1234:1:f816:3eff:fe58:f80a's password:
$