理解 OpenStack 高可用(HA):Neutron 分布式虚拟路由(中)

在上一篇理解OpenStack 高可用(HA):Neutron 分布式虚拟路由(上)中,详细介绍了基础知识和Neutron的传统,本文详进行分析。

3. 安装和功能分析

3.1 安装和配置

Juno 版本中 DVR 的要求如下:

  • 使用 ML2 plugin
  • 使用 L2pop mechanism driver
  • 使用 Openvswitch mechanism driver, 安装 OVS agent 在所有的计算节点上
  • 所有的计算节点连接外网
  • Juno 中只支持 Tunnel 虚拟网络模式 (VXLAN or GRE)。 Kilo 版本中会增加 VLAN 模式的支持。

3.1.1 安装

使用两个结算节点。在每个计算节点上安装并配置 L3 Agent:

(1)修改系统配置


root@compute2:/var/log/nova# vi /etc/sysctl.conf
root@compute2:/var/log/nova# sysctl -p
net.ipv4.ip_forward = 1
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0

(2)安装 neutron-l3-agent: apt-get install neutron-l3-agent

(3)增加一块访问外网的网卡 eth3

(4)创建 OVS bridge:ovs-vsctl add-br br-ex

(5)增加新的网卡到该 bridge 上:ovs-vsctl add-port br-ex eth3

(6)配置 L3 Agent

interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver
use_namespaces = True
external_network_bridge = br-eth3

(7)配置 Metadata Agent

3.1.2 配置 DVR

控制节点 /etc/neutron/neutron.conf router_distributed = True 注意:需要设置 l3_ha = false 来禁用 VRRP
计算节点

/etc/neutron/l3_agent.ini

/etc/neutron/plugins/ml2/ml2_conf.ini

agent_mode = dvr

enable_distributed_routing = True

 
网络节点

/etc/neutron/l3_agent.ini

/etc/neutron/plugins/ml2/ml2_conf.ini

agent_mode = dvr_snat

enable_distributed_routing = True

 

注意还需要配置使用 l2_population。

对普通用户来说,neutron 会根据管理员在控制节点上的配置项 router_distributed 的值,来决定是创建普通 Router 还是 DVR Router;对管理员来说,还可以使用 –distributed {True,False} 参数来指定是否创建 DVR 模式的 router。

经过以上配置后的 neutron agent如下。可以看到,除了网络节点外,所有的计算介绍上也部署了 L3 Agent 和 Metadata Agent。

s1@controller:~$ neutron agent-list
+--------------------------------------+--------------------+----------+-------+----------------+---------------------------+
| id                                   | agent_type         | host     | alive | admin_state_up | binary                    |
+--------------------------------------+--------------------+----------+-------+----------------+---------------------------+
| 04c360d0-3066-4f04-9af2-d4ef8586ad2b | L3 agent           | network  | :-)   | True           | neutron-l3-agent          |
| 2ef04905-4a37-4de8-a8f0-9c6488a592b7 | Open vSwitch agent | network  | :-)   | True           | neutron-openvswitch-agent |
| 3f307355-2167-4b15-affa-9f296f698752 | DHCP agent         | network  | :-)   | True           | neutron-dhcp-agent        |
| 54609006-a769-4b17-b175-1a834e6e7a26 | Open vSwitch agent | compute1 | :-)   | True           | neutron-openvswitch-agent |
| 90c87c01-1cd1-48b0-8369-30f44c058574 | Loadbalancer agent | network  | :-)   | True           | neutron-lbaas-agent       |
| 951b8efc-1f2c-4a51-84d1-2261ff31c12c | Metadata agent     | compute2 | :-)   | True           | neutron-metadata-agent    |
| 99d13b27-89f8-4abe-bc03-3f69f5e7e0cc | Metadata agent     | network  | :-)   | True           | neutron-metadata-agent    |
| aa8cf021-7f3d-4667-9d92-4d77d4c4fb59 | L3 agent           | compute2 | :-)   | True           | neutron-l3-agent          |
| beec232b-48d7-4424-83e2-8cc4e49ec339 | L3 agent           | compute1 | :-)   | True           | neutron-l3-agent          |
| d65bbede-4b1d-4914-8c8b-ab591975828f | Metadata agent     | compute1 | :-)   | True           | neutron-metadata-agent    |
| e3f83dcf-27f2-4c91-bead-adebcab1e3c7 | Open vSwitch agent | compute2 | :-)   | True           | neutron-openvswitch-agent |
+--------------------------------------+--------------------+----------+-------+----------------+---------------------------+

3.2 DVR Router 流程

3.2.1 创建 DVR Router

(1)创建如下的 DVR Router:

理解 OpenStack 高可用(HA):Neutron 分布式虚拟路由(中)_第1张图片

可以看到该 router 被分布在neutron network 节点和计算节点上:

s1@controller:~$ neutron l3-agent-list-hosting-router dvr-r1
+--------------------------------------+----------+----------------+-------+
| id                                   | host     | admin_state_up | alive |
+--------------------------------------+----------+----------------+-------+
| 04c360d0-3066-4f04-9af2-d4ef8586ad2b | network  | True           | :-)   |
| beec232b-48d7-4424-83e2-8cc4e49ec339 | compute1 | True           | :-)   |
+--------------------------------------+----------+----------------+-------+

(2)网络节点上,创建了 SNAT network namespace。该 netns 中,对router 的每一个网络,都有一个 qg 或者 sg interface:

root@network:/home/s1# ip netns exec snat-e8f12f7a-6938-4e65-88c4-97e4cb211b27 ip addr
42: qg-32878e35-a2:  mtu 1500 qdisc noqueue state UNKNOWN group default #对应 port 1,连接外网
    link/ether fa:16:3e:4a:40:48 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.115/24 brd 192.168.1.255 scope global qg-32878e35-a2
       valid_lft forever preferred_lft forever
44: sg-4f80ec3d-f2:  mtu 1500 qdisc noqueue state UNKNOWN group default #对应 port 2,连接内网1
    link/ether fa:16:3e:82:a9:ca brd ff:ff:ff:ff:ff:ff
    inet 81.1.180.17/24 brd 81.1.180.255 scope global sg-4f80ec3d-f2
       valid_lft forever preferred_lft forever
46: sg-6c01abc3-5d:  mtu 1500 qdisc noqueue state UNKNOWN group default #对应 port 4,连接内网2
    link/ether fa:16:3e:47:55:00 brd ff:ff:ff:ff:ff:ff
    inet 91.1.180.16/24 brd 91.1.180.255 scope global sg-6c01abc3-5d
       valid_lft forever preferred_lft forever

root@network:/home/s1# ip netns exec snat-e8f12f7a-6938-4e65-88c4-97e4cb211b27 iptables -t nat -S
-A POSTROUTING -j neutron-l3-agent-POSTROUTING
-A POSTROUTING -j neutron-postrouting-bottom
-A neutron-l3-agent-POSTROUTING ! -i qg-32878e35-a2 ! -o qg-32878e35-a2 -m conntrack ! --ctstate DNAT -j ACCEPT
-A neutron-l3-agent-snat -s 81.1.180.0/24 -j SNAT --to-source 192.168.1.115
-A neutron-l3-agent-snat -s 91.1.180.0/24 -j SNAT --to-source 192.168.1.115
-A neutron-postrouting-bottom -j neutron-l3-agent-snat

以及 qrouter network namespace:

root@network:/home/s1# ip netns exec qrouter-e8f12f7a-6938-4e65-88c4-97e4cb211b27 ip addr
43: qr-517bdba3-b1: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default #对应 port 3
    link/ether fa:16:3e:63:3b:4c brd ff:ff:ff:ff:ff:ff
    inet 81.1.180.1/24 brd 81.1.180.255 scope global qr-517bdba3-b1
       valid_lft forever preferred_lft forever
45: qr-e47fca31-db: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default #对应 port 5
    link/ether fa:16:3e:a9:da:b5 brd ff:ff:ff:ff:ff:ff
    inet 91.1.180.1/24 brd 91.1.180.255 scope global qr-e47fca31-db
       valid_lft forever preferred_lft forever

root@network:/home/s1# ip netns exec qrouter-e8f12f7a-6938-4e65-88c4-97e4cb211b27 iptables -t nat -S
-A neutron-l3-agent-PREROUTING -d 169.254.169.254/32 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 9697
-A neutron-l3-agent-snat -j neutron-l3-agent-float-snat
-A neutron-postrouting-bottom -j neutron-l3-agent-snat

(3)在计算节点 compute1 上创建一个虚机

在 compute1 上生成了一个 qrouter network namespace:

root@compute1:/home/s1# ip netns exec qrouter-e8f12f7a-6938-4e65-88c4-97e4cb211b27 ip addr
29: qr-517bdba3-b1: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default #对应 port 3,作为 81.1.180.1/24 网段内的虚机的默认网关
    link/ether fa:16:3e:63:3b:4c brd ff:ff:ff:ff:ff:ff
    inet 81.1.180.1/24 brd 81.1.180.255 scope global qr-517bdba3-b1
       valid_lft forever preferred_lft forever
    inet6 fe80::f816:3eff:fe63:3b4c/64 scope link
       valid_lft forever preferred_lft forever
31: qr-e47fca31-db: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default #对应 port 5,作为 91.1.180.1/24 网段内的虚机的默认网关
    link/ether fa:16:3e:a9:da:b5 brd ff:ff:ff:ff:ff:ff
    inet 91.1.180.1/24 brd 91.1.180.255 scope global qr-e47fca31-db
       valid_lft forever preferred_lft forever
    inet6 fe80::f816:3eff:fea9:dab5/64 scope link
       valid_lft forever preferred_lft forever

root@compute1:/home/s1# ip netns exec qrouter-e8f12f7a-6938-4e65-88c4-97e4cb211b27 iptables -t nat -S
-A neutron-l3-agent-PREROUTING -d 169.254.169.254/32 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 9697

(4)给虚机分配一个浮动IP 后,compute1 上出现了 fip network namespace。该 netns 的命名规则是 fip-,这里的 external net 是指该浮动IP所在的外网的:

root@compute1:/home/s1# ip netns exec fip-557e9f0c-9c66-46da-b289-218d49c218d2 ip addr
2: fpr-e8f12f7a-6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 #该 port 和 qrouter 中的 rpf port 是一对 veth pair,各自配置了自己的 IP 地址
    link/ether 9a:d0:23:ba:d2:02 brd ff:ff:ff:ff:ff:ff
    inet 169.254.31.29/31 scope global fpr-e8f12f7a-6
       valid_lft forever preferred_lft forever
    inet6 fe80::98d0:23ff:feba:d202/64 scope link
       valid_lft forever preferred_lft forever
32: fg-9eeb3fb1-25: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
    link/ether fa:16:3e:22:2d:90 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.117/24 brd 192.168.1.255 scope global fg-9eeb3fb1-25
       valid_lft forever preferred_lft forever
    inet6 fe80::f816:3eff:fe22:2d90/64 scope link
       valid_lft forever preferred_lft forever


root@compute1:/home/s1# ip netns exec fip-557e9f0c-9c66-46da-b289-218d49c218d2 ip route
default via 192.168.1.1 dev fg-9eeb3fb1-25
169.254.31.28/31 dev fpr-e8f12f7a-6  proto kernel  scope link  src 169.254.31.29
192.168.1.0/24 dev fg-9eeb3fb1-25  proto kernel  scope link  src 192.168.1.117
192.168.1.116 via 169.254.31.28 dev fpr-e8f12f7a-6

而且,compute1 上的 qrouter netns 中的变化:

root@compute1:/home/s1# ip netns exec qrouter-e8f12f7a-6938-4e65-88c4-97e4cb211b27 ip addr
2: rfp-e8f12f7a-6:  mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 #该 port 和 fip 中的 pfr port 是一对 veth,各自配置了自己的 IP 地址,该地址来自 169.254.x.y 网段
    link/ether 42:81:66:11:60:66 brd ff:ff:ff:ff:ff:ff
    inet 169.254.31.28/31 scope global rfp-e8f12f7a-6
       valid_lft forever preferred_lft forever
    inet 192.168.1.116/32 brd 192.168.1.116 scope global rfp-e8f12f7a-6
       valid_lft forever preferred_lft forever

NAP iptables 规则:

-A neutron-l3-agent-OUTPUT -d 192.168.1.116/32 -j DNAT --to-destination 81.1.180.18
-A neutron-l3-agent-POSTROUTING ! -i rfp-e8f12f7a-6 ! -o rfp-e8f12f7a-6 -m conntrack ! --ctstate DNAT -j ACCEPT
-A neutron-l3-agent-PREROUTING -d 169.254.169.254/32 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 9697
-A neutron-l3-agent-PREROUTING -d 192.168.1.116/32 -j DNAT --to-destination 81.1.180.18
-A neutron-l3-agent-float-snat -s 81.1.180.18/32 -j SNAT --to-source 192.168.1.116

以及一条路由策略。具体见下文。

但是 neutron 网络节点上的 qrouter 上并没有增加该浮动 IP和相应的 NAT iptables 规则。

3.2 网络包走向分析

不同网段内的虚机之间或者虚机和计算机之间的网络流向可以分为几类:

  • 3.2.1 SNAT:当数据包离开 rouer 的 external device 时改变它的源 IP 地址。这在没有浮动IP 时虚机访问外网的情况下使用。
  • 3.2.2/3 FIP:有时候也称为 DNAT。当虚机的固定 IP分配了浮动 IP 的时候,虚机和外网中的虚机通信的时候使用。
  • 3.2.4 不同服务器上不同网段内的虚机之间的通信
  • 3.2.5 同一个服务器上不同网段内的虚机之间的通信

3.2.1 SNAT:虚机访问外网(没有分配浮动IP 的情况下)

Neuron 布网:

理解 OpenStack 高可用(HA):Neutron 分布式虚拟路由(中)_第2张图片

虚机(81.1.180.18)发出给外网中机器(192.168.1.20)的包,因为是跨网段的,先发给 compute1 上的 qrouter 的 qr-517bdba3-b1 interface。然后,qruoter 查路由表:

root@compute1:/home/s1# ip netns exec qrouter-e8f12f7a-6938-4e65-88c4-97e4cb211b27 ip rule
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default
1359066113:     from 81.1.180.1/24 lookup 1359066113
1526838273:     from 91.1.180.1/24 lookup 1526838273

root@compute1:/home/s1# ip netns exec qrouter-e8f12f7a-6938-4e65-88c4-97e4cb211b27 ip route list table 1359066113 #只有一个默认路由  
default via 81.1.180.17 dev qr-517bdba3-b1 #经过 qr 端口发到下一个路由器 81.1.180.17

查表结果是经过 interface qr-517bdba3-b1 将包发到下一个路由器 81.1.180.17,而这个IP 在 neutron 网络节点上的 SNAT netns 的 44: sg-4f80ec3d-f2 interface。在这里,先做 SNAT:

root@network:/home/s1# ip netns exec snat-e8f12f7a-6938-4e65-88c4-97e4cb211b27 iptables -t nat -S
-A neutron-l3-agent-POSTROUTING ! -i qg-32878e35-a2 ! -o qg-32878e35-a2 -m conntrack ! --ctstate DNAT -j ACCEPT
-A neutron-l3-agent-snat -s 81.1.180.0/24 -j SNAT --to-source 192.168.1.115 # 命中这条,把网络包的 Src IP 修改为 192.168.1.115
-A neutron-l3-agent-snat -s 91.1.180.0/24 -j SNAT --to-source 192.168.1.115
-A neutron-postrouting-bottom -j neutron-l3-agent-snat

然后查路由表确定下一跳:

root@network:/home/s1# ip netns exec snat-e8f12f7a-6938-4e65-88c4-97e4cb211b27 ip rule show #这里没定义额外的路由策略,直接查 main 路由表
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default
root@network:/home/s1# ip netns exec snat-e8f12f7a-6938-4e65-88c4-97e4cb211b27 ip route list table main
default via 192.168.1.1 dev qg-32878e35-a2
81.1.180.0/24 dev sg-4f80ec3d-f2  proto kernel  scope link  src 81.1.180.17 
91.1.180.0/24 dev sg-6c01abc3-5d  proto kernel  scope link  src 91.1.180.16
192.168.1.0/24 dev qg-32878e35-a2  proto kernel  scope link  src 192.168.1.115 #根据目的地址,命中这条,网络包从 qg 端口发出

结论:在没有设置浮动 IP (SNAT)的情况下,虚机访问外网时,虚机发出的网络包首先经过其所在的服务器上的 qrouter 做路由选择(81.1.180.1),然后再经过 neutron network 节点上的 snat network namespace (81.1.180.17)出去到外网。这个结论也和 traceroute 的结果互相验证:

图片描述

完整过程:

理解 OpenStack 高可用(HA):Neutron 分布式虚拟路由(中)_第3张图片

3.2.2 FIP:在虚机 81.1.180.18 上添加浮动IP,从它 ping 外网

Neutron 组网:

理解 OpenStack 高可用(HA):Neutron 分布式虚拟路由(中)_第4张图片

添加浮动 IP 后,虚机所在的主机上的 qrouter netns 上添加了浮动IP:

root@compute1:/home/s1# ip netns exec qrouter-e8f12f7a-6938-4e65-88c4-97e4cb211b27 ip addr
3: rfp-e8f12f7a-6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 46:ef:97:f4:4d:ff brd ff:ff:ff:ff:ff:ff
    inet 169.254.31.238/31 scope global rfp-e8f12f7a-6
       valid_lft forever preferred_lft forever
    inet 192.168.1.112/32 brd 192.168.1.112 scope global rfp-e8f12f7a-6
       valid_lft forever preferred_lft forever

还增加了一条路由策略及路由表:

root@compute1:/home/s1# ip netns exec qrouter-e8f12f7a-6938-4e65-88c4-97e4cb211b27 ip rule
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default
32769:  from 81.1.180.18 lookup 16 #每个固定 IP 对应一条路由策略,都查 ID 为 16 的路由表

root@compute1:/home/s1# ip netns exec qrouter-e8f12f7a-6938-4e65-88c4-97e4cb211b27 ip route list table 16
default via 169.254.31.239 dev rfp-e8f12f7a-6

(1)网络包从虚机触发,进入本服务器所在的 qrouter 的 qr interface,首先经过 DNAT,没有命中,然后查路由表,local,main,default 中没有命中的路由规则,查表 16,命中默认路由,需要经过 rfp 端口发到下一个路由器 169.254.31.239。

(2)rfp 端口是这样子:

3: rfp-e8f12f7a-6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 46:ef:97:f4:4d:ff brd ff:ff:ff:ff:ff:ff
    inet 169.254.31.238/31 scope global rfp-e8f12f7a-6
       valid_lft forever preferred_lft forever
    inet 192.168.1.112/32 brd 192.168.1.112 scope global rfp-e8f12f7a-6
       valid_lft forever preferred_lft forever

(3)该 rfp 和 fip netns 上的端口通过 veth 直接连接:

root@compute1:/home/s1# ip netns exec fip-557e9f0c-9c66-46da-b289-218d49c218d2 ip addr2: 
fpr-e8f12f7a-6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 9a:4d:66:1c:b5:2b brd ff:ff:ff:ff:ff:ff
    inet 169.254.31.239/31 scope global fpr-e8f12f7a-6
       valid_lft forever preferred_lft forever

(4)看 fip netns 的路由表,决定将其从 fg interface 发出去。

root@compute1:/home/s1# ip netns exec fip-557e9f0c-9c66-46da-b289-218d49c218d2 ip route
default via 192.168.1.1 dev fg-4a292fe1-58
169.254.31.238/31 dev fpr-e8f12f7a-6  proto kernel  scope link  src 169.254.31.239
192.168.1.0/24 dev fg-4a292fe1-58  proto kernel  scope link  src 192.168.1.118
192.168.1.112 via 169.254.31.238 dev fpr-e8f12f7a-6

(5)再经过 SNAT,经 Src 地址换成浮动 IP 地址:-A neutron-l3-agent-float-snat -s 81.1.180.18/32 -j SNAT –to-source 192.168.1.112

结论:配有浮动IP的虚机上 ping 外网,依次经过虚机所在的服务器上的 qrouter (81.1.180.1)和 fip netns (169.254.31.239) 到外网机器(192.168.1.20)。

图片描述

完整路径:

理解 OpenStack 高可用(HA):Neutron 分布式虚拟路由(中)_第5张图片

3.2.3 FIP:外网机器通过虚机的浮动 IP 访问虚机

外网中的机器首先要通过 ARP 获取虚机浮动 IP 对应的 MAC 地址。浮动 IP 并没有配置在 fip 的端口上,因此 fip 无法直接响应 ARP 请求,那怎么办呢?Neutron 在 fip NS 的 fg 端口上配置了 arp proxy,这样,fip 既可以响应它自己的 interface 上的 IP 地址的 ARP 请求,也可以响应能通过它路由到的 IP 地址的 ARP 请求。

(1)从下图可见,fip netns 的 fg-4a292fe1-58 interface 上配置了 ARP 代理:

理解 OpenStack 高可用(HA):Neutron 分布式虚拟路由(中)_第6张图片

root@compute1:/home/s1# ip netns exec fip-557e9f0c-9c66-46da-b289-218d49c218d2 sysctl net.ipv4.conf.fg-4a292fe1-58.proxy_arp
net.ipv4.conf.fg-4a292fe1-58.proxy_arp = 1

而 qrouter 的 interface 没有设置 arp proxy:
root@compute1:/home/s1# ip netns exec qrouter-e8f12f7a-6938-4e65-88c4-97e4cb211b27 sysctl net.ipv4.conf.rfp-e8f12f7a-6.proxy_arp
net.ipv4.conf.rfp-e8f12f7a-6.proxy_arp = 0

(2)fip netns 收到 ARP 请求后,将其 fg interface 的 MAC 地址返回。其实这是一个 MAC 地址欺骗,但是。。这就是一个 arp proxy 所起的作用。

外网中的机器获取到虚机浮动 IP 的 MAC 地址后,发出 ICMP 网络包(Dest IP: 192.168.1.112,Souce IP: 192.168.1.20,Dest MAC: fa:16:3e:95:55:29

(fip 的 fg interface 的 MAC 地址),Source MAC: MAC of 192.168.1.20):

(1)网络包经过 br-ex,被 fip 的 fg 端口收到,查路由表,命中最后一条路由,从其 fpr interface 发出,到达 169.254.31.238.

root@compute1:/home/s1# ip netns exec fip-557e9f0c-9c66-46da-b289-218d49c218d2 ip route
default via 192.168.1.1 dev fg-4a292fe1-58
169.254.31.238/31 dev fpr-e8f12f7a-6  proto kernel  scope link  src 169.254.31.239
192.168.1.0/24 dev fg-4a292fe1-58  proto kernel  scope link  src 192.168.1.118
192.168.1.112 via 169.254.31.238 dev fpr-e8f12f7a-6
17:38:41.462365 9a:4d:66:1c:b5:2b > 46:ef:97:f4:4d:ff, ethertype IPv4 (0x0800), length 98: (tos 0x0, flags [DF], proto ICMP (1), length 84)
    192.168.1.20 > 192.168.1.112: ICMP echo request, id 3138, seq 180, length 64

(2)被 veth 另一端的 qrouter 的 rfp-e8f12f7a-6 interface 收到。

3: rfp-e8f12f7a-6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 46:ef:97:f4:4d:ff brd ff:ff:ff:ff:ff:ff
    inet 169.254.31.238/31 scope global rfp-e8f12f7a-6
       valid_lft forever preferred_lft forever
    inet 192.168.1.112/32 brd 192.168.1.112 scope global rfp-e8f12f7a-6
       valid_lft forever preferred_lft forever

(3)在 qrouter 上,首先做 DNAT:

-A neutron-l3-agent-PREROUTING -d 192.168.1.112/32 -j DNAT –to-destination 81.1.180.18。将目的 IP 由浮动 IP 修改为固定 IP。

(4)查 qrouter 的 main 路由表,命中第一条,从 qr-517bdba3-b1 发出

root@compute1:/home/s1# ip netns exec  qrouter-e8f12f7a-6938-4e65-88c4-97e4cb211b27 ip route
81.1.180.0/24 dev qr-517bdba3-b1  proto kernel  scope link  src 81.1.180.1
91.1.180.0/24 dev qr-e47fca31-db  proto kernel  scope link  src 91.1.180.1
169.254.31.238/31 dev rfp-e8f12f7a-6  proto kernel  scope link  src 169.254.31.238
17:43:21.363808 fa:16:3e:63:3b:4c > fa:16:3e:30:ee:23, ethertype IPv4 (0x0800), length 98: (tos 0x0, flags [DF], proto ICMP (1), length 84)
    192.168.1.20 > 81.1.180.18: ICMP echo request, id 3202, seq 221, length 64

(5)SNAT:没有

(6)网络包经过 br-int,然后到达虚机

3.2.4 不同服务器上不同网段上的虚机互相访问

在另一个计算节点上新建虚机,固定 IP 为 90.1.180.6。从虚机 81.1.180.18 上 ping 它,看看网络包的走向。新建虚机后,compute 2 节点上也分布了 router 实例:

s1@controller:~$ neutron l3-agent-list-hosting-router dvr-r1
+--------------------------------------+----------+----------------+-------+
| id                                   | host     | admin_state_up | alive |
+--------------------------------------+----------+----------------+-------+
| 04c360d0-3066-4f04-9af2-d4ef8586ad2b | network  | True           | :-)   |
| aa8cf021-7f3d-4667-9d92-4d77d4c4fb59 | compute2 | True           | :-)   |
| beec232b-48d7-4424-83e2-8cc4e49ec339 | compute1 | True           | :-)   |
+--------------------------------------+----------+----------------+-------+

在 compute 2 上,创建了 qrouter network namespace,其中的配置和 compute 1 上的 qrouter 的配置完全相同。

(1)网络包离开 vm1,通过br-int,进入 compute 1 上的 qrouter 的 qr-517bdba3-b1,查 main 路由表,从 qr-e47fca31-db 出。

08:17:14.483282 fa:16:3e:30:ee:23 > fa:16:3e:63:3b:4c, ethertype IPv4 (0x0800), length 98: (tos 0x0, flags [DF], proto ICMP (1), length 84)
81.1.180.18 > 90.1.180.6: ICMP echo request, id 12033, seq 4, length 64
root@compute1:/home/s1# ip netns exec qrouter-e8f12f7a-6938-4e65-88c4-97e4cb211b27 ip route list table main
81.1.180.0/24 dev qr-517bdba3-b1 proto kernel scope link src 81.1.180.1
90.1.180.0/24 dev qr-f849ae46-48 proto kernel scope link src 90.1.180.1
91.1.180.0/24 dev qr-e47fca31-db proto kernel scope link src 91.1.180.1
169.254.31.238/31 dev rfp-e8f12f7a-6 proto kernel scope link src 169.254.31.238
08:18:30.555867 fa:16:3e:ec:f3:dd > fa:16:3e:13:93:0d, ethertype IPv4 (0x0800), length 98: (tos 0x0, flags [DF], proto ICMP (1), length 84)
81.1.180.18 > 90.1.180.6: ICMP echo request, id 12033, seq 80, length 64

(2)网络包重新进入 br-int,被它的 flows 处理。

root@compute1:/home/s1# ovs-ofctl dump-flows br-inttable=0, n_packets=0, n_bytes=0, idle_age=6318, priority=2,in_port=5,dl_src=fa:16:3f:12:a3:38 actions=resubmit(,1)
table=0, n_packets=336, n_bytes=32928, idle_age=1, priority=2,in_port=5,dl_src=fa:16:3f:db:6f:73 actions=resubmit(,1)
table=0, n_packets=12877, n_bytes=1220950, idle_age=1, priority=1 actions=NORMAL
table=1, n_packets=0, n_bytes=0, idle_age=6309, priority=2,ip,dl_vlan=2,nw_dst=81.1.180.0/24 actions=strip_vlan,mod_dl_src:fa:16:3e:63:3b:4c,output:4table=1, n_packets=336, n_bytes=32928, priority=4,dl_vlan=2,dl_dst=fa:16:3e:30:ee:23 actions=strip_vlan,mod_dl_src:fa:16:3e:63:3b:4c,output:4table=1, n_packets=0, n_bytes=0, idle_age=6319, priority=1 actions=drop
table=23, n_packets=0, n_bytes=0, idle_age=6319, priority=0 actions=drop

(3)进入 br-tun,依次被其 flows 处理:

root@compute1:/home/s1# ovs-ofctl dump-flows br-tun
NXST_FLOW reply (xid=0x4):
table=0, n_packets=6423, n_bytes=593912, idle_age=0, priority=1,in_port=1 actions=resubmit(,1)
table=1, n_packets=5751, n_bytes=563598, idle_age=0, priority=1,dl_vlan=1,dl_src=fa:16:3e:ec:f3:dd actions=mod_dl_src:fa:16:3f:b2:34:82,resubmit(,2)
 table=2, n_packets=5768, n_bytes=565152, idle_age=0, priority=0,dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,20)
table=20, n_packets=0, n_bytes=0, idle_age=6900, priority=0 actions=resubmit(,22)
table=20, n_packets=11, n_bytes=1022, idle_age=3650, priority=2,dl_vlan=2,dl_dst=fa:16:3e:82:a9:ca actions=strip_vlan,set_tunnel:0x6,output:3
table=20, n_packets=5, n_bytes=490, idle_age=6411, priority=2,dl_vlan=1,dl_dst=fa:16:3e:47:55:00 actions=strip_vlan,set_tunnel:0x4,output:3
table=20, n_packets=0, n_bytes=0, idle_age=5820, priority=2,dl_vlan=1,dl_dst=fa:16:3e:54:f8:b8 actions=strip_vlan,set_tunnel:0x4,output:3
 table=20, n_packets=1108, n_bytes=108584, idle_age=0, priority=2,dl_vlan=1,dl_dst=fa:16:3e:13:93:0d actions=strip_vlan,set_tunnel:0x4,output:2
table=20, n_packets=0, n_bytes=0, idle_age=6889, priority=2,dl_vlan=2,dl_dst=fa:16:3e:a1:76:41 actions=strip_vlan,set_tunnel:0x6,output:2
table=20, n_packets=1, n_bytes=42, idle_age=6685, priority=2,dl_vlan=2,dl_dst=fa:16:3e:c0:8f:2c actions=strip_vlan,set_tunnel:0x6,output:3
table=20, n_packets=0, n_bytes=0, idle_age=6782, priority=2,dl_vlan=1,dl_dst=fa:16:3e:69:92:30 actions=strip_vlan,set_tunnel:0x4,output:3

从这里可以看出:

  • table 1 将网络包的 src mac 修改为了 compute node 1 的 DVR MAC 地址。
  • table 20 通过 l2population 获得了到虚机所在的租户网络内的所有存在的虚机的 MAC 地址和 Tunnel 端口号的映射关系。至此,网络包被打上了 Tunnel ID 4,进入 GRE Port 2.
  • 其 GRE 隧道的另一头正是 compute 2.

(4)到了 compute 2 上,依次被 br-tun,br-int 处理,直到通过 tap 设备进入 vm 2。

小结:

理解 OpenStack 高可用(HA):Neutron 分布式虚拟路由(中)_第7张图片

3.2.5 同一个服务器上不同网段上的虚机互相访问

这里只经过 3.2.4 中的 (1) 和 (2),网络包经过 br-int 直接进入 vm2.

3.3 小结

网络流量类型 特征 转发机制
本地 源和目的 IP 在同一个 subnet 中,虚机在同一个计算节点上 br-int 通过 MAC 地址学习直接转发网络包给目标虚机
远程 源和目的 IP 在同一个 subnet 中,虚机不在同一个计算节点上 标准转发,取决于网络的段类型
东-西 源和目的 IP 不在同一个 subnet 中 由源虚机所在计算节点上的 qrouter 负责转发
SNAT IP 不属于本地 router 的任何 subnet 中,而且虚机没有浮动IP 由源虚机所在计算节点上的 qrouter 负责转发到 neutron 网络节点上 snat
FIP IP 不属于本地 router 的任何 subnet 中,而且虚机有浮动IP 由源虚机所在计算节点上的 qrouter转发到本地的 fip

刘世民, 云架构师,十余年IT行业从业经验,在电信软件、企业软件、存储以及云计算等领域从事过研发、管理和架构设计等方面的工作。从2012年开始从事 OpenStack 研发工作,对其核心模块、相关开源技术和产品,以及行业等都有着较深的理解。

责编:陈晨 联系请添加微信:violace95 备注公司 职位 姓名。寻求报道或投稿,请请发送至邮箱:[email protected]

你可能感兴趣的:(理解 OpenStack 高可用(HA):Neutron 分布式虚拟路由(中))