openstack网络模型

来源:互联网 发布:昆明癫闲军海网络援助 编辑:程序博客网 时间:2024/06/06 09:30

一、OpenStack网络设备的命名规律:

1、TenantA的router和Linux网络命名空间qrouter名称

复制代码
root@controller:~# neutron --os-tenant-name TenantA --os-username UserA --os-password password --os-auth-url=http://localhost:5000/v2.0 router-list --field id --field name+--------------------------------------+-----------+| id                                   | name      |+--------------------------------------+-----------+| 680944ad-679c-4fe8-ae4b-258cd8ac337f | tenant-R1 |+--------------------------------------+-----------+
复制代码
root@network:~# ip netnsqdhcp-7c22bbd9-166c-4610-9a3d-3b8b92c77518qrouter-680944ad-679c-4fe8-ae4b-258cd8ac337f

即租户的虚拟路由器ID号和qrouter命名相对应。

2、TenantA的network和Linux网络命名空间qdhcp名称

复制代码
root@controller:~# neutron --os-tenant-name TenantA --os-username UserA --os-password password --os-auth-url=http://localhost:5000/v2.0 net-list  --field id --field name+--------------------------------------+-------------+| id                                   | name        |+--------------------------------------+-------------+| 7c22bbd9-166c-4610-9a3d-3b8b92c77518 | tenantA-Net || c8699820-7c6d-4441-9602-3425f2c630ec | Ext-Net     |+--------------------------------------+-------------+
复制代码
root@network:~# ip netnsqdhcp-7c22bbd9-166c-4610-9a3d-3b8b92c77518qrouter-680944ad-679c-4fe8-ae4b-258cd8ac337f

租户虚拟网络的ID号,与qdhcp命名相对应。

3、TenantA网络端口和其它的网络设备的名称

复制代码
root@controller:~# neutron --os-tenant-name TenantA --os-username UserA --os-password password --os-auth-url=http://localhost:5000/v2.0 port-list+--------------------------------------+------+-------------------+----------------------------------------------------------------------------------+| id                                   | name | mac_address       | fixed_ips                                                                        |+--------------------------------------+------+-------------------+----------------------------------------------------------------------------------+| 1653ec91-ad7d-40d9-b777-f74aec697026 |      | fa:16:3e:51:a2:97 | {"subnet_id": "c37d8ed0-372e-4b24-9ba2-897c38c6ddbf", "ip_address": "10.0.0.9"}  || 2df7c3ed-dfbb-480d-9cd3-fdefa079e66a |      | fa:16:3e:da:41:49 | {"subnet_id": "c37d8ed0-372e-4b24-9ba2-897c38c6ddbf", "ip_address": "10.0.0.3"}  || 81388454-30e0-45e4-b3dd-b7b2e8dbf067 |      | fa:16:3e:f7:e6:9c | {"subnet_id": "c37d8ed0-372e-4b24-9ba2-897c38c6ddbf", "ip_address": "10.0.0.1"}  || d7233b80-9d4b-4ef6-a60d-19b3be661069 |      | fa:16:3e:75:e0:5a | {"subnet_id": "c37d8ed0-372e-4b24-9ba2-897c38c6ddbf", "ip_address": "10.0.0.10"} |+--------------------------------------+------+-------------------+----------------------------------------------------------------------------------+
复制代码

IP地址为10.0.0.9的虚拟机(ID为bec0b963-99c0-4a56-ae04-936d47e173eb)端口为1653ec91-ad7d-40d9-b777-f74aec697026,那么与之相连的网络设备tab ,qbr,qvb,qvo的命名都是加上port ID的前缀11个字符。

验证:

通过查看libvirt XML定义文件/var/lib/nova/instances/<instance-id>/libvirt.xml可以看到qbr和tap。

复制代码
 <interface type="bridge">      <mac address="fa:16:3e:51:a2:97"/>      <model type="virtio"/>      <driver name="qemu"/>      <source bridge="qbr1653ec91-ad"/>  //虚机TAP设备所挂接的linux bridge      <target dev="tap1653ec91-ad"/>  //虚机所连接的interface </interface>
复制代码

通过virsh list查看qbr连接qvb和tap

复制代码
root@compute1:~# brctl showbridge name     bridge id               STP enabled     interfacesqbr1653ec91-ad          8000.22ca68904e2f       no              qvb1653ec91-ad                                                        tap1653ec91-adqbrd7233b80-9d          8000.964cf783c9e1       no              qvbd7233b80-9d                                                        tapd7233b80-9dvirbr0          8000.000000000000       yes
复制代码

同理,qr加上内部网关IP10.0.0.1的端口ID号前缀就是qrouter下的设备名了。

qg加上路由网关10.1.101.80端口号的前缀就是qrouter下的qg设备名了。

tap加上内网dhcp10.0.0.3的端口ID号前缀就是qdhcp下的设备名了。

可以使用下面这些命令验证:

复制代码
root@controller:~# neutron port-list+--------------------------------------+------+-------------------+-------------------------------------------------------------------------------------+| id                                   | name | mac_address       | fixed_ips                                                                           |+--------------------------------------+------+-------------------+-------------------------------------------------------------------------------------+| 1653ec91-ad7d-40d9-b777-f74aec697026 |      | fa:16:3e:51:a2:97 | {"subnet_id": "c37d8ed0-372e-4b24-9ba2-897c38c6ddbf", "ip_address": "10.0.0.9"}     || 2df7c3ed-dfbb-480d-9cd3-fdefa079e66a |      | fa:16:3e:da:41:49 | {"subnet_id": "c37d8ed0-372e-4b24-9ba2-897c38c6ddbf", "ip_address": "10.0.0.3"}     || 81388454-30e0-45e4-b3dd-b7b2e8dbf067 |      | fa:16:3e:f7:e6:9c | {"subnet_id": "c37d8ed0-372e-4b24-9ba2-897c38c6ddbf", "ip_address": "10.0.0.1"}     || accd8dbf-0f16-4aec-b797-bbb33abcdc83 |      | fa:16:3e:97:ee:cb | {"subnet_id": "ef86e785-8cec-486a-b67f-dcbba5311293", "ip_address": "10.100.0.103"} || bfe7eaa4-26bc-4fe9-9da2-550abf44beaa |      | fa:16:3e:e1:00:41 | {"subnet_id": "2c4155c9-5a2e-471c-a4d8-40a86b45ab0a", "ip_address": "10.1.101.83"}  || d7233b80-9d4b-4ef6-a60d-19b3be661069 |      | fa:16:3e:75:e0:5a | {"subnet_id": "c37d8ed0-372e-4b24-9ba2-897c38c6ddbf", "ip_address": "10.0.0.10"}    || eb60f9c4-2ddb-49ee-8b78-2fc2564a7600 |      | fa:16:3e:78:39:e9 | {"subnet_id": "2c4155c9-5a2e-471c-a4d8-40a86b45ab0a", "ip_address": "10.1.101.80"}  || f6812a11-c4ce-4880-8566-2206afcc612a |      | fa:16:3e:9e:75:a2 | {"subnet_id": "2c4155c9-5a2e-471c-a4d8-40a86b45ab0a", "ip_address": "10.1.101.82"}  |+--------------------------------------+------+-------------------+-------------------------------------------------------------------------------------+
复制代码
复制代码
root@network:~# ip netns exec qrouter-680944ad-679c-4fe8-ae4b-258cd8ac337f ifconfiglo        Link encap:Local Loopback            inet addr:127.0.0.1  Mask:255.0.0.0          inet6 addr: ::1/128 Scope:Host          UP LOOPBACK RUNNING  MTU:65536  Metric:1          RX packets:0 errors:0 dropped:0 overruns:0 frame:0          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0          collisions:0 txqueuelen:0           RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)qg-eb60f9c4-2d Link encap:Ethernet  HWaddr fa:16:3e:78:39:e9            inet addr:10.1.101.80  Bcast:10.1.101.255  Mask:255.255.255.0          inet6 addr: fe80::f816:3eff:fe78:39e9/64 Scope:Link          UP BROADCAST RUNNING  MTU:1500  Metric:1          RX packets:31953 errors:0 dropped:0 overruns:0 frame:0          TX packets:372 errors:0 dropped:0 overruns:0 carrier:0          collisions:0 txqueuelen:0           RX bytes:4158911 (4.1 MB)  TX bytes:40876 (40.8 KB)qr-81388454-30 Link encap:Ethernet  HWaddr fa:16:3e:f7:e6:9c            inet addr:10.0.0.1  Bcast:10.0.0.255  Mask:255.255.255.0          inet6 addr: fe80::f816:3eff:fef7:e69c/64 Scope:Link          UP BROADCAST RUNNING  MTU:1500  Metric:1          RX packets:882 errors:0 dropped:0 overruns:0 frame:0          TX packets:832 errors:0 dropped:0 overruns:0 carrier:0          collisions:0 txqueuelen:0           RX bytes:93440 (93.4 KB)  TX bytes:96206 (96.2 KB)
复制代码
复制代码
root@network:~# ip netns exec qdhcp-7c22bbd9-166c-4610-9a3d-3b8b92c77518 ifconfiglo        Link encap:Local Loopback            inet addr:127.0.0.1  Mask:255.0.0.0          inet6 addr: ::1/128 Scope:Host          UP LOOPBACK RUNNING  MTU:65536  Metric:1          RX packets:6 errors:0 dropped:0 overruns:0 frame:0          TX packets:6 errors:0 dropped:0 overruns:0 carrier:0          collisions:0 txqueuelen:0           RX bytes:3456 (3.4 KB)  TX bytes:3456 (3.4 KB)tap2df7c3ed-df Link encap:Ethernet  HWaddr fa:16:3e:da:41:49            inet addr:10.0.0.3  Bcast:10.0.0.255  Mask:255.255.255.0          inet6 addr: fe80::f816:3eff:feda:4149/64 Scope:Link          UP BROADCAST RUNNING  MTU:1500  Metric:1          RX packets:117 errors:0 dropped:0 overruns:0 frame:0          TX packets:48 errors:0 dropped:0 overruns:0 carrier:0          collisions:0 txqueuelen:0           RX bytes:11176 (11.1 KB)  TX bytes:5865 (5.8 KB)
复制代码

二、系统环境

环境见OpenStack三个节点icehouse-gre模式部署

1、系统中的网络设备:

复制代码
root@controller:~# nova list --all-tenant+--------------------------------------+-------+--------+------------+-------------+-----------------------+| ID                                   | Name  | Status | Task State | Power State | Networks              |+--------------------------------------+-------+--------+------------+-------------+-----------------------+| f467ba96-09c4-4eb7-b79c-5391f326c7d1 | vm001 | ACTIVE | -          | Running     | tenantA-Net=10.0.0.10 || bec0b963-99c0-4a56-ae04-936d47e173eb | vm002 | ACTIVE | -          | Running     | tenantA-Net=10.0.0.9  |+--------------------------------------+-------+--------+------------+-------------+-----------------------+root@controller:~# neutron net-list   +--------------------------------------+-------------+----------------------------------------------------+| id                                   | name        | subnets                                            |+--------------------------------------+-------------+----------------------------------------------------+| 7c22bbd9-166c-4610-9a3d-3b8b92c77518 | tenantA-Net | c37d8ed0-372e-4b24-9ba2-897c38c6ddbf 10.0.0.0/24   || c8699820-7c6d-4441-9602-3425f2c630ec | Ext-Net     | 2c4155c9-5a2e-471c-a4d8-40a86b45ab0a 10.1.101.0/24 |+--------------------------------------+-------------+----------------------------------------------------+root@controller:~# neutron subnet-list+--------------------------------------+------+---------------+-------------------------------------------------+| id                                   | name | cidr          | allocation_pools                                |+--------------------------------------+------+---------------+-------------------------------------------------+| 2c4155c9-5a2e-471c-a4d8-40a86b45ab0a |      | 10.1.101.0/24 | {"start": "10.1.101.80", "end": "10.1.101.100"} || c37d8ed0-372e-4b24-9ba2-897c38c6ddbf |      | 10.0.0.0/24   | {"start": "10.0.0.2", "end": "10.0.0.254"}      |+--------------------------------------+------+---------------+-------------------------------------------------+root@controller:~# neutron router-list+--------------------------------------+-----------+-----------------------------------------------------------------------------+| id                                   | name      | external_gateway_info                                                       |+--------------------------------------+-----------+-----------------------------------------------------------------------------+| 680944ad-679c-4fe8-ae4b-258cd8ac337f | tenant-R1 | {"network_id": "c8699820-7c6d-4441-9602-3425f2c630ec", "enable_snat": true} |+--------------------------------------+-----------+-----------------------------------------------------------------------------+root@controller:~# neutron port-list+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+| id                                   | name | mac_address       | fixed_ips                                                                          |+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+| 1653ec91-ad7d-40d9-b777-f74aec697026 |      | fa:16:3e:51:a2:97 | {"subnet_id": "c37d8ed0-372e-4b24-9ba2-897c38c6ddbf", "ip_address": "10.0.0.9"}    || 2df7c3ed-dfbb-480d-9cd3-fdefa079e66a |      | fa:16:3e:da:41:49 | {"subnet_id": "c37d8ed0-372e-4b24-9ba2-897c38c6ddbf", "ip_address": "10.0.0.3"}    || 81388454-30e0-45e4-b3dd-b7b2e8dbf067 |      | fa:16:3e:f7:e6:9c | {"subnet_id": "c37d8ed0-372e-4b24-9ba2-897c38c6ddbf", "ip_address": "10.0.0.1"}    || bfe7eaa4-26bc-4fe9-9da2-550abf44beaa |      | fa:16:3e:e1:00:41 | {"subnet_id": "2c4155c9-5a2e-471c-a4d8-40a86b45ab0a", "ip_address": "10.1.101.83"} || d7233b80-9d4b-4ef6-a60d-19b3be661069 |      | fa:16:3e:75:e0:5a | {"subnet_id": "c37d8ed0-372e-4b24-9ba2-897c38c6ddbf", "ip_address": "10.0.0.10"}   || eb60f9c4-2ddb-49ee-8b78-2fc2564a7600 |      | fa:16:3e:78:39:e9 | {"subnet_id": "2c4155c9-5a2e-471c-a4d8-40a86b45ab0a", "ip_address": "10.1.101.80"} || f6812a11-c4ce-4880-8566-2206afcc612a |      | fa:16:3e:9e:75:a2 | {"subnet_id": "2c4155c9-5a2e-471c-a4d8-40a86b45ab0a", "ip_address": "10.1.101.82"} |+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
复制代码
root@network:~# ip netnsqdhcp-7c22bbd9-166c-4610-9a3d-3b8b92c77518qrouter-680944ad-679c-4fe8-ae4b-258cd8ac337f

一个外部网络Ext-Net,它的子网是2c4155c9-5a2e-471c-a4d8-40a86b45ab0a,网段为10.1.101.0/24,分配池是10.1.101.8010.1.101.100。

有一个租户网络tenantA-Net(TenantA的网络,ID号为7c22bbd9-166c-4610-9a3d-3b8b92c77518,对应着qdhcp-7c22bbd9-166c-4610-9a3d-3b8b92c77518),它的子网是c37d8ed0-372e-4b24-9ba2-897c38c6ddbf,网段为10.0.0.0/24,分配池为10.0.0.210.0.0.254。

 TenantA有一个私有路由器tenant-R1(ID号为680944ad-679c-4fe8-ae4b-258cd8ac337f,对应着qrouter-680944ad-679c-4fe8-ae4b-258cd8ac337f)

2、系统中的端口号

复制代码
root@controller:~# neutron port-list+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+| id                                   | name | mac_address       | fixed_ips                                                                          |+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+| 1653ec91-ad7d-40d9-b777-f74aec697026 |      | fa:16:3e:51:a2:97 | {"subnet_id": "c37d8ed0-372e-4b24-9ba2-897c38c6ddbf", "ip_address": "10.0.0.9"}    || 2df7c3ed-dfbb-480d-9cd3-fdefa079e66a |      | fa:16:3e:da:41:49 | {"subnet_id": "c37d8ed0-372e-4b24-9ba2-897c38c6ddbf", "ip_address": "10.0.0.3"}    || 81388454-30e0-45e4-b3dd-b7b2e8dbf067 |      | fa:16:3e:f7:e6:9c | {"subnet_id": "c37d8ed0-372e-4b24-9ba2-897c38c6ddbf", "ip_address": "10.0.0.1"}    || bfe7eaa4-26bc-4fe9-9da2-550abf44beaa |      | fa:16:3e:e1:00:41 | {"subnet_id": "2c4155c9-5a2e-471c-a4d8-40a86b45ab0a", "ip_address": "10.1.101.83"} || d7233b80-9d4b-4ef6-a60d-19b3be661069 |      | fa:16:3e:75:e0:5a | {"subnet_id": "c37d8ed0-372e-4b24-9ba2-897c38c6ddbf", "ip_address": "10.0.0.10"}   || eb60f9c4-2ddb-49ee-8b78-2fc2564a7600 |      | fa:16:3e:78:39:e9 | {"subnet_id": "2c4155c9-5a2e-471c-a4d8-40a86b45ab0a", "ip_address": "10.1.101.80"} || f6812a11-c4ce-4880-8566-2206afcc612a |      | fa:16:3e:9e:75:a2 | {"subnet_id": "2c4155c9-5a2e-471c-a4d8-40a86b45ab0a", "ip_address": "10.1.101.82"} |+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
复制代码
复制代码
root@network:~# ip netnsqdhcp-7c22bbd9-166c-4610-9a3d-3b8b92c77518qrouter-680944ad-679c-4fe8-ae4b-258cd8ac337froot@network:~# ip netns exec qrouter-680944ad-679c-4fe8-ae4b-258cd8ac337f ifconfiglo        Link encap:Local Loopback            inet addr:127.0.0.1  Mask:255.0.0.0          inet6 addr: ::1/128 Scope:Host          UP LOOPBACK RUNNING  MTU:65536  Metric:1          RX packets:0 errors:0 dropped:0 overruns:0 frame:0          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0          collisions:0 txqueuelen:0           RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)qg-eb60f9c4-2d Link encap:Ethernet  HWaddr fa:16:3e:78:39:e9            inet addr:10.1.101.80  Bcast:10.1.101.255  Mask:255.255.255.0          inet6 addr: fe80::f816:3eff:fe78:39e9/64 Scope:Link          UP BROADCAST RUNNING  MTU:1500  Metric:1          RX packets:32619 errors:0 dropped:0 overruns:0 frame:0          TX packets:374 errors:0 dropped:0 overruns:0 carrier:0          collisions:0 txqueuelen:0           RX bytes:4280629 (4.2 MB)  TX bytes:40960 (40.9 KB)qr-81388454-30 Link encap:Ethernet  HWaddr fa:16:3e:f7:e6:9c            inet addr:10.0.0.1  Bcast:10.0.0.255  Mask:255.255.255.0          inet6 addr: fe80::f816:3eff:fef7:e69c/64 Scope:Link          UP BROADCAST RUNNING  MTU:1500  Metric:1          RX packets:1012 errors:0 dropped:0 overruns:0 frame:0          TX packets:914 errors:0 dropped:0 overruns:0 carrier:0          collisions:0 txqueuelen:0           RX bytes:106266 (106.2 KB)  TX bytes:108626 (108.6 KB)root@network:~# ip netns exec qdhcp-7c22bbd9-166c-4610-9a3d-3b8b92c77518 ifconfiglo        Link encap:Local Loopback            inet addr:127.0.0.1  Mask:255.0.0.0          inet6 addr: ::1/128 Scope:Host          UP LOOPBACK RUNNING  MTU:65536  Metric:1          RX packets:6 errors:0 dropped:0 overruns:0 frame:0          TX packets:6 errors:0 dropped:0 overruns:0 carrier:0          collisions:0 txqueuelen:0           RX bytes:3456 (3.4 KB)  TX bytes:3456 (3.4 KB)tap2df7c3ed-df Link encap:Ethernet  HWaddr fa:16:3e:da:41:49            inet addr:10.0.0.3  Bcast:10.0.0.255  Mask:255.255.255.0          inet6 addr: fe80::f816:3eff:feda:4149/64 Scope:Link          UP BROADCAST RUNNING  MTU:1500  Metric:1          RX packets:126 errors:0 dropped:0 overruns:0 frame:0          TX packets:50 errors:0 dropped:0 overruns:0 carrier:0          collisions:0 txqueuelen:0           RX bytes:12344 (12.3 KB)  TX bytes:6595 (6.5 KB)
复制代码

neutron port-list出来一共7个端口

显然1653ec91-ad7d-40d9-b777-f74aec697026(10.0.0.9)和d7233b80-9d4b-4ef6-a60d-19b3be661069(10.0.0.10)是虚拟机vm002和vm001的私有IP地址端口(虚拟机tap网络设备端口)。

端口f6812a11-c4ce-4880-8566-2206afcc612a(10.1.101.82)和bfe7eaa4-26bc-4fe9-9da2-550abf44beaa(10.1.101.83)是两个浮动IP。

端口81388454-30e0-45e4-b3dd-b7b2e8dbf067(10.0.0.1)和端口eb60f9c4-2ddb-49ee-8b78-2fc2564a7600(10.1.101.80)是qrouter上面的网络端口。分别作TenantA的网络环境中,子网(c37d8ed0-372e-4b24-9ba2-897c38c6ddbf,网段为10.0.0.0/24)的网关qr-81388454-30和外网通道qg-eb60f9c4-2d。【多个网络对应多个qrouter,即qr和qg设备】

 端口2df7c3ed-dfbb-480d-9cd3-fdefa079e66a(10.0.0.3)是qdhcp上面的网络端口tap2df7c3ed-df,为TenantA的网络环境中,子网(c37d8ed0-372e-4b24-9ba2-897c38c6ddbf,网段为10.0.0.0/24)动态分配私有IP地址,提供子网dhcp服务。【多个子网对应多个qdhcp,即tap设备】

3、网络节点上的linux网桥和OVS网桥:

复制代码
root@network:~# brctl show                  
bridge name     bridge id               STP enabled     interfaces
root@network:~# ovs-vsctl show1c921779-83ff-4493-8def-df53783ebae2 Bridge br-ex Port "qg-eb60f9c4-2d" Interface "qg-eb60f9c4-2d" type: internal Port "eth2" Interface "eth2" Port br-ex Interface br-ex type: internal Bridge br-int fail_mode: secure Port br-int Interface br-int type: internal Port "tap2df7c3ed-df" tag: 10 Interface "tap2df7c3ed-df" type: internal Port patch-tun Interface patch-tun type: patch options: {peer=patch-int} Port "qr-81388454-30" tag: 10 Interface "qr-81388454-30" type: internal Bridge br-tun Port patch-int Interface patch-int type: patch options: {peer=patch-tun} Port "gre-0a00011f" Interface "gre-0a00011f" type: gre options: {in_key=flow, local_ip="10.0.1.21", out_key=flow, remote_ip="10.0.1.31"} Port "gre-0a000129" Interface "gre-0a000129" type: gre options: {in_key=flow, local_ip="10.0.1.21", out_key=flow, remote_ip="10.0.1.41"} Port br-tun Interface br-tun type: internal ovs_version: "2.0.2"
复制代码

可以看出网络节点没有运行虚拟机,所以linux网桥为空。
OVS网桥br-int上面有qrouter的qr端口和qdhcp的tap端口;

OVS网桥br-ex上面有qrouter的qg端口,并且br-ex与物理网卡eth2相连;

OVS网桥br-tun只是patch网桥br-int和构建隧道平面。

4、compute节点上的linux网桥和OVS网桥:

复制代码
root@compute1:~# virsh list Id    Name                           State---------------------------------------------------- 2     instance-00000029              running 3     instance-00000028              runningroot@compute1:~# brctl show bridge name     bridge id               STP enabled     interfacesqbr1653ec91-ad          8000.22ca68904e2f       no              qvb1653ec91-ad                                                        tap1653ec91-adqbrd7233b80-9d          8000.964cf783c9e1       no              qvbd7233b80-9d                                                        tapd7233b80-9dvirbr0          8000.000000000000       yesroot@compute1:~# ovs-vsctl show   ///查询和更新ovs-vswitchd的配置14b9e1b3-2d80-4380-92b0-f585cf9f74f7    Bridge br-tun   //OVS Tunnel 桥br-tun        Port "gre-0a000129"  //端口,连接GRE Tunnel            Interface "gre-0a000129"                type: gre                options: {in_key=flow, local_ip="10.0.1.31", out_key=flow, remote_ip="10.0.1.41"} //GRE Tunnel 是点到点之间建立的,这头的IP是10.0.1.31,那头的IP地址是10.0.1.41        Port "gre-0a000115"  //端口,连接GRE Tunnel            Interface "gre-0a000115"                type: gre                options: {in_key=flow, local_ip="10.0.1.31", out_key=flow, remote_ip="10.0.1.21"}  //GRE Tunnel 是点到点之间建立的,这头的IP是10.0.1.31,那头的IP地址是10.0.1.21        Port br-tun            Interface br-tun                type: internal        Port patch-int  //端口patch-int,用来连接桥br-int            Interface patch-int                type: patch                options: {peer=patch-tun}    Bridge br-int   //OVS integration网桥 br-int        fail_mode: secure        Port "qvod7233b80-9d"  //端口,用来连接【一个虚拟网卡的TAP设备连接的linux bridge】            tag: 1            Interface "qvod7233b80-9d"        Port "qvo1653ec91-ad"   //端口,用来连接【一个虚拟网卡的TAP设备连接的linux bridge】            tag: 1            Interface "qvo1653ec91-ad"        Port patch-tun  //端口,用来连接br-tun            Interface patch-tun                type: patch                options: {peer=patch-int}  //和桥 br-tun上的patch-int是对等端口        Port br-int            Interface br-int                type: internal    ovs_version: "2.0.2"
root@compute1:~# ovs-ofctl show br-tun  ///查询和更新OpenFlow交换机和控制器OFPT_FEATURES_REPLY (xid=0x2): dpid:0000d63ebd331948n_tables:254, n_buffers:256capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IPactions: OUTPUT SET_VLAN_VID SET_VLAN_PCP STRIP_VLAN SET_DL_SRC SET_DL_DST SET_NW_SRC SET_NW_DST SET_NW_TOS SET_TP_SRC SET_TP_DST ENQUEUE 1(patch-int): addr:9a:0f:cb:ab:46:7a //端口 patch-int的ID 是 1     config:     0     state:      0     speed: 0 Mbps now, 0 Mbps max 2(gre-0a000115): addr:e2:01:f1:7d:a5:af //端口 gre-0a000115的ID 是 2     config:     0     state:      0     speed: 0 Mbps now, 0 Mbps max 3(gre-0a000129): addr:8e:b1:ce:5f:51:9b     config:     0     state:      0     speed: 0 Mbps now, 0 Mbps max LOCAL(br-tun): addr:d6:3e:bd:33:19:48     config:     0     state:      0     speed: 0 Mbps now, 0 Mbps maxOFPT_GET_CONFIG_REPLY (xid=0x4): frags=normal miss_send_len=0
 
复制代码

可以看出计算节点compute节点上面运行2个虚拟机。

可以看到qbr1653ec91-adlinux网桥qvb1653ec91-ad端口和tap1653ec91-ad端口。

OVS网桥br-int上有qvo端口,

OVS网桥br-tun只是patch网桥br-int和构建隧道平面。

三、虚拟机中数据流

下图是典型的Neutron-OVS-GRE网络模式图。

有两个计算节点Compute-01和Compute-02和一个网络节点。

1、网络设备简介

tap:是vm连接qbr的接口,在qbr上。与此对应的是vm上的虚拟网卡。

qbr:就是Linux bridge

qvb:veth pari bridge side。qvb和qvo是qbr和ovs之间连通的一对接口。qvb是这对接口中在qbr那边的接口。

qvo:veth pair openvswitch side。qvb和qvo是qbr和ovs之间连通的一对接口。qvb是这对接口中在ovs那边的接口。

qr:l3 agent managed port,是router端的port。

qg:l3 agent managed port,是gateway端的port。

2、虚拟机通外网(虚拟机数据从计算节点到网络节点到外网)

 假设物理计算节点Compute-02上面的虚拟机VM-003的网卡eth0上有网络数据包向外部物理路由器网关10.1.101.254发出,那么数据流如下:

数据依次经过tap设备;Linux Bridge设备qbr;qvb和qvo虚拟网络设备;到达物理计算节点的OVS网桥br-int上,被打上VLAN ID Tag;br-int将数据包attach到计算节点Compute02的OVS网桥br-tun上,将VLAN ID转化为Tunnel ID;数据包再从计算节点Compute-02的OVS网桥br-tun与网络节点Network-node上的OVS网桥br-tun构成的网络隧道穿过(要通过物理网卡)将Tunnel ID转化为VLAN ID,交付到网络节点的OVS网桥br-int上;网络节点上的br-int通过qr设备借助Linux网络命名空间qrouter连通br-ex上的qg设备(这个过程router的NAT表将fixed IP地址转化为floating IP地址),将数据包交付到OVS网桥br-ex上;最后br-ex通过网络节点的外部物理网卡eth2把数据包送达到外部路由器网关。

3、计算节点中虚拟机之间数据流

(1) 同一个host上同一个子网内虚拟机之间的通信:

因为br-int是个虚拟的二层交换机,比如TenantA的两个虚拟机vm001和vm002可以经过br-int桥直接通信,不需要通过br-tun。

(2)不同主机上同一个子网内虚拟机通信:

Compute1的虚拟机发出的数据包,经过qbr到达br-int,被打上vlan ID;到达br-tun,将VLAN ID转化为Tunnel ID,从GRE Tunnel发出,到达compute2节点。

(3)虚拟机发送DHCP请求

compute节点数据包从br-int到br-tun通过GRE隧道到network节点br-tun,再经过br-int到qdhcp,qdhcp返回其fixed IP地址,原路返回。

4、分别介绍计算节点和网络节点的网络设备

计算节点:

(1)与虚拟机相连的tap设备

每个虚拟机都有一个虚拟网卡eth0,eth0和主机上的一个TAP设备连接,该TAP设备直接挂载在一个linux bridge qbr上,qbr和br-int相连。其实理想的情况下,tap设备能和br-int直接相连就好了,如图中绿色框所示。因为OpenStack要借助TAP设备的iptables rules实现安全组,但是TAP和OVS网桥br-int直接连接的话,br-int不兼容iptables规则,所以OpenStack就用了一个变通的权宜之计,多加了一层linux bridge。导致OVS br-int和linux 网桥都是二层桥,但同时出现了。

Neutron使用tap设备的iptables来实现Security groups

查看虚拟机vm002的tap设备上的iptables:

root@compute1:~# iptables -S |grep tap1653ec91-ad-A neutron-openvswi-FORWARD -m physdev --physdev-out tap1653ec91-ad --physdev-is-bridged -j neutron-openvswi-sg-chain-A neutron-openvswi-FORWARD -m physdev --physdev-in tap1653ec91-ad --physdev-is-bridged -j neutron-openvswi-sg-chain-A neutron-openvswi-INPUT -m physdev --physdev-in tap1653ec91-ad --physdev-is-bridged -j neutron-openvswi-o1653ec91-a-A neutron-openvswi-sg-chain -m physdev --physdev-out tap1653ec91-ad --physdev-is-bridged -j neutron-openvswi-i1653ec91-a-A neutron-openvswi-sg-chain -m physdev --physdev-in tap1653ec91-ad --physdev-is-bridged -j neutron-openvswi-o1653ec91-a

OpenStack Neutron在neutron-openvswi-sg-chain上实现security groups。

使用默认安全组的情况:

neutron-openvswi-i1653ec91-a控制进入虚拟机的traffic

复制代码
root@compute1:~# iptables -S |grep neutron-openvswi-i1653ec91-a-N neutron-openvswi-i1653ec91-a-A neutron-openvswi-i1653ec91-a -m state --state INVALID -j DROP-A neutron-openvswi-i1653ec91-a -m state --state RELATED,ESTABLISHED -j RETURN-A neutron-openvswi-i1653ec91-a -p udp -m udp -m multiport --dports 1:65535 -j RETURN-A neutron-openvswi-i1653ec91-a -s 10.0.0.10/32 -j RETURN-A neutron-openvswi-i1653ec91-a -p icmp -j RETURN-A neutron-openvswi-i1653ec91-a -p tcp -m tcp -m multiport --dports 1:65535 -j RETURN-A neutron-openvswi-i1653ec91-a -s 10.0.0.3/32 -p udp -m udp --sport 67 --dport 68 -j RETURN-A neutron-openvswi-i1653ec91-a -j neutron-openvswi-sg-fallback-A neutron-openvswi-sg-chain -m physdev --physdev-out tap1653ec91-ad --physdev-is-bridged -j neutron-openvswi-i1653ec91-a
复制代码

neutron-openvswi-o1653ec91-a控制从虚拟机出去的traffic

复制代码
root@compute1:~# iptables -S |grep neutron-openvswi-o1653ec91-a-N neutron-openvswi-o1653ec91-a-A neutron-openvswi-INPUT -m physdev --physdev-in tap1653ec91-ad --physdev-is-bridged -j neutron-openvswi-o1653ec91-a-A neutron-openvswi-o1653ec91-a -p udp -m udp --sport 68 --dport 67 -j RETURN-A neutron-openvswi-o1653ec91-a -j neutron-openvswi-s1653ec91-a-A neutron-openvswi-o1653ec91-a -p udp -m udp --sport 67 --dport 68 -j DROP-A neutron-openvswi-o1653ec91-a -m state --state INVALID -j DROP-A neutron-openvswi-o1653ec91-a -m state --state RELATED,ESTABLISHED -j RETURN-A neutron-openvswi-o1653ec91-a -j RETURN-A neutron-openvswi-o1653ec91-a -j neutron-openvswi-sg-fallback-A neutron-openvswi-sg-chain -m physdev --physdev-in tap1653ec91-ad --physdev-is-bridged -j neutron-openvswi-o1653ec91-a
复制代码

 添加一条security group规则允许使用TCP 22端口

复制代码
root@controller:~# neutron --os-tenant-name TenantA --os-username UserA --os-password password --os-auth-url=http://localhost:5000/v2.0 security-group-rule-create --protocol tcp --port-range-min 22 --port-range-max 22 --direction ingress defaultCreated a new security_group_rule:+-------------------+--------------------------------------+| Field             | Value                                |+-------------------+--------------------------------------+| direction         | ingress                              || ethertype         | IPv4                                 || id                | be3d6a06-be6b-4f51-b1a5-294ad2a0a261 || port_range_max    | 22                                   || port_range_min    | 22                                   || protocol          | tcp                                  || remote_group_id   |                                      || remote_ip_prefix  |                                      || security_group_id | 8bd8fb6b-7141-4900-8321-390cc1a5d999 || tenant_id         | 60a10cd7a61b493d910eabd353c07567     |+-------------------+--------------------------------------+
复制代码

那么tap设备的iptables会出现下面变化:

Connection to neutron failed: [Errno 111] Connection refusedroot@compute1:~# iptables -S | grep 22-A FORWARD -d 192.168.122.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT-A FORWARD -s 192.168.122.0/24 -i virbr0 -j ACCEPT-A neutron-openvswi-i1653ec91-a -p tcp -m tcp --dport 22 -j RETURN-A neutron-openvswi-id7233b80-9 -p tcp -m tcp --dport 22 -j RETURN

(2)OVS一体化网桥br-int

br-int是OpenvSwitch创建的虚拟网桥,但在实际运行中它充当着虚拟交换机的角色。br-int上的端口tap设备将宿主机上的虚拟机连接到同一网络交换层上。再透过本机OVS网桥br-tun的互联协议可以将OpenStack系统架构中所有节点的br-int组织成一个更大的虚拟交换机BR-INT{compuer-01-br-int + compuer-02-br-int….}。

每一个使用neutron net-create 命令创建的network都有一个新的vlan ID。见ovsl-vsctl show命令显示结果中的Port的tag值。

br-int处理从VM进出的traffic的vlan ID。

(3)OVS通道网络br-tun

br-tun是OVS创建的虚拟网桥,它的作用是向下直接与br-int连接作为网络数据的进出口;对上通过特定的通信协议与各个节点上的br-tun相连构成一个扁平的通信/通道层。如果把所有的br-int构建的抽象层定义为虚拟二层网络,那么所有的br-tun构成的抽象层便是虚拟三层网络了。

br-tun使用OpenFlow规则处理vlan ID和Tunnel ID 的转换

从下面OpenFlow rule tables可见两种ID的转化过程:

复制代码
root@compute1:~# ovs-ofctl show br-tun
OFPT_FEATURES_REPLY (xid=0x2): dpid:0000d63ebd331948
n_tables:254, n_buffers:256
capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP
actions: OUTPUT SET_VLAN_VID SET_VLAN_PCP STRIP_VLAN SET_DL_SRC SET_DL_DST SET_NW_SRC SET_NW_DST SET_NW_TOS SET_TP_SRC SET_TP_DST ENQUEUE
 1(patch-int): addr:9a:0f:cb:ab:46:7a //端口patch-int的ID是 1
     config:     0
     state:      0
     speed: 0 Mbps now, 0 Mbps max
 2(gre-0a000115): addr:e2:01:f1:7d:a5:af //端口gre-0a000115的ID是 2
     config:     0
     state:      0
     speed: 0 Mbps now, 0 Mbps max
 3(gre-0a000129): addr:8e:b1:ce:5f:51:9b //端口gre-0a000129的ID是 3
     config:     0
     state:      0
     speed: 0 Mbps now, 0 Mbps max
 LOCAL(br-tun): addr:d6:3e:bd:33:19:48
     config:     0
     state:      0
     speed: 0 Mbps now, 0 Mbps max
OFPT_GET_CONFIG_REPLY (xid=0x4): frags=normal miss_send_len=0
root@compute1:~# ovs-ofctl dump-flows br-tunNXST_FLOW reply (xid=0x4): cookie=0x0, duration=99058.105s, table=0, n_packets=0, n_bytes=0, idle_age=65534, hard_age=65534, priority=1,in_port=3 actions=resubmit(,2)//从端口3即gre-0a000129进来的traffic会被重新执行table 2的rule cookie=0x0, duration=164986.43s, table=0, n_packets=303, n_bytes=29712, idle_age=7626, hard_age=65534, priority=1,in_port=1 actions=resubmit(,1)//从端口1即patch-int进来的traffic重新执行table1 cookie=0x0, duration=164981.72s, table=0, n_packets=188, n_bytes=28694, idle_age=7626, hard_age=65534, priority=1,in_port=2 actions=resubmit(,2)//从端口2即gre-0a000115进来的traffic重新执行table2 cookie=0x0, duration=164986.109s, table=0, n_packets=4, n_bytes=320, idle_age=65534, hard_age=65534, priority=0 actions=drop cookie=0x0, duration=164985.783s, table=1, n_packets=257, n_bytes=25328, idle_age=7626, hard_age=65534, priority=1,dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,20)//重新执行table 20的rule cookie=0x0, duration=164985.31s, table=1, n_packets=46, n_bytes=4384, idle_age=7631, hard_age=65534, priority=1,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,21) cookie=0x0, duration=164979.109s, table=2, n_packets=188, n_bytes=28694, idle_age=7626, hard_age=65534, priority=1,tun_id=0x2 actions=mod_vlan_vid:1,resubmit(,10)//从neutron node来的traffic,打上vlan ID 1,重新执行table 10 的rule cookie=0x0, duration=164984.991s, table=2, n_packets=8, n_bytes=648, idle_age=65534, hard_age=65534, priority=0 actions=drop cookie=0x0, duration=164984.676s, table=3, n_packets=0, n_bytes=0, idle_age=65534, hard_age=65534, priority=0 actions=drop cookie=0x0, duration=164984.395s, table=10, n_packets=188, n_bytes=28694, idle_age=7626, hard_age=65534, priority=1 actions=learn(table=20,hard_timeout=300,priority=1,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:0->NXM_OF_VLAN_TCI[],load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],output:NXM_OF_IN_PORT[]),output:1///学习规则table20,从port1即patch-int发出 cookie=0x0, duration=164984.067s, table=20, n_packets=0, n_bytes=0, idle_age=65534, hard_age=65534, priority=0 actions=resubmit(,21)//重新执行table 21的rule cookie=0x0, duration=164979.293s, table=21, n_packets=36, n_bytes=3576, idle_age=7631, hard_age=65534, dl_vlan=1 actions=strip_vlan,set_tunnel:0x2,output:3,output:2//去掉vlan ID,打上tunnel ID 2即neutron节点的tunnel ID,从端口2即gre端口发出 cookie=0x0, duration=164983.75s, table=21, n_packets=10, n_bytes=808, idle_age=65534, hard_age=65534, priority=0 actions=drop
复制代码

网络节点:

(1)OVS通道网桥br-tun

它与计算节点上的br-tun作用相同,只是作为通道层用于连接别的物理节点。唯一不同的是这个br-tun连接的是网络节点的br-int,网络节点br-int与计算节点的br-int区别较大。

(2)OVS一体化网桥br-int

br-int是OVS创建的虚拟网桥,也起到了虚拟交换机的作用。上面主要有两类设备:一类是tap设备,另一类是qr设备。

linux网络命名空间qdhcp和qrouter均由l3-agent所创建,用来隔离管理租户的虚拟网络和路由。

br-int的tap设备,ip地址为xxx.xxx.xxx.3与dnsmasq进程构成dhcp,为新创建的虚拟机动态分配私有IP地址。

br-int上的qr设备,IP地址一般为xxx.xxx.xxx.1与br-ex的qg设备构成qrouter,为租户网络做路由转发,通过qg打通租户内部的虚拟网络和外部的物理网络。

(3)OVS外部网桥

br-ex是OVS创建的虚拟网桥,网桥上有qg设备端口,它是打通租户网络和外部网络的重要通道。另外br-ex与物理网卡(图中是eth2)相连,通往internet网络。

http://docs.openstack.org/admin-guide-cloud/content/under_the_hood_openvswitch.html





本文不会讲解每一种网络技术的细节,也不会讲解 Neutron 网络的实现细节,而是高度概括这些基础网络技术的技术本质,试图帮您在这些网络技术和 Neutron 之间建立更高级别的联系,让大家举重若轻,全局系统把握 Neutron。所以阅读本文前,了解以下知识将有助于本文的理解:

  • 了解 OSI 七层模型,了解基本的 L2 层帧转发、L3 层路由转发等网络基础知识。
  • 了解 Neutron 网络或者其他任何云网络也将有助于本文的理解。

Neutron 是什么?

一句话描述,Neutron 是 OpenStack 的一个子模块,它的实质是一个定义良好的框架用来驱动 L2-L7 层不同的底层网络技术来为第三方应用独立地提供租户隔离的虚拟网络服务。

上面的定义只是笔者对 Neutron 长期以来一个最直观的感受,仁者见仁,智者见智,相信您在读完本文后,对于“Neutron 是什么”这个问题会有自己的看法。

笔者之前在 developworks 上曾发表过一篇文章,《漫步云中网络》,在那篇文章中,笔者也没有直接具体讲 Quantum HOWTO 的问题(目前 Quantum 因为与一家公司重名,所以已更名为 Neturon),而是描述了 Qauntum 网络背后的一般原理,读者至少可以从那篇文章获取如下知识:

  • 知道 Linux 下实现虚拟网卡一般使用 TAP/TUN 技术。一个 TAP 设备就是 Linux 下的一个进程,两个虚机通过虚拟网卡的通信,实际上就是 Linux 中两个进程间的通信。所以很多 Hypervisor 为了提升同一物理机中的两台虚机之间的网络 IO 性能采用 DMA(直接内存访问)技术也就毫不奇怪了。
  • 知道在 L2 层,Linux 网桥是虚拟交换机的一种实现,知道无论是虚拟交换机还是物理交换机,原理都是一样的。知道 L2 层用于使用 VLAN 来做物理隔离。知道 FLAT 网络和 VLAN 网络的根本区别。
  • 知道在 L3 层如何通过 ipv4 forward 功能进行静态路由转发,知道如何使用 iptables 的 SNAT 和 DNAT 规则实现内网中的虚机访问外网和外网访问内网上的虚机(也就是所谓的浮动 IP)。

在我写第一季的时候,Quantum 只实现了 L2,L3 两层,所以在《漫步云中网络》一文也就只涉及了 L2、L3 两层背后的网络原理知识。但是现在 Neutron 在 L2 和 L3 层上实现了更多的网络技术,同时在 L4-L7 层也有更多的动作,所以有必要出第二季对整个 L2-L7 层的网络进行一个全面的疏理。本季中也会概括 L2、L3 的理论知识,但不会像第一季中那么详细,大家也可以结合第一季进行学习。所以,本文的主要内容有:

  • L2 层:交换机的原理;为什么会出现 VLAN;Neutron 中 FLAT 与 VLAN 的区别;
  • L3 层:Linux 上实现静态路由的技术(namespace + ipv4 forward + iptables);动态路由;Neutron 用 L3 层的 GRE 遂道技术克服 VLAN 大小的限制;
  • 利用 L3 层扩展 L2 层的遂道技术:VXLAN; NVGRE;
  • 利用 L2 层扩展 L3 层的标签技术:MPLS;
  • 区别于传统路由转发的流转发技术:OpenFlow 以及 SDN 的实质;
  • L4-L7 层:如 LBaaS;FWaaS; VPNaaS; NATaaS

OSI 七层模型

提到网络不得不提到 OSI 七层模型,从上到下,OSI 分为七层:

  • L7,应用层
  • L6,表示层
  • L5,会话层
  • L4,运输层
  • L3,网络层
  • L2,数据链路层
  • L1,物理层

对于 OSI 七层模型至少得知道下列常识:

  • L2 层主要通过 MAC 地址进行帧转发
  • L3 层主要通过 IP 地址进行包转发
  • L4 层再结合端口 PORT 来唯一标志一个应用程序
  • 协议是通信双方对数据的一个理解,例如在 L7 层有我们常用的协议 HTTP 协议,在 HTTP 协议上传输的是通信双方都理解的 HTML 数据;在 L4 层有两大重要协议,无连接的 UDP 和面向连接的 TCP。可靠传输可以通过 TCP 协议来实现,对于下面的 L2,L3 层并不需要实现可靠传输机制,像 L2 层,传输数据帧的过程中出了错误简单丢弃就行,上层的 TCP 自然会控制它重传。socket 不是协议,只是 L4 层传输数据的一个接口定义。
  • 当网卡接收到数据之后,硬件网卡会给 CPU 发中断,CPU 在指令周期内指示操作系统软件从网卡缓冲区取走数据,然后操作系统将数据交给 TCP/IP 栈来处理,到了 L2 层,解析 L2 层数据帧头中的 MAC 地址来决定 L2 中的转发,如需 3 层转发就交给上面的 L3 层解析出数据包头中的 IP 地址来决定 L3 中的转发,依此类推。

L1

L1 是物理层,主要是涉及硬件的一些电气特性,与偏软件的 Neutron 虚拟网络从知识脉络上关系甚少,不展开。

L2

FLAT

L2 数据链路层通过交换机设备进行帧转发。交换机在接收到帧之后(L2 层叫帧,L3 层叫包)先解析出帧头中的 MAC 地址,再在转发表中查找是否有对应 MAC 地址的端口,有的话就从相应端口转发出去。没有,就洪泛(专业术语,即将帧转发到交换机的所有端口),每个端口上的计算机都检查帧头中的 MAC 地址是否与本机网卡的 MAC 地址一致,一致的话就接收数据帧,不一致就直接丢弃。而转发表是通过自学习自动建立的。

这里引出一个重要概念,混杂模式。默认情况下计算机只接收和本机 MAC 地址一致的数据帧,不一致就丢弃,如果要求计算机接受所有帧的话,就要设置网卡为混杂模式(ifconfig eth0 0.0.0.0 promisc up)。所以在虚拟网桥中,如果希望虚机和外部通讯,必须打开桥接到虚拟网桥中物理网卡的混杂模式特性。

VLAN

FLAT 中的洪泛,经常会在一个局域网内产生大量的广播,这也就是所谓的“广播风暴”。为了隔离广播风暴,引入了 VLAN 的概念。即为交换机的每一个端口设置一个 1-4094 的数字,交换机根据 MAC 地址进行转发的同时也要结合 VLAN 号这个数字,不同的话也要丢弃。这样就实现了 L2 层数据帧的物理隔离,避免了广播风暴。

在 Neutron 中,我们知道,截止到笔者写这篇文章之时已经实现了 FLAT、VLAN、GRE、VXLAN 四种网络拓扑。那么如何区分 FLAT 和 VLAN 呢?很简单,结合 VLAN 号和 MAC 地址进行转发的是 VLAN 模式,只根据 MAC 地址进行转发的是 FLAT 模式。

VLAN 的缺点与大 L2 层技术

实际上,遂道技术并不能完全归类于 L2 层。因为有基于 L2 层的遂道协议,例如 PPTP 和 L2TP 等;也有基于 L3 层的遂道,如 GRE、VXLAN、NVGRE 等;但是这些遂道从技术原理上讲差不多,所以笔者将这些技术作为“大 L2 层”放在一块来描述,但希望读者不要误解。

本文只将着重讲 Neutron 中用到的 GRE 和 VXLAN 技术。

L3 层的 GRE 遂道

VLAN 技术能有效隔离广播域,但同时有很多缺点:

  • 要求穿越的所有物理交换机都配置允许带有某个 VLAN 号的数据帧通过,因为物理交换机通常只提供 CLI 命令,不提供远程接口可编程调用,所以都需要手工配置它,容易出错且工作量巨大,纯粹的体力劳动,影响了大规模部署。
  • VLAN 号只能是 1-4094 中的一个数字,对于小规模的私有云可能不是个问题,但对于租户众多的公有云,可选择的 VLAN 号的范围是不是少了点呢?

为了克服上面的缺点,Neutron 开发了对 GRE 模式的支持。GRE 是 L3 层的遂道技术,本质是在遂道的两端的 L4 层建立 UDP 连接传输重新包装的 L3 层包头,在目的地再取出包装后的包头进行解析。因为直接在遂道两端建立 UDP 连接,所以不需要在遂道两端路径的物理交换机上配置 TRUNK 的操作。

说说 GRE 的缺点吧:

  • GRE 将 L2 层的操作上移到 L3 层来做,性能肯定是会下降的。同时,由于遂道只能是点对点的,所以可以想象,如果有 N 个节点,就会有 N*(N-1)条 GRE 遂道,对于宝贵的 L4 层的端口资源也是一个浪费哦。那也是为什么 GRE 遂道使用 UDP 而不使用 TCP 的原因了,因为 UDP 用完后就可以释放,不用老占着端口又不用。
  • 在 Neutron 的 GRE 实现中,即使两台物理机上的两台虚机也不是直接建立 GRE 遂道的。而是通过 L3-agent 网络节点进行中转,这样做是基于方便使用 iptables 隔离网络流量的考虑。

利用 L3 层扩展 L2 层的遂道技术 VXLAN 与 SDN 的本质

VXLAN 是 VMware 的技术,可以克服 VLAN 号不足的问题;同时也可以克服 GRE 实质上作为点对点遂道扩展性太差的问题。

如果说 GRE 的本质是将 L3 层的数据包头重新定义后再通过 L4 层的 UDP 进行传输,那么 VXLAN 的本质就是对 L2 层的数据帧头重新定义再通过 L4 层的 UDP 进行传输。也就是笔者说的所谓的利用 L3 层扩展 L2 层.

既然 L2 层的数据帧头要重新定义,那就随便定义啦,是否满足以下三点是笔者从技术角度将一件产是否视为 SDN 的关键因素:

  • 可将 L7 层租户 tenant 的概念做到 L2 层。在笔者的前一篇《漫步云中网络》姊妹篇中已经介绍了 IaaS 云的本质就是卖虚机,即将虚机租给多租户使用后收费。所以位于 L7 应用层的 tenant 的概念是云用来对计算、存储、网络资源进行隔离的重要概念。那么将 tenant 的概念从 L7 层下移到 L2 层中意义重大。
  • 也可将类似 VLAN 的概念做到 L2 层,并且由于是软件定义的(不像物理交换机那样受硬件限制),那么很容易突破 VLAN 号在 1-4094 之间的限制。
  • 是否提供集中式的控制器对外提供北向 API 供第三方调用来动态改变网络拓扑。

清楚了 SDN 的本质,那么 VXLAN 的本质又是什么呢?

  • VXLAN 是一种 L2 层帧头的重新封装的数据格式。
  • VXLAN 仍然使用 GRE 遂道通过 UDP 传输重新封装帧头后的数据帧。

VXLAN 重新定义的 L2 层帧头格式如下图 1 所示,其中 VNI VXLAN ID 与 VLAN 的从概念上等同,但是因为它是用软件实现的,范围可用 24 bits 来表示,这就比 VLAN 的 1-4094 大多了。

图 1. VXLAN 帧头格式
VXLAN 帧头格式

因为 VXLAN 通过重新定义 L2 层帧头(相当于通过 MAC 地址进行 NAT 的方案)从而让两个跨 L3 层的甚至广域网内的两个子网从 L2 层上互通。所以 VXLAN 的优点很多,能让遗留子网不改变 IP 地址的情况下无缝的迁移到云上来;也可以让虚机跨数据中心进行迁移(以前顶多只能在同一个 VLAN 里迁移)。

当然,VXLAN 也不是没有缺点的,通过上面的学习,大家已经知道 VXLAN 也是通过 GRE 走 UDP 来传输重定义的标准化的 VXLAN 封装格式的帧头的。由于在遂道的两端之间直接建立遂道,那么它是无法与途经的一些物理设备(如 DHCP 服务器)通信的,那么就需要 VXLAN 网关这种物理设备在遂道的中途截获 VXLAN 数据包(网关网关嘛,就是进行数据截获再转换的),解析里面的数据,然后做一些事情(像流量统计,DHCP 信息等等),最后再将数据重新打成 VXLAN 数据包交给遂道继续传输。可以想象,在所有需要与物理设备打交道的地方都是需要 VXLAN 网关的。觉得麻烦了吗?

利用 L2 层扩展 L3 层的标签技术 MPLS

VLAN 是一种标签技术,VLAN 一般用在局域网的交换机上,标签很容易在 L2 层通过硬件来实现转发。

MPLS 也是一种标签技术,原理类似于 VLAN,但一般用在 WAN 上的路由器上,下面我们说道说道。

对于 L3 层的传统路由转发来说一般是在路由表里查找相应的路由来实现。因为路由嘛,不同的 CIDR 之间可长可短,如 10.0.0.0/8 与 10.0.100.0/24 这两个子网首先长度不一样,其次 CIDR 号一个是 8,一个是 24,在路由器中,是通过字符串的按最长匹配算法来匹配路由的,那么应该选择 10.0.100.0/24 这个路由。字符串的按最长匹配算法很难通过硬件来实现,通过软件速度慢啊。那么广域网的路由器能不能也引入标签通过硬件转发的优点,在路由器作转发时,不再在 L3 层的通过软件去查找路由来实现转发,而是直接在 L2 层就通过标签通过硬件转发了呢?答案就是 MPLS。

例如 A 路由器通过 B 路由器给 C 路由器发包时,传统的路由器是根据目的地址进行转发,A 在开始转发时,并不知道去 C 的完整路由,它只知道转给 B,B 再决定转给 C,这种走一步看一步的叫基于目的地址的路由转发。但是 MPLS 的原理完全不同,A 在给 C 发包时,先发个 HELLO 包从 A 到 C 走一遍,在走的过程中就已经知道了 A 到 C 的路由路径并且根据 LDP(标签分发协议)将 A 到 C 的标签序列就事先确定好了。那样 A 再给 C 发数据时,A 就提前知道了在 L2 层怎么根据标签来转发,所以它不用再到 L3 层查找路由信息了,另外它在 L2 层通过标签转发可以很容易通过硬件来实现,这样速度更快了,最后标签的确定是通过 LDP 协议动态分配的这也避免了像 VLAN 的那种标签需要手工去设置的麻烦。

SDN

在 VXLAN 一节中,笔者已经说过了笔者判断一个产品是否是 SDN 产品的核心判断因素,即是否将 tenant 租户的概念做到了 L2 层并且提供了北向 API 供第三方应用调用动态调整网络拓扑。做到了,就是 SDN 产品。目前,SDN 产品主要有三类:

  • 基于 Overlay 技术的,如 VMware 的 VxLAN,如 Microsoft 的 NVGRE,如 IBM 的 Dove
  • 基于 OpenFlow 技术的
  • 基于专有技术的,如 Cisco 的 onePK

基于 Overlay 技术的 VxLAN 已经在上面介绍过了,这里着重介绍一下 OpenFlow 和 Dove。

OpenFlow

OpenFlow 是完全不同于传统网络技术的新兴网络技术。

传统交换机能通过自主学习建立转发表,然后根据转发表转发。但对于 OpenFlow 交换机,它是很“笨”的,数据帧来了它并不知道往哪个端口转发,不知道怎么办呢?不懂就问呗,找 OpenFlow 控制器问。控制器通过一定算法告诉它往哪个端口转发,然后 OpenFlow 交换机照着做就行了。下图 2 显示了 OpenFlow 的结构:

图 2. OpenFlow 的结构
OpenFlow 的结构

我并没有将 OpenFlow 归于 L2 层,因为从理论上讲,它并不严格属于 L2 层,因为它设计了 L2-L4 层的转发项进行转发。现在 OpenFlow 的 FIB(转发信息表,Forward Info Base)中至少有下列条目:

  • L2 层的 MAC、VLAN 等
  • L3 层的 source ip, dest ip
  • L4 层的 source port, dest port
  • 甚至有基于 WAN 的动态路由的转发项,如 BGP、MPLS 等

OpenFlow 进行转发的时候和传统的网络技术不一样,传统的是存储包转发(数据到了 L2 层就解析出 MAC 地址进行转发,到了 L3 层后就解析出 IP 地址进行转发)。而 OpenFlow 则根据所谓的流进行转发。它将上面的 MAC、VLAN, source ip, dest ip, source port, dest port 等视作平等的平面,直接通过某个高效的字符串匹配算法匹配到了后再做某些动作,如 accept 或者 drop 掉。

再聊聊笔者所理解的 OpenFlow 的缺点。理论上,如果 OpenFlow 通过 L3 层的 IP 进行转发的话,那它就成了一个路由器了。但实际上,目前,OpenFlow 主要还是用在 L2 层当做一个交换机来使用的。如果真要在 L3 层和路由结合的话,那么它将以怎么样的方式和现存的分布式的动态路由协议(如 RIP、OSPF、BGP、MPLS)协作呢? 并且传统的 WAN 本来为了可靠就是以分布式来设计的,现在搞成 OpenFlow 式的集中式控制,监控什么的是方便了,但一旦控制器挂了那么整个网络也全挂了,并且 OpenFlow 控制器一旦被某方势力所掌握,那么整个 OpenFlow 网络也就全被掌握了,毕竟 WAN 是要考虑这些因素的。所以笔者不认为 OpenFlow 这种集中式控制的路由器能在 WAN 上将取代传统分布式的路由协议,顶多在 LAN 的 L2 层会有一些作为吧。

Dove/OpenDaylight

上面已经说到 SDN 需要对外提供北向 API 供第三方调用。

对于控制器与交换机之间的南向 API 的通讯标准就是由 google, facebook 这些用户主导定制的 OpenFlow 协议。

北向 API 没有标准,南向 API 也五花八门,将 tenant 和 VLAN 的概念做到 SDN 里也没有标准(虽然有 VMware 主导了一个 VXLAN 的数据封装格式),所以业界存在很多 SDN 的产品,Dove 便是由 IBM 实现的其中一种,OpenDaylight 的插件结构可以同时和众多的 SDN 控制器打交道,降低第三方应用同时和众多 SDN 控制器打交道的复杂性。

L3

L3 层的路由分静态路由和动态路由两种:

  • 在 Linux 中,通过打开 ipv4 forward 特性可以让数据包从一块网卡路由到另外一块网卡上。
  • 动态路由,如内部网关协议 RIP,OSPF;如外部网关协议 BGP。能够自动地学习建立路由表。

目前 Neutron 只支持静态路由,要点如下:

  • 对于不同 tenant 子网通过 namespace 功能进行隔离,在 Linux 中,一个命名空间 namespace 您可以简单理解成 linux 又启动了一个新的 TCP/IP 栈的进程。多个 tenant 意味着多个 namespace,也意味着多个 TCP/IP 栈。
  • 对于同一 tenant 中的不同子网的隔离通过 iptables 来做,也意味着,同一 tenant 中的相同子网的两个虚机不用走 L3 层,直接走 L2 层能通,没问题;但如果同一 tenant 中的不同子网的两个虚机要通讯的话,必须得绕道 L3-agent 网络节点,这是影响性能的。

L4-L7

LBaaS

OpenStack 最初的目标是做 x86 平台下的开源 IaaS 云,但它目前也有了类似于 LBaaS (Load Balance as a Service)这样本属于 SaaS 的特性。

LbaaS 服务可以为一个 tenant 下的多台虚机提供负载均衡服务,要点如下:

  • 提供负载均衡的虚机之间组成一个服务组
  • 虚机之间提供心跳检查
  • 外部通过 VIP 来访问 LB 服务组提供的服务,动态地将 VIP 根据负载均衡策略绑定到具体提供服务虚机的 fixed ip 上

 下图 3 显示了 LBaaS 应用的几种情形:

图 3. LBaaS 的应用场景
LBaaS 的应用场景

说明如下:

  • 有两个虚机 192.168.0.3 和 192.168.0.1 组成负载均衡池,它们之间做心跳
  • 如果这个 LB 服务只用在内网,可以只为虚机提供一个内部的 vip,如 192.168.0.4
  • 如果这个 LB 服务也需要从外部访问,那么这个 vip 可以做成 floating ip,如 10.1.1.10

所以实现上述 LB 服务的 neutron 命令如下:

清单 1. 实现例子 LB 服务的 neutron 命令
neurton lb-pool-create --lb-method ROUND_ROBIN --name mypool --protocol HTTP --subnet-id <subnet-id>neurton lb-member-create --address 192.168.0.3 --protocol-port 80 mypoolneurton lb-member-create --address 192.168.0.1 --protocol-port 80 mypoolneurton lb-healthmonitor-create --delay 3 --type HTTP --max-retries 3 --timeout 3neurton lb-healthmonitor-associate <lb-healthomonitor-id> mypoolneurton lb-vip-create --name myvip --protocol-port 80 --protocol HTTP --subnet-id  <subnet-id> mypoolneurton lb-vip-create --name myvip --protocol-port 80 --protocol HTTP --subnet-id  <subnet-id> mypoolneurton floatingip-create publicneurton floatingip-associate <floating-ip-id>  <lb-vip-port-id>

FwaaS

目前,Neutron 已经实现了一个 Security Group 服务,FWaaS 服务正在开发中。 FwaaS 和 Security Group 的原理差不多,只不过代码重构将以前 Security Group 的代码挪到了现有的 L4/L7 层框架来了;这样,以前 Security Group 作为 nova-compute 的一个组件只能运行在计算节点上,单纯拆出来做为一个独立进程之后也可以部署在 l3-agent 的那个物理机上提供边缘防火墙特性。下图 4 显示了 Security Group 服务的原理图:

图 4. Security Group 原理图
Security Group 原理图

Security Group 由一系列的 iptables rule 组成

  • 这些 iptables rule 运行在计算节点上
  • 可以控制从虚机出去的流量
  • 可以控制进来虚机的流量
  • 可以控制虚机之间的流量

实施 Security Group 的步骤如下,例如,四个虚机,可以从 80 端口访问 web 虚机,从 web 虚机上可以访问 database 虚机,ssh 跳转虚机上可以同时访问 database 和 web 虚机,可以通过端口 22 访问 ssh 虚机。

清单2. 实施Security Group 的步骤
neutron security-group-create webneutron security-group-create databaseneutron security-group-create sshneutron security-group-rule-create --direction ingress --protocol TCP \--port-range-min 80 --port-range-max 80 webneutron security-group-rule-create --direction ingress --protocol TCP \--port-range-min 3306 --port-range-max 3306 --remote-group-id web databaseneutron security-group-rule-create --direction ingress --protocol TCP \--port-range-min 22 --port-range-max 22 --remote-group-id ssh databaseneutron security-group-rule-create --direction ingress --protocol TCP \--port-range-min 22 --port-range-max 22 --remote-group-id ssh webneutron security-group-rule-create --direction ingress --protocol tcp \--port-range-min 22 --port-range-max 22 ssh

VPNaaS

我们仍然从技术的本质角度出发来解释什么是 VPN。VPN 类似于 GRE,也是一种遂道。但是不同的是 VPN 也要求不同的用户可以使用相同的子网,所以在每个建立 VPN 的两个端点所对应的边缘路由器上都会为每个用户建立它自己的 VPN 路由实例 VRF,白话一点的话,VRF 就是 Linux 里上面提到过的 namespace 的概念。

建立 GRE 遂道容易,但是 VPN 强调私密性,一个组织的 VPN 总不希望不经授权的访问吧。所以一般使用 SSL 或者 IPSec 结合 GRE 来建立 VPN。也可以通过 MPLS 来建立 VPN。Neutron 中这三类 VPN 目前均在开发之中。从下面 MPLS VPN 的 blueprint 中的图 5 可以看到将来要实现的样子:

图 5. MPLS VPN 实现原理图
MPLS VPN 实现原理图

目前,l3-agent 没有使用动态路由,使用的是 namespace + ipv4 forward + iptables 的静态路由技术。l3-agent 现在充当着 CE 的角色(Custum Edge)。我们设想一下,笔者认为 BGPMpls Driver 将来至少要实现下列几个方面的内容:

  • 调用 PE API 在边缘路由器 PE 上通过 namespace 特性定义并配置 tenant 之间隔离的自己的 VPN 路由实例 VRF
  • tenant 定义的 VRF 路由并不需要在每个 WAN 核心路由上都存在,所以可以通过配置输入和输出策略实现,即使用 router-target import/export 命令导入或导出相应的 VRF 条目
  • 配置 PE 到 CE 的链路
  • 将 CE 的接口关联到预先定义的 VRF

Neutron 有什么?

Neutron 就是一个定义良好的插件框架,用来调用上述 L2-L7 层不同实现,且对外提供北向 API 来提供虚拟网络服务。

它自己提供了 tenant 的概念,它只是一个 SDN 框架,和底层的 SDN 软件如 Dove 集成时可以提供 SDN 的功能,但需要将它的 tenant 和 SDN 自身的 tenant 概念之间做一个映射。

L2

在 L2 层,由虚拟交换机来实现。虚拟交换机有下列这些种:

  • Linux 网桥,基于 Linux 内核的网桥。需要说明的是,网桥就是交换机,是交换机的一种常用的书面叫法。
  • OpenvSwitch(OVS):OVS 有两种模式,一种是当普通的虚拟交换机来使用,另一个是和 OpenFlow 控制器协作当作 OpenFlow 控制器来使用。
  • 一些基于 Overlay 技术的 SDN 实现,如 Dove 等。
  • 一些非开源的商业交换机。

目前,Neutron 已经实现的 L2 层插件如下图 6 所示,linuxbridge 实现了 Linux 网桥,openvswitch 插件实现了 openvswitch 网桥,bigswitch 插件实现了一种 SDN 控制器,ml2 是一种通用的插件(这些 L2 层的插件主要分写数据库的 plugin 部分和运行在计算节点的 agent 部分,plugin 写数据库的字段有差异但不多,所以代码重复,ml2 可以理解为一个公共的 plugin)。且每种插件基本上实现了 FLAT, VLAN, VXLAN, GRE 等四种拓扑。

图 6. Neutron 中 L2 层插件
Neutron 中 L2 层插件

L3

Neutron 的 L3 层由基于 namespace ipv4 forward + iptables 实现。

需要启动 l3-agent 进程,如果需要 DHCP 服务的话也需要启动 dhcp-agent 进程。

L4-L7

LBaaS 基于 Haproxy 实现;FWaaS 基于 iptables 实现;VPNaaS 有基于 IPSec 的 VPN 实现,也有基于 MPLS 的 VPN 实现,也有基于 SSL 的 VPN 实现。

截止到笔者写此文为止,目前只有 LBaaS 能用,其他的 FWaaS, VPNaaS 和 NATaaS 仍在开发中。但对于 FWaaS 有 Security Group 功能可用,区别在于前者由于作为独立服务也能部署在网络节点上提供边缘防火墙特性,后者依然能够在计算节点上使用 iptables 规则控制从虚机出去的,进来虚机的,虚机之间的流量。


0 0
原创粉丝点击