本文旨在通过全部手动的方式,来完成DVR的手动部署。大体思路是,在一个DVR的环境里,手动创建虚拟机,手动创建各种Linux网络设备,手动添加各种流表,完成新建虚拟机和在DVR模式下的虚拟机的DHCP,二层,三层通信。
目录
Human Defined DVR之虚拟机三层通信
首先新创建个网络、子网,在用路由器把上面的子网和刚创建的子网连接,最后的逻辑拓扑是这样的:
我们创建的Cirros虚拟机在下面的蓝色区域里,我们要和上面黄色区域里的虚拟机通信。
首先,Cirros虚拟机的请求包转发到了br-tun上,我们分析下Cirros发送的报文,如下:
fa:16:3e:ff:aa:66 > fa:16:3e:35:25:42, ethertype IPv4 (0x0800), length 98: 192.168.10.222 > 10.10.10.4: ICMP echo request, id 31745, seq 0, length 64
三层通信时,虚拟机会把包发到自己的默认网关上(网关是192.168.10.1,目的IP是10.10.10.4,目的MAC是fa:16:3e:35:25:42)。
由于本地的L3 agent是DVR模式,那么会把流量路由到本地的路由器上。路由器里的两个QR设备(一个是192.168.10.1,另一个是10.10.10.1)挂载在了br-int上,当Cirros虚拟机请求自己的网关192.168.10.1时,在br-int上192.168.10.1的QR设备收到了请求包(虚拟机发来的数据包的Tag是1,自己的Tag也是1),路由器一看,目的地址是10.10.10.4,自己本地正好有个10.10.10.1的网关设备,就把数据包发给了它,这个QR设备在br-int上的Tag是2,那么这个请求继续发到了br-tun上。
接下来看看br-tun上的流表:
首先,对于从br-int上来的数据包resubmit到table1
ovs-ofctl add-flow br-tun table=0,priority=1,in_port=1,actions=resubmit(,1)
接下来,在table1上匹配从10.10.10.1上来的,Tag是2,的数据包resubmit到table2,并且改成本地的HOST MAC
ovs-ofctl add-flow br-tun table=1,priority=1,dl_vlan=2,dl_src=fa:16:3e:de:07:79,actions=mod_dl_src:fa:16:3f:02:d7:f2,resubmit(,2)
PS:HOST MAC可以通过查看数据库查询:
MariaDB [neutron]> select * from dvr_host_macs;
+————+——————-+
| host | mac_address |
+————+——————-+
| server-233 | fa:16:3f:02:d7:f2 |
| server-68 | fa:16:3f:08:c7:a5 |
| server-64 | fa:16:3f:c9:7c:3c |
+————+——————-+
让我们继续看看table2上干了啥。
很简单,单播请求到table20,广播请求到table22
ovs-ofctl add-flow br-tun,table=2,priority=0,dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,20)
ovs-ofctl add-flow br-tun,table=2,priority=0,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,22)
由于CIrros虚拟机并不知道对端虚拟机在哪里,于是发广播,通过如下规则完成本地VLAN和全局VXLAN的转换,并发给其他所有的计算节点
ovs-ofctl add-flow br-tun table=22,dl_vlan=2,actions=strip_vlan,set_tunnel:0x1a,output:2,output:
来到了对面的68节点
从br-tun上收到了来自远端233的数据包,resubmit 到table4
ovs-ofctl add-flow br-tun table=0,priority=1,in_port=3,actions=resubmit(,4)
在table4上完成全局VXLAN和本地VLAN的转换
ovs-ofctl add-flow br-tun table=9,priority=1,tun_id=0x1a,actions=mod_vlan_vid:2,resubmit(,9)
因为从233上发来的数据的源MAC是HOST MAC,那么在br-tun上匹配这个MAC地址,转给patch port
ovs-ofctl add-flow br-tun table=9,priority=1,dl_src=fa:16:3f:02:d7:f2,actions=output:1
对端的路由器10.10.10.1挂载在了br-int上,并且Tag是2,那么这个设备收到了请求,一看目的地址10.10.10.4,那么直接转发给了目的虚拟机。
至此。搞定。
Human Defined DVR之FloatingIP的实现
首先,我们在Neutron里创建一个外部网络,网段是2.2.2.0/24,创建floatingip,并给server-64上的一个虚拟机绑定这个公网IP,如下:
[root@server-233 ~(keystone_admin)]# neutron net-create external_network –router:external=True
Created a new network:
+—————————+————————————–+
| Field | Value |
+—————————+————————————–+
| admin_state_up | True |
| id | ccf351c9-826c-4d93-9dd4-625302bf3051 |
| mtu | 0 |
| name | external_network |
| provider:network_type | vxlan |
| provider:physical_network | |
| provider:segmentation_id | 22 |
| router:external | True |
| shared | False |
| status | ACTIVE |
| subnets | |
| tenant_id | ef979882f1954a0fa4ce7daf244aa557 |
+—————————+————————————–+
[root@server-233 ~(keystone_admin)]# neutron subnet-create ccf351c9-826c-4d93-9dd4-625302bf3051 2.2.2.0/24
Created a new subnet:
+——————-+——————————————+
| Field | Value |
+——————-+——————————————+
| allocation_pools | {“start”: “2.2.2.2”, “end”: “2.2.2.254”} |
| cidr | 2.2.2.0/24 |
| dns_nameservers | |
| enable_dhcp | True |
| gateway_ip | 2.2.2.1 |
| host_routes | |
| id | 285aebd1-cd44-4663-9e2d-5f948fc369dc |
| ip_version | 4 |
| ipv6_address_mode | |
| ipv6_ra_mode | |
| name | |
| network_id | ccf351c9-826c-4d93-9dd4-625302bf3051 |
| subnetpool_id | |
| tenant_id | ef979882f1954a0fa4ce7daf244aa557 |
+——————-+——————————————+
[root@server-233 ~(keystone_admin)]# neutron floatingip-create ccf351c9-826c-4d93-9dd4-625302bf3051
Created a new floatingip:
+———————+————————————–+
| Field | Value |
+———————+————————————–+
| fixed_ip_address | |
| floating_ip_address | 2.2.2.4 |
| floating_network_id | ccf351c9-826c-4d93-9dd4-625302bf3051 |
| id | 8fc5a7b8-c5ab-4e8d-a9be-83ea8ffc34ef |
| port_id | |
| router_id | |
| status | DOWN |
| tenant_id | ef979882f1954a0fa4ce7daf244aa557 |
+———————+————————————–+
接下来我们要打通floatingip和server-64的管理网——10.0.44.64,打通的最后结果就是,在宿主机上可以ping通虚拟机的floatingip,在虚拟机里也能ping通宿主机的管理网地址。如图:
我们的目标,手动创建floatingip 2.2.2.100,把我们创建的Cirros虚拟机(内网IP:192.168.10.222/24)也能实现如上效果。
在QRouter ns里干点事
注:以下如没有特殊说明,均在Router namespace中执行
首先,在qrouter namespace里的rfp设备上增加一个/32位的公网IP地址,如下:
ip -4 addr add 2.2.2.100/32 scope global dev rfp-28e4ec01-f brd 2.2.2.100
其次,在iptables的nat表中添加floatingip和fix ip的规则,如下:
[root@server-233 ~(keystone_admin)]# iptables -t nat -A neutron-l3-agent-OUTPUT -d 2.2.2.100/32 -j DNAT –to-destination 192.168.10.222
[root@server-233 ~(keystone_admin)]# iptables -t nat -A neutron-l3-agent-PREROUTING -d 2.2.2.100/32 -j DNAT –to-destination 192.168.10.222
[root@server-233 ~(keystone_admin)]# iptables -t nat -A neutron-l3-agent-float-snat -s 192.168.10.222/32 -j SNAT –to-source 2.2.2.100
添加高级路由
ip -4 rule add from 192.168.10.222 priority 57482 table 16 type unicast
其中,table 16里是这样的规则:
[root@server-233 ~(keystone_admin)]# ip route show table 16
default via 169.254.31.29 dev rfp-28e4ec01-f
由于虚拟路由器的rfp设备和fip里的fpr设备是一对veth设备,那么会在fip namespace里收到包
在FIP ns里干点事
在FIP namespace里添加一条路由,如下:
ip -4 route replace 2.2.2.100/32 via 169.254.31.28 dev fpr-28e4ec01-f
最后,FIP namespace里的设备和路由信息是这样的:
[root@server-233 ~(keystone_admin)]# ip route
default via 2.2.2.1 dev fg-9f4709e2-8e
2.2.2.0/24 dev fg-9f4709e2-8e proto kernel scope link src 2.2.2.6
2.2.2.9 via 169.254.31.28 dev fpr-28e4ec01-f
2.2.2.100 via 169.254.31.28 dev fpr-28e4ec01-f
169.254.31.28/31 dev fpr-28e4ec01-f proto kernel scope link src 169.254.31.29
[root@server-233 ~(keystone_admin)]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: fpr-28e4ec01-f@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 42:55:ae:6e:ab:34 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 169.254.31.29/31 scope global fpr-28e4ec01-f
valid_lft forever preferred_lft forever
inet6 fe80::4055:aeff:fe6e:ab34/64 scope link
valid_lft forever preferred_lft forever
62: fg-9f4709e2-8e: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN
link/ether fa:16:3e:e1:15:10 brd ff:ff:ff:ff:ff:ff
inet 2.2.2.6/24 brd 2.2.2.255 scope global fg-9f4709e2-8e
valid_lft forever preferred_lft forever
inet6 fe80::f816:3eff:fee1:1510/64 scope link
valid_lft forever preferred_lft forever
好了,下面就是见证奇迹的时刻!!
LOOK!
作者简介:
苌智:
个人简介:SDN 工程师,2015年1月加入 UnitedStack有云,专注于虚拟网络和 SDN 方向,OpenStack Neutron 社区活跃贡献者。