深入理解Openstack
2016-12-09 阅读 6225


在这篇文章中,我们将用1个简单的use case,展示基本网络组件如何以工作从而实现openstack的SDN方案。

在这些use case中,我们会了解整个网络配置和他们如何一起运行。use case如下:

  1. 创建网络——我们创建网络时,发生了什么。如何创建多个隔离的网络。

  2. 创建虚拟机——一旦我们有了网络,我们可以创建虚拟机并将其接入网络。

  3. 虚拟机的DHCP请求——opensack可以自动为虚拟机配置IP。通过openstack neutron控制的DHCP服务完成。我们来了解这个服务如何运行,DHCP请求和回应是什么样子的?

这篇文章中,我们会展示网络连接的原理,我们会了解网络包如何从A到B。我们先了解已经完成的网络配置是什么样子的?然后我们讨论这些网络配置是如 何以及何时创建的?

Use case #1: Create Network

创建network的操作非常简单。我们可以使用GUI或者命令行完成。openstack的网络仅供创建该网络的租户使用。当然如果这个网络是 “shared”,它也可以被其他所有租户使用。一个网络可以有多个subnets,但是为了演示目的和简单,我们仅为每一个network创建一个 subnet。通过命令行创建network:

1.  # neutron net-create net1 

2.   

3.  Created a new network: 

4.   

5.  +---------------------------+--------------------------------------+ 

6.   

7.  | Field                     | Value                                | 

8.   

9.  +---------------------------+--------------------------------------+ 

10. 

11.| admin_state_up            | True                                 | 

12. 

13.| id                        | 5f833617-6179-4797-b7c0-7d420d84040c | 

14. 

15.| name                      | net1                                 | 

16. 

17.| provider:network_type     | vlan                                 | 

18. 

19.| provider:physical_network | default                              | 

20. 

21.| provider:segmentation_id  | 1000                                 | 

22. 

23.| shared                    | False                                | 

24. 

25.| status                    | ACTIVE                               | 

26. 

27.| subnets                   |                                      | 

28. 

29.| tenant_id                 | 9796e5145ee546508939cd49ad59d51f     | 

30. 

31.+---------------------------+--------------------------------------+ 

为这个network创建subnet::

1.  # neutron subnet-create net1 10.10.10.0/24 

2.   

3.  Created a new subnet: 

4.   

5.  +------------------+------------------------------------------------+ 

6.   

7.  | Field            | Value                                          | 

8.   

9.  +------------------+------------------------------------------------+ 

10. 

11.| allocation_pools | {"start": "10.10.10.2", "end": "10.10.10.254"} | 

12. 

13.| cidr             | 10.10.10.0/24                                  | 

14. 

15.| dns_nameservers  |                                                | 

16. 

17.| enable_dhcp      | True                                           | 

18. 

19.| gateway_ip       | 10.10.10.1                                     | 

20. 

21.| host_routes      |                                                | 

22. 

23.| id               | 2d7a0a58-0674-439a-ad23-d6471aaae9bc           | 

24. 

25.| ip_version       | 4                                              | 

26. 

27.| name             |                                                | 

28. 

29.| network_id       | 5f833617-6179-4797-b7c0-7d420d84040c           | 

30. 

31.| tenant_id        | 9796e5145ee546508939cd49ad59d51f               | 

32. 

33.+------------------+------------------------------------------------+ 

现在我们有了一个network和subnet,网络拓扑像这样:

现在让我们深入看下到底发生了什么?在控制节点,我们一个新的namespace被创建: 

1.  # ip netns list 

2.   

3.  qdhcp-5f833617-6179-4797-b7c0-7d420d84040c 

这个namespace的名字是qdhcp- (参见上边),让我们深入namespace中看看有什么?

1.  # ip netns exec qdhcp-5f833617-6179-4797-b7c0-7d420d84040c ip addr 

2.   

3.  1: lo:  mtu 65536 qdisc noqueue state UNKNOWN 

4.   

5.      link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 

6.   

7.      inet 127.0.0.1/8 scope host lo 

8.   

9.      inet6 ::1/128 scope host 

10. 

11.       valid_lft forever preferred_lft forever 

12. 

13.12: tap26c9b807-7c:  mtu 1500 qdisc noqueue state UNKNOWN 

14. 

15.    link/ether fa:16:3e:1d:5c:81 brd ff:ff:ff:ff:ff:ff 

16. 

17.    inet 10.10.10.3/24 brd 10.10.10.255 scope global tap26c9b807-7c 

18. 

19.    inet6 fe80::f816:3eff:fe1d:5c81/64 scope link 

20. 

21.       valid_lft forever preferred_lft forever 

我们发下在namespace下有两个网络接口,一个是loop设备,另一个叫“tap26c9b807-7c”。这个接口设置了IP地址 10.10.10.3,他会接收dhcp请求(后边会讲)。接下来我们来跟踪下“tap26c9b807-7c”的网络连接性。我们从OVS上看下这个接 口所连接的OVS网桥"br-int"。

1.  # ovs-vsctl show 

2.  8a069c7c-ea05-4375-93e2-b9fc9e4b3ca1 

3.      Bridge "br-eth2" 

4.          Port "br-eth2" 

5.              Interface "br-eth2" 

6.                  type: internal 

7.          Port "eth2" 

8.              Interface "eth2" 

9.          Port "phy-br-eth2" 

10.            Interface "phy-br-eth2" 

11.    Bridge br-ex 

12.        Port br-ex 

13.            Interface br-ex 

14.                type: internal 

15.    Bridge br-int 

16.        Port "int-br-eth2" 

17.            Interface "int-br-eth2" 

18.        Port "tap26c9b807-7c" 

19.            tag: 1 

20.            Interface "tap26c9b807-7c" 

21.                type: internal 

22.        Port br-int 

23.            Interface br-int 

24.                type: internal 

25.    ovs_version: "1.11.0" 

由上可知,veth pair的两端“int-br-eth2” 和 "phy-br-eth2",这个veth pari连接两个OVS网桥"br-eth2"和"br-int"。上一篇文章中,我们解释过如何通过ethtool命令查看veth pairs的两端。就如下边的例子:

1.  # ethtool -S int-br-eth2 

2.  NIC statistics: 

3.       peer_ifindex: 10 

4. 

5. 

6.    

7.  #ip link 

8. 

9. 

10.10: phy-br-eth2:  mtu 1500 qdisc pfifo_fast state UP qlen 1000 

11.. 

12.. 

注意“phy-br-eth2”连接到网桥"br-eth2",这个网桥的一个网口是物理网卡eth2。这意味着我们创建的网络创建了一个连接到了物理网卡eth2的namespace。eth2所在的虚拟机网络会连接所有的虚拟机的。

关于网络隔离:

Openstack支持创建多个隔离的网络,也可以使用多种机制完成网络间的彼此隔离。这些隔离机制包括 VLANs/VxLANs/GRE tunnels,这个在我们部署openstack环境时配置。本文中我们选择了VLANs。当使用VLAN标签作为隔离机制,Neutron会从预定义 好的VLAN池中选择一个VLAN标签,并分配给一个新创建的network。通过分配VLAN标签给network,Neutron允许在一个物理网卡 上创建多个隔离的网络。与其他的平台的最大的区别是,用户不需要负责管理VLAN如何分配给networks。Neutron会负责管理分配VLAN标 签,并负责回收。在我们的例子中,net1使用VLAN标签1000,这意味着连接到该网络的虚拟机,发出的包会被打上VLAN标签1000然后发送到物 理网络中。对namespace也是同样的,如果我们希望namespace连接到某个特定网络,我们需要确保这个namespace发出的/接收的包被 正确的打上了标签。

在上边的例子中,namespace中的网络接口“tap26c9b807-7c”被分配了VLAN标签1。如果我们从 OVS观察下,会发现VLAN1会被改为VLAN1000,当包进入eth2所在的uxniji网络。反之亦然。我们通过OVS的dump-flows命 令可以看到进入虚拟机网络的网络包在br-eth2上进行了VLAN标签的修改:

1.  #  ovs-ofctl dump-flows br-eth2 

2.  NXST_FLOW reply (xid=0x4): 

3.   cookie=0x0, duration=18669.401s, table=0, n_packets=857, n_bytes=163350, idle_age=25, priority=4,in_port=2,dl_vlan=1 actions=mod_vlan_vid:1000,NORMAL 

4.   cookie=0x0, duration=165108.226s, table=0, n_packets=14, n_bytes=1000, idle_age=5343, hard_age=65534, priority=2,in_port=2 actions=-- DROP  

5.   cookie=0x0, duration=165109.813s, table=0, n_packets=1671, n_bytes=213304, idle_age=25, hard_age=65534, priority=1 actions=NORMAL 

从网络接口到namespace我们看到VLAN标签的修改如下:

1.  #  ovs-ofctl dump-flows br-int 

2.  NXST_FLOW reply (xid=0x4): 

3.   cookie=0x0, duration=18690.876s, table=0, n_packets=1610, n_bytes=210752, idle_age=1, priority=3,in_port=1,dl_vlan=1000 actions=mod_vlan_vid:1,NORMAL 

4.   cookie=0x0, duration=165130.01s, table=0, n_packets=75, n_bytes=3686, idle_age=4212, hard_age=65534, priority=2,in_port=1 actions=-- DROP  

5.   cookie=0x0, duration=165131.96s, table=0, n_packets=863, n_bytes=160727, idle_age=1, hard_age=65534, priority=1 actions=NORMAL 

总之,当用户创建network,neutrong会创建一个namespace,这个namespace通过OVS连接到虚拟机网络。OVS还负 责namespace与虚拟机网络之间VLAN标签的修改。