分享

Neutron系列 : Neutron 是如何向 Nova 虚机分配固定IP地址的(10)

breaking 发表于 2015-12-17 14:07:59 [显示全部楼层] 只看大图 回帖奖励 阅读模式 关闭右栏 0 15481
本帖最后由 eying 于 2016-1-13 16:55 编辑

问题导读:
1.Neutron L3 Agent 的实现原理是怎么样的
2.L3 Agent iptables 完整流程实验是怎么样的




2. Neutron L3 Agent 的实现原理
    每个 L3 Agent 运行在一个 network namespace 中,每个 namespace 由 qrouter-<router-UUID>命名,比如 qrouter-e506f8fe-3260-4880-bd06-32246225aeae。网络节点如果不支持 Linux namespace 的话,只能运行一个 Virtual Router。也可以通过设置配置项 use_namespaces = True/False 来使用或者不使用 namespace。
   Neutron L3 Agent 负责路由(routing)、浮动 IP 分配(floatingip allocation), 地址转换(SNAT/DNAT)和 Security Group 管理(Blueprint 在这里。在后面的文章中打算和 Nova 中的 Security Group 一起分析)。

2.1 Router 作为浮动 IP 地址的ARP Proxy
    虚机的浮动 IP 其实不是真实网卡的 IP 地址,而是一个虚机的地址。那么,使用浮动 IP 和虚机通信的机器怎么获得 MAC 地址呢?Router 在这个过程中作为一个 ARP Proxy,其 IP 协议栈会向 ARP 广播请求回应浮动 IP 对应所在的外部端口的 MAC 地址。下面的例子中,该 router 挂接的子网内有两个浮动 IP,L3 Agent 都将它们添加到 Router 的外部端口 qg-3c8d6a68-97 上:
[mw_shl_code=bash,true]42: qg-3c8d6a68-97: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
    link/ether fa:16:3e:2e:5b:23 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.110/24 brd 192.168.1.255 scope global qg-3c8d6a68-97
       valid_lft forever preferred_lft forever
    inet 192.168.1.104/32 brd 192.168.1.104 scope global qg-3c8d6a68-97
       valid_lft forever preferred_lft forever
    inet 192.168.1.111/32 brd 192.168.1.111 scope global qg-3c8d6a68-97
       valid_lft forever preferred_lft forever
    inet6 fe80::f816:3eff:fe2e:5b23/64 scope link
       valid_lft forever preferred_lft forever[/mw_shl_code]

    这么做的目的,由于外网中的机器和虚机浮动 IP 是同一个网段的,外网中的机器通过浮动 IP 访问虚机之前,需要通过 ARP 获取该浮动 IP 的 MAC 地址。浮动IP 其实是个虚机IP,没有对应一个网络设备,因此,Neutron 将它们添加到 external port 上,共享 external port 的 MAC 地址。这样,在 router network namespace IP 协议栈收到 ARP 广播后,就可以该 IP 对应 的 MAC 地址,然后外网中的虚机就会使用该 MAC 作为目的 MAC 地址直接向 router 的 external port 端口发送网络帧。查询外网机器的 arp table,即可看到 192.168.1.104 的 MAC 为 qg-3c8d6a68-97 的  MAC 地址。也就是说,外部端口上的所有 IP 的 MAC 地址都相同。这时候,其实 router 充当了一个 ARP Proxy 的角色。
s1@controller:~$ arpAddress                  HWtype  HWaddress           Flags Mask            Iface192.168.1.104            ether   fa:16:3e:2e:5b:23   C                     eth0192.168.1.110            ether   fa:16:3e:2e:5b:23   C                     eth0192.168.1.111            ether   fa:16:3e:2e:5b:23   C                     eth0

2.2 路由 (Routing)
一个 Virtual Router 连接几个 subnet 就会有几个 virtual interface。每个 interface 的地址是该 subnet 的 gateway 地址。比如:
[mw_shl_code=bash,true]root@network:/home/s1# ip netns exec qrouter-e438bebe-6795-4b68-a613-ec0df38d3064 ip addr

33: qr-2aa928c9-e8: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default #IP 设为它连接的子网的 Gateway IP
    link/ether fa:16:3e:90:e5:50 brd ff:ff:ff:ff:ff:ff
    inet 91.1.180.1/24 brd 91.1.180.255 scope global qr-2aa928c9-e8
37: qr-a5c6ed86-c1: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
    link/ether fa:16:3e:87:40:f3 brd ff:ff:ff:ff:ff:ff
    inet 81.1.180.1/24 brd 81.1.180.255 scope global qr-a5c6ed86-c1
48: qg-3c8d6a68-97: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
    link/ether fa:16:3e:2e:5b:23 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.110/24 brd 192.168.1.255 scope global qg-3c8d6a68-97[/mw_shl_code]

    L3 Agent 在启动时设置如下的路由规则:
[mw_shl_code=bash,true]root@network:/home/s1# ip netns exec qrouter-e438bebe-6795-4b68-a613-ec0df38d3064 route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.1.1     0.0.0.0         UG    0      0        0 qg-3c8d6a68-97
81.1.180.0      0.0.0.0         255.255.255.0   U     0      0        0 qr-a5c6ed86-c1 #到哪个网段的traffic发到相应的 interface
91.1.180.0      0.0.0.0         255.255.255.0   U     0      0        0 qr-2aa928c9-e8
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 qg-3c8d6a68-97[/mw_shl_code]
   虚机的 IP 栈在发现数据包的目的虚机的 IP 地址不在自己网段的话,会将其发到 Router 上对应其 subnet 的 Virtual Interface。然后,Virtual Router 根据配置的路由规则和目的IP地址,将包转发到目的端口发出。

2.3 源地址转换 SNAT

2.3.1 Neutron 的 SNAT iptables chains
在没有设置浮动 IP 时,当主机访问外网时,需要将主机的固定 IP 转换成外网网段的 gateway 的 IP 地址,以免暴露内部 IP 地址。其做法是 Neutron 在 iptables 表中增加了 POSTROUTING 链。
[mw_shl_code=bash,true]root@network:/home/s1# ip netns exec qrouter-e438bebe-6795-4b68-a613-ec0df38d3064 iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N neutron-l3-agent-OUTPUT      #Neutorn 增加的 chain
-N neutron-l3-agent-POSTROUTING  #Neutorn 增加的 SNAT chain
-N neutron-l3-agent-PREROUTING   
-N neutron-l3-agent-float-snat  #Neutorn 增加的 SNAT chain
-N neutron-l3-agent-snat        #Neutorn 增加的 SNAT chain
-N neutron-postrouting-bottom   #Neutorn 增加的 SNAT chain
-A PREROUTING -j neutron-l3-agent-PREROUTING
-A OUTPUT -j neutron-l3-agent-OUTPUT
-A POSTROUTING -j neutron-l3-agent-POSTROUTING #(1)将 SNAT chain 转到自定义的 neutron-l3-agent-POSTROUTING
-A POSTROUTING -j neutron-postrouting-bottom   #(3)将 SNAT chain 转到自定义的 neutron-postrouting-bottom
-A neutron-l3-agent-POSTROUTING ! -i qg-3c8d6a68-97 ! -o qg-3c8d6a68-97 -m conntrack ! --ctstate DNAT -j ACCEPT #(2)如果出口或者入口不是 qg-3c8d6a68-97 并且状态不是 DNAT 的都接受
-A neutron-l3-agent-snat -j neutron-l3-agent-float-snat
-A neutron-l3-agent-snat -s 91.1.180.0/24 -j SNAT --to-source 192.168.1.110 #(5)将 91.1.180.0/24 网段的包的目的 IP 转为 192.168.1.110
-A neutron-l3-agent-snat -s 81.1.180.0/24 -j SNAT --to-source 192.168.1.110 #(5)将 91.1.180.0/24 网段的包的目的 IP 转为 192.168.1.110
-A neutron-postrouting-bottom -j neutron-l3-agent-snat                      #(4)再转到 neutron-l3-agent-snat[/mw_shl_code]


2.3.2 实验:从虚机  81.1.180.12 ping 外网 192.168.1.15
1. 在 router 的连接 81.1.180.12 网段 interface 上:
[mw_shl_code=bash,true]root@network:/home/s1# ip netns exec qrouter-e438bebe-6795-4b68-a613-ec0df38d3064 tcpdump -envi qr-a5c6ed86-c1 -vvv
tcpdump: listening on qr-a5c6ed86-c1, link-type EN10MB (Ethernet), capture size 65535 bytes
^C17:42:48.904820 fa:16:3e:2b:3e:2a > fa:16:3e:87:40:f3, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 28892, offset 0, flags [DF], proto ICMP (1), length 84)
    81.1.180.12 > 192.168.1.15: ICMP echo request, id 32769, seq 0, length 64
17:42:48.906601 fa:16:3e:87:40:f3 > fa:16:3e:2b:3e:2a, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 63, id 24799, offset 0, flags [none], proto ICMP (1), length 84)
    192.168.1.15 > 81.1.180.12: ICMP echo reply, id 32769, seq 0, length 64
17:42:49.906238 fa:16:3e:2b:3e:2a > fa:16:3e:87:40:f3, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 28893, offset 0, flags [DF], proto ICMP (1), length 84)[/mw_shl_code]

2. 在 route 的连接 192.168.1.15 网段 interface 上

[mw_shl_code=bash,true]root@network:/home/s1# ip netns exec qrouter-e438bebe-6795-4b68-a613-ec0df38d3064 tcpdump -envi qg-3c8d6a68-97 -vvv
tcpdump: listening on qg-3c8d6a68-97, link-type EN10MB (Ethernet), capture size 65535 bytes
^C17:44:47.661916 fa:16:3e:2e:5b:23 > 08:00:27:c7:cf:ca, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 63, id 28896, offset 0, flags [DF], proto ICMP (1), length 84)
    192.168.1.110 > 192.168.1.15: ICMP echo request, id 33281, seq 0, length 64
17:44:47.663300 08:00:27:c7:cf:ca > fa:16:3e:2e:5b:23, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 36308, offset 0, flags [none], proto ICMP (1), length 84)
    192.168.1.15 > 192.168.1.110: ICMP echo reply, id 33281, seq 0, length 64[/mw_shl_code]

可见在外网网段的 interface 收到数据包之前,SRC IP 已经被替换成了外网网段的 Gateway IP 了。

2.4 目的地址转换 DNAT
    要使外网内的机器能访问虚机,需要设置虚机的浮动IP。浮动 IP 在 Virtual Router 连接的 external network 的 subnet 内分配。注意浮动 IP 只有在 Virtual Router 上配置了 External network subnet gateway 才有意义。

2.4.1 浮动IP分配
创建浮动IP:

[mw_shl_code=bash,true]root@sun:~# neutron floatingip-create Extnet
Created a new floatingip:
+---------------------+--------------------------------------+
| Field               | Value                                |
+---------------------+--------------------------------------+
| fixed_ip_address    |                                      |
| floating_ip_address | 10.8.127.11                          |
| floating_network_id | 9c9436d4-2b7c-4787-8535-9835e6d9ac8e |
| id                  | 7b4cee72-ffcd-4484-a5d8-371b23bb3cc3 |[/mw_shl_code]

关联到一个 port:

[mw_shl_code=bash,true]root@sun:~# neutron port-list | grep 192.168.10.26
| d74c703e-824a-41b1-b4b3-3cd4edfa22b3 |      | fa:16:3e:14:ff:6d | {"subnet_id": "ccc80588-2b0d-459b-82e9-972ff4291b79", "ip_address": "192.168.10.26"} |
root@sun:~# neutron floatingip-associate 7b4cee72-ffcd-4484-a5d8-371b23bb3cc3 d74c703e-824a-41b1-b4b3-3cd4edfa22b3
+---------------------+--------------------------------------+
| Field               | Value                                |
+---------------------+--------------------------------------+
| fixed_ip_address    | 192.168.10.26                        |
| floating_ip_address | 10.8.127.11                          |[/mw_shl_code]

    每个浮动 IP 唯一对应一个 Router:浮动IP -> 关联的 Port -> 所在的 Subnet -> 包含该 subnet 以及 external subnet 的 Router。创建浮动 IP 时,在 Neutron 完成数据库操作来分配浮动IP后,它通过 RPC 来通知该浮动IP对应的 router 去设置该浮动IP对应的 iptables 规则。上面的例子中,固定IP 为 ‘192.168.10.26’ 的虚机可以在外网中使用浮动 IP  ‘10.8.127.11’ 来访问了。
<更新 2015/11/27> Kilo 版本中,创建浮动 IP 的时候允许指定浮动IP 地址,这么做就能够对同一个虚机使用同一个浮动IP。
blueprint:Allow specific Floating IP Address
效果:Neutorn floatingip-create cli 上增加了一个参数 --floating-ip-address 用于指定创建的浮动IP地址:

[mw_shl_code=bash,true]root@controller:~/s1# neutron floatingip-create --port-id 97f3ed61-7f9e-4f0a-91af-e95a572acd9c --floating-ip-address 9.115.251.105 5b4daf62-d992-453f-b74d-8c585365a604
Created a new floatingip:
+---------------------+--------------------------------------+
| Field               | Value                                |
+---------------------+--------------------------------------+
| fixed_ip_address    | 70.0.0.105                           |
| floating_ip_address | 9.115.251.105                        |
| floating_network_id | 5b4daf62-d992-453f-b74d-8c585365a604 |
| id                  | 77935422-e2cf-4dc6-85a3-26a58a493f70 |
| port_id             | 97f3ed61-7f9e-4f0a-91af-e95a572acd9c |
| router_id           | b94a203d-5317-4d0b-9833-5c65e01bd76f |
| status              | DOWN                                 |
| tenant_id           | dea8b51d28bf41599e63464828102759     |
+---------------------+--------------------------------------+[/mw_shl_code]

默认情况下,只有 admin 才能使用,不过,可以修改 policy.json 文件将其向普通租户开放。

2.4.2 Neturon DNAT Chains
  外网访问虚机时,目的 IP 地址为虚机的浮动 IP 地址,因此,必须由 iptables 将其转化为固定 IP 地址,然后再将它路由到虚机。我们需要关注的是 iptables 的 nat 表的 PREOUTING chain:

[mw_shl_code=bash,true]root@network:/home/s1# ip netns exec qrouter-e438bebe-6795-4b68-a613-ec0df38d3064 iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N neutron-l3-agent-OUTPUT
-N neutron-l3-agent-PREROUTING               #neutron 增加的 DNAT chain
-A PREROUTING -j neutron-l3-agent-PREROUTING # DNAT 由 neutron 新增的 chain 负责处理
-A OUTPUT -j neutron-l3-agent-OUTPUT
-A neutron-l3-agent-OUTPUT -d 192.168.1.104/32 -j DNAT --to-destination #本机访问浮动IP 修改为固定 IP
-A neutron-l3-agent-PREROUTING -d 169.254.169.254/32 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 9697 #将虚机访问 metadata server 的 traffic 端口由 80 改到 9697(由配置项 metadata_port 设置,默认为 9697),那里有 application 在监听。具体内容很深,可以参考这篇文章。
-A neutron-l3-agent-PREROUTING -d 192.168.1.104/32 -j DNAT --to-destination 91.1.180.14 #到浮动IP的traffic的目的IP 换成虚机的固定 IP[/mw_shl_code]

每个浮动 IP,增加三个规则:
-A neutron-l3-agent-PREROUTING -d <floatingip> -j DNAT --to-destination <fixedip> #从本机访问虚机,Dst IP 由浮动IP该为访问固定IP -A neutron-l3-agent-OUTPUT -d <floatingip> -j DNAT --to <fixedip>                 #从别的机器上访问虚机,DST IP 由浮动IP改为固定IP-A neutron-l3-agent-float-snat -s <fixedip> -j SNAT --to <floatingip>             #虚机访问外网,将Src IP 由固定IP改为浮动IP
这里可以看到当设置了浮动 IP 以后,SNAT 不在使用 External Gateway 的 IP 了,而是使用浮动 IP 。虽然 entires 依然存在,但是因为 neutron-l3-agent-float-snat 比 neutron-l3-agent-snat 靠前而得到执行。
-A neutron-l3-agent-float-snat -s 91.1.180.14/32 -j SNAT --to-source 192.168.1.104-A neutron-l3-agent-snat -j neutron-l3-agent-float-snat-A neutron-l3-agent-snat -s 91.1.180.0/24 -j SNAT --to-source 192.168.1.110-A neutron-l3-agent-snat -s 81.1.180.0/24 -j SNAT --to-source 192.168.1.110-A neutron-postrouting-bottom -j neutron-l3-agent-snat

2.4.3 实验:从外网192.168.1.15 ping虚机 81.1.180.14 的浮动IP 192.168.1.104
1. 在route 的连接外网网段的interace 上:
17:58:46.116944 08:00:27:c7:cf:ca > fa:16:3e:2e:5b:23, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 25176, offset 0, flags [DF], proto ICMP (1), length 84)    192.168.1.15 > 192.168.1.104: ICMP echo request, id 24530, seq 4, length 6417:58:46.117910 fa:16:3e:2e:5b:23 > 08:00:27:c7:cf:ca, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 63, id 23128, offset 0, flags [none], proto ICMP (1), length 84)    192.168.1.104 > 192.168.1.15: ICMP echo reply, id 24530, seq 4, length 64
2. 在 router 的连接内网网段的interface上:

[mw_shl_code=bash,true]root@network:/home/s1# ip netns exec qrouter-e438bebe-6795-4b68-a613-ec0df38d3064 tcpdump -envi qr-2aa928c9-e8 -vvv
tcpdump: listening on qr-2aa928c9-e8, link-type EN10MB (Ethernet), capture size 65535 bytes
^C19:46:12.266739 fa:16:3e:90:e5:50 > fa:16:3e:f3:1e:c0, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 63, id 53299, offset 0, flags [DF], proto ICMP (1), length 84)
    192.168.1.15 > 91.1.180.14: ICMP echo request, id 2831, seq 1, length 64
19:46:12.269143 fa:16:3e:f3:1e:c0 > fa:16:3e:90:e5:50, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 23157, offset 0, flags [none], proto ICMP (1), length 84)
    91.1.180.14 > 192.168.1.15: ICMP echo reply, id 2831, seq 1, length 64[/mw_shl_code]
root@network:/home/s1# ip netns exec qrouter-e438bebe-6795-4b68-a613-ec0df38d3064 tcpdump -envi qr-2aa928c9-e8 -vvv
tcpdump: listening on qr-2aa928c9-e8, link-type EN10MB (Ethernet), capture size 65535 bytes
^C19:46:12.266739 fa:16:3e:90:e5:50 > fa:16:3e:f3:1e:c0, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 63, id 53299, offset 0, flags [DF], proto ICMP (1), length 84)
192.168.1.15 > 91.1.180.14: ICMP echo request, id 2831, seq 1, length 64
19:46:12.269143 fa:16:3e:f3:1e:c0 > fa:16:3e:90:e5:50, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 23157, offset 0, flags [none], proto ICMP (1), length 84)
91.1.180.14 > 192.168.1.15: ICMP echo reply, id 2831, seq 1, length 64

2.5 L3 Agent iptables 完整流程实验
该实验中使用 “ iptables -t nat  -L -nv” 命令来查看每个链上匹配到的数据包数目。

2.4.1 虚机 91.1.180.14 ping 另一个虚机 81.1.180.12
171644461415543.jpg
可见:
(1)DNAT 匹配到的是默认的 Policy
(2)SNAT 匹配到 “-A neutron-l3-agent-POSTROUTING ! -i qg-3c8d6a68-97 ! -o qg-3c8d6a68-97 -m conntrack ! --ctstate DNAT -j ACCEPT” 规则后就被 Accept 了。

2.5.1 虚机 91.1.180.14 ping 外网 192.168.1.4
171717433919615.jpg
可见:
(1)DNAT 匹配到的是默认的 Policy ACCEPT
(2)SNAT 匹配到 “-A neutron-l3-agent-float-snat -s 91.1.180.14/32 -j SNAT --to-source 192.168.1.104” 规则后做 SNAT。

2.5.2 外网 192.168.1.4 ping 虚机 192.168.1.104(91.1.180.14)
171727055015055.jpg
可见:
(1)DNAT 匹配到 “-A neutron-l3-agent-PREROUTING -d 192.168.1.104/32 -j DNAT --to-destination 91.1.180.14” 然后做 DNAT。
(2)SNAT 匹配到的是默认的 Policy ACCEPT。
  为什么结果中显示的 pacakge 数目只是1呢?参考网上文章,对于 SNAT 和 DNAT target 来说,如果一个包被匹配了,那么和它属于同一个流的所有的包都会被自动转换,然后就可以被路由到正确的主机或网络,这么说来,一个流中被匹配的包的数目就是1了。
总结:
131705408763229.jpg
(图片来源。Neutron 代码分析也可以参考这篇文章。)

3. Neutron L3 Agent 主要代码结构
L3 Agent 启动后,它有若干个 Workers 去 MQ 中拿数据,然后将数据放进一个内部的 queue 中。它还会启动一个循环线程去queue 中取数据。当发现有 router 相关的操作发生后,即调用 _process_routers_loop 方法去处理获取的数据。

3.1 L3 Agent 启动
Neutorn L3 Agent 的 binary 是 /usr/bin/neutron-l3-agent,其main 会初始化一个 class Service(n_rpc.Service) 类的实例。在该实例的 start 函数中,它会启动两个周期性任务:
(1).启动 一个线程来执行循环函数 _process_routers_loop 来处理第二个周期性任务添加到  _queue 中的每一个 router 的 action,包括删除、添加和更新。对每一个待处理的 router,最终会调用到 RouterInfo.process 方法。注意 router 的操作都是在其对应的 namespace 中进行的。在 namespace 创建的时候,执行 'sysctl -w net.ipv4.ip_forward=1' 来使得它能够做 IP 路由转发。

[mw_shl_code=bash,true]def process(self, agent):
        """Process updates to this router
        This method is the point where the agent requests that updates be   applied to this router.
        :param agent: Passes the agent in order to send RPC messages.
        """
        self._process_internal_ports()
        self.process_external(agent)
        # Process static routes for router
        self.routes_updated()

        # Update ex_gw_port and enable_snat on the router info cache
        self.ex_gw_port = self.get_ex_gw_port()
        self.snat_ports = self.router.get(
            l3_constants.SNAT_ROUTER_INTF_KEY, [])
        self.enable_snat = self.router.get('enable_snat')[/mw_shl_code]

(2)启动一个周期性函数 periodic_sync_routers_task。它负责通过 RPC 获取到 router 列表,然后将需要增加和删除的 router 加入到 _queue 中。

3.2 Router 处理
L3 Agent 的核心是 Router 的处理。
(1)处理 external gateway (比如,external_gateway_added 增加 external gateway:获取该 router 的所有浮动 IP,在agent_conf.external_network_bridge 所指定的外网物理 OVS bridge 上增加一个 tap 设备,名称为 “gq-*”,然后设置其 MAC 地址,MTU 等)
(2)修改路由表 (routes_updated)
(3)在有 external gateway 时,设置 SNAT iptables (_handle_router_snat_rules):先删除当前所有 POSTROUTING 和 snat chains,然后再增加:

[mw_shl_code=bash,true]#增加 SNAT chain
-N neutron-l3-agent-float-snat
#为 external gateway
-A neutron-l3-agent-POSTROUTING ! -i qg-3c8d6a68-97 ! -o qg-3c8d6a68-97 -m conntrack ! --ctstate DNAT -j ACCEPT

#为每一个子网创建一条 SNAT 规则
-A neutron-l3-agent-snat -s 91.1.180.0/24 -j SNAT --to-source 192.168.1.110 #(5)将 91.1.180.0/24 网段的包的目的 IP 转为 192.168.1.110
-A neutron-l3-agent-snat -s 81.1.180.0/24 -j SNAT --to-source 192.168.1.110 #(5)将 91.1.180.0/24 网段的包的目的 IP 转为 192.168.1.110[/mw_shl_code]
#增加 SNAT chain
-N neutron-l3-agent-float-snat#为 external gateway
-A neutron-l3-agent-POSTROUTING ! -i qg-3c8d6a68-97 ! -o qg-3c8d6a68-97 -m conntrack ! --ctstate DNAT -j ACCEPT

#为每一个子网创建一条 SNAT 规则-A neutron-l3-agent-snat -s 91.1.180.0/24 -j SNAT --to-source 192.168.1.110 #(5)将 91.1.180.0/24 网段的包的目的 IP 转为 192.168.1.110 -A neutron-l3-agent-snat -s 81.1.180.0/24 -j SNAT --to-source 192.168.1.110 #(5)将 91.1.180.0/24 网段的包的目的 IP 转为 192.168.1.110

(4)如果有 external gateway 的话,处理浮动 IP 的 SNAT/DNAT iptables (process_snat_dnat_for_fip)
#为每一个浮动 IP,以 192.168.1.104 为例-A neutron-l3-agent-PREROUTING -d 192.168.1.104/32 -j DNAT --to-destination 91.1.180.14 #DNAT-A neutron-l3-agent-OUTPUT -d 192.168.1.104/32 -j DNAT --to-destination 91.1.180.14 #本机访问-A neutron-l3-agent-float-snat -s 91.1.180.14/32 -j SNAT --to-source 192.168.1.104 #SNAT

(5)将浮动IP 配置到 external gateway port (process_floating_ip_addresses -> add_floating_ip -> _add_fip_addr_to_device)
42: qg-3c8d6a68-97: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default    link/ether fa:16:3e:2e:5b:23 brd ff:ff:ff:ff:ff:ff    inet 192.168.1.110/24 brd 192.168.1.255 scope global qg-3c8d6a68-97       valid_lft forever preferred_lft forever    inet 192.168.1.104/32 brd 192.168.1.104 scope global qg-3c8d6a68-97       valid_lft forever preferred_lft forever

(6)除了上述操作,L3 Agent 还在创建/添加 router 的每一个端口(包括internal 的和 external 的)时发出 Gratuitous  ARP,通知其所在广播域内的其它机器去更新它的 ARP 表中该 IP 条目。比如:
'ip netns exec qrouter-b49a8032-a676-4ef9-aade-355592949aaa arping -A -I qg-e83aae8d-d2 -c 3 192.168.1.100'
其中,“-A” 表示不需要 ARP 返回包;“-I” 表示通过指定的 port 发出包,这样就算只对有需要的subnet 发出包了;“-c 3” 表示尝试3次。

3.3 浮动 IP 处理
在创建、绑定、去绑定或者删除浮动IP时,neutron server 首先执行 DB 操作,然后调用 RPC (notify_routers_updated) 去通知指定的 Router:”create_floatingip“,”update_floatingip“,”delete_floatingip“ 等。



相关内容:


neutron系列:Neutron 所实现的虚拟化网络(1)


neutron系列:Neutron 所实现的虚拟化网络(2)

neutron系列:使用 Open vSwitch + VLAN 组网(3)

neutron系列:使用 Open vSwitch + VLAN 组网(4)

Neutron系列 : 使用Open vSwitch + GRE/VxLAN 组网 (5)

Neutron系列 : 使用Open vSwitch + GRE/VxLAN 组网(6)

Neutron系列 : Neutron OVS OpenFlow 流表 和 L2 Population(7)

Neutron系列 : Neutron OVS OpenFlow 流表 和 L2 Population(8)

Neutron系列 : Neutron 是如何向 Nova 虚机分配固定IP地址的(9)

Neutron系列 : Neutron 是如何向 Nova 虚机分配固定IP地址的(10)

Neutron 系列 (11): Neutron 是如何实现负载均衡器虚拟化的【基础篇】

Neutron 系列 (12): Neutron 是如何实现负载均衡器虚拟化的【提高篇】

Neutron 系列 (13): Neutron 是如何实现虚机防火墙的 【上】

Neutron 系列 (14): Neutron 是如何实现虚机防火墙的 【下】

Neutron 系列 (15): OpenStack 是如何实现 Neutron 网络 和 Nova虚机 防火墙的

Neutron 系列(16):虚拟专用网(VPN)虚拟化

Neutron 系列 (17): Neutron 分布式虚拟路由【上】

Neutron 系列 (18): Neutron 分布式虚拟路由【下】

Neutron系列(19):Neutron L3 Agent HA 之 虚拟路由冗余协议(VRRP)【上】

Neutron系列(20):Neutron L3 Agent HA 之 虚拟路由冗余协议(VRRP)【下】

Neutron系列(21):OpenStack 高可用和灾备方案 [OpenStack HA and DR]【上】

Neutron系列(22):OpenStack 高可用和灾备方案 [OpenStack HA and DR]【下】







没找到任何评论,期待你打破沉寂

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条