Neutron 终于不“浪费”公网 IP深度解析
一直以来,很多用户对于 Neutron “浪费”公网 IP 一事比较诟病,什么是“浪费”公网 IP呢? 那Neutron社区当前又是怎么解决的呢
浪费原因分析
我们知道,Neutron 中将外部网络中的子网作为公网 IP 池,大体分为两个功能:
- 当路由器开启公网网关时,从 IP 池中通过 IPAM 获取 IP 地址提供 1:N SNAT 功能;
- 在路由器开启公网网关后,从 IP 池中通过 IPAM 获取 IP 地址,将此地址绑定到虚拟机或者负载均衡器上,提供 1:1 NAT (DNAT 和 SNAT)功能。
这样带来的问题是,如果只想给虚拟机或负载均衡器绑定公网 IP 的话,势必“多使用”一个公网 IP 作为路由器开启公网网关使用,在公网 IP 较为紧缺的环境中,“多使用”的公网 IP 就造成了一定程度的“浪费”。
- 还需指出的是,公网 IP 的“浪费”还体现在了 DVR 场景下。
DVR 场景下,当某个计算节点上的虚拟机绑定了公网 IP,Neutron L3 Agent 会在该计算节点上创建 fip-[external-network-id] 为名称的 namespace,并在此 namespace 中创建 fg 设备,在该设备上绑定一个公网 IP,作为路由(将本地的公网 IP 路由出本计算节点)使用。
- fg 设备上的公网 IP 一定程度上也造成了公网 IP 的“浪费”。
Newton 解决方式
在最新的 Newton 版中,Neutron 引入了 “Service Subnet” 解决了上述问题。什么是 Service Subnet?
简单的讲,就是“专网专用”。在 Subnet 资源中添加了 “service_types” 属性,该属性决定了该 Subnet作为何用。哪种属性如何确定?和 Port 的“device_owner” 属性保持一致即可。
对于传统 legacy 路由器来说,当路由器开启公网网关后,会创建一个 device_owner 为 “network:router_gateway”的 port,此 port 即为虚拟路由器的 qg 设备,该设备上配置了 1:N 的 SNAT 地址和 1:1 NAT(DNAT 和 SNAT) 的地址;
对于 DVR 路由器来说,当路由器开启公网网关后,会创建一个 device_owner 为 “network:router_centralized_snat”的 port 作为 1:N SNAT 使用,当虚拟机绑定公网 IP 后,创建 device_owner 为 “network:floatingip_agent_gateway”的 port 作为计算节点上路由使用;
对于 HA 路由器来说,路由器开启网关时创建的 port 和传统 legacy 路由器相同。
因此,我们可以创建一个 service_type 为 network:router_gateway 的 Subnet 作为为 legacy 和 HA 路由器开启公网网关使用,和一个 service_type 为 network:floatingip 的 Subnet 作为申请 FloatingIP 使用。
使用过程
这里我将创建一个外部网络(External Network),并在其中创建两个 Subnet,一个作为路由器开启公网网关使用,另一个作为 FloatingIP 使用。
创建 flat 类型的外部网络:
在上述创建的外部网络中创建两个 Service Subnet:
创建一个 legacy 类型的路由器,并开启公网网关:
通过命令可以看到,Neutron 为该路由器分配了一个 10.10.10.7 的 IP 地址,作为网关使用:
申请 FloatingIP :
可以看到 Neutron 从 service_type 为 network:floatingip 的 Subnet 中分配了一个 IP。
最后,在路由器上关联子网,并在子网中创建一个虚拟机,并且将上述申请的 FloatingIP 与其绑定。
观察 router namespace 中 IP 地址和路由:
qg 设备上配置了 1:N SNAT 的地址和 1:1 NAT 的地址,需要注意的是,虚拟路由器中的默认路由,依旧是 service_type 为 network:router_gateway 的 Subnet 的网关地址,因此在实际环境中,我们只需确保该网关地址可达即可。
以上就是 Service Subnet 的简单应用。
本次测试使用的 Neutron 代码为 master 最新代码,在使用过程中遇到一个 bug(https://bugs.launchpad.net/neutron/+bug/1637366)讨论邮件在此(http://osdir.com/ml/openstack-dev/2016-10/msg01477.html),为了避免此 bug 因此 revert 了这个patch (https://review.openstack.org/#/c/346217/3)。