深刻理解openstack網絡架構(2)----Basic Use Cases

原文地址: https://blogs.oracle.com/ronen/entry/diving_into_openstack_network_architecture1
html

在上一篇文章中,咱們瞭解了幾個網絡組件,如openvswitch/network namespace/Linux bridges/veth pairs。這篇文章中,咱們將用3個簡單的use case,展現這些基本網絡組件如何以工做從而實現openstack的SDN方案。
在這些use case中,咱們會了解整個網絡配置和他們如何一塊兒運行。use case以下: git

  1. 建立網絡——咱們建立網絡時,發生了什麼。如何建立多個隔離的網絡。
  2. 建立虛擬機——一旦咱們有了網絡,咱們能夠建立虛擬機並將其接入網絡。
  3. 虛擬機的DHCP請求——opensack能夠自動爲虛擬機配置IP。經過openstack neutron控制的DHCP服務完成。咱們來了解這個服務如何運行,DHCP請求和迴應是什麼樣子的?

這篇文章中,咱們會展現網絡鏈接的原理,咱們會了解網絡包如何從A到B。咱們先了解已經完成的網絡配置是什麼樣子的?而後咱們討論這些網絡配置是如何以及什麼時候建立的?我我的認爲,經過例子和具體實踐看到真實的網絡接口如何工做以及如何將他們鏈接起來是很是有價值的。而後,一切真相大白,咱們知道網絡鏈接如何工做,在後邊的文章中,我將進一步解釋neutron如何配置這些組件,從而提供這樣的網絡鏈接能力。github

我推薦在你本身的環境上嘗試這些例子或者使用Oracle Openstack Tech Preview。徹底理解這些網絡場景,對咱們調查openstack環境中的網絡問題很是有幫助。 安全

Use case #1: Create Network

建立network的操做很是簡單。咱們可使用GUI或者命令行完成。openstack的網絡僅供建立該網絡的租戶使用。固然若是這個網絡是「shared」,它也能夠被其餘全部租戶使用。一個網絡能夠有多個subnets,可是爲了演示目的和簡單,咱們僅爲每個network建立一個subnet。經過命令行建立network: 
cookie

# neutron net-create net1

Created a new network:

+---------------------------+--------------------------------------+

| Field                     | Value                                |

+---------------------------+--------------------------------------+

| admin_state_up            | True                                 |

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

| name                      | net1                                 |

| provider:network_type     | vlan                                 |

| provider:physical_network | default                              |

| provider:segmentation_id  | 1000                                 |

| shared                    | False                                |

| status                    | ACTIVE                               |

| subnets                   |                                      |

| tenant_id                 | 9796e5145ee546508939cd49ad59d51f     |

+---------------------------+--------------------------------------+

爲這個network建立subnet::

# neutron subnet-create net1 10.10.10.0/24

Created a new subnet:

+------------------+------------------------------------------------+

| Field            | Value                                          |

+------------------+------------------------------------------------+

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

| cidr             | 10.10.10.0/24                                  |

| dns_nameservers  |                                                |

| enable_dhcp      | True                                           |

| gateway_ip       | 10.10.10.1                                     |

| host_routes      |                                                |

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

| ip_version       | 4                                              |

| name             |                                                |

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

| tenant_id        | 9796e5145ee546508939cd49ad59d51f               |

+------------------+------------------------------------------------+



如今咱們有了一個network和subnet,網絡拓撲像這樣:網絡


horizon_network

如今讓咱們深刻看下到底發生了什麼?在控制節點,咱們一個新的namespace被建立: 
oracle

# ip netns list

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


這個namespace的名字是qdhcp- (參見上邊),讓咱們深刻namespace中看看有什麼?
dom

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

1: lo:  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

    inet6 ::1/128 scope host

       valid_lft forever preferred_lft forever

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

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

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

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

       valid_lft forever preferred_lft forever


咱們發下在namespace下有兩個網絡接口,一個是loop設備,另外一個叫「tap26c9b807-7c」。這個接口設置了IP地址10.10.10.3,他會接收dhcp請求(後邊會講)。接下來咱們來跟蹤下「tap26c9b807-7c」的網絡鏈接性。咱們從OVS上看下這個接口所鏈接的OVS網橋"br-int"。tcp

# ovs-vsctl show
8a069c7c-ea05-4375-93e2-b9fc9e4b3ca1
    Bridge "br-eth2"
        Port "br-eth2"
            Interface "br-eth2"
                type: internal
        Port "eth2"
            Interface "eth2"
        Port "phy-br-eth2"
            Interface "phy-br-eth2"
    Bridge br-ex
        Port br-ex
            Interface br-ex
                type: internal
    Bridge br-int
        Port "int-br-eth2"
            Interface "int-br-eth2"
        Port "tap26c9b807-7c"
            tag: 1
            Interface "tap26c9b807-7c"
                type: internal
        Port br-int
            Interface br-int
                type: internal
    ovs_version: "1.11.0"

由上可知,veth pair的兩端「int-br-eth2」 和 "phy-br-eth2",這個veth pari鏈接兩個OVS網橋"br-eth2"和"br-int"。上一篇文章中,咱們解釋過如何經過ethtool命令查看veth pairs的兩端。就以下邊的例子:
ide

# ethtool -S int-br-eth2
NIC statistics:
     peer_ifindex: 10
.
.
 
#ip link
.
.
10: phy-br-eth2:  mtu 1500 qdisc pfifo_fast state UP qlen 1000
.
.

注意「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標籤的修改:

#  ovs-ofctl dump-flows br-eth2
NXST_FLOW reply (xid=0x4):
 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
 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
 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標籤的修改以下:

#  ovs-ofctl dump-flows br-int
NXST_FLOW reply (xid=0x4):
 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
 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
 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標籤的修改。如今,讓咱們看下建立虛擬機時,發生了什麼?虛擬機是怎麼鏈接到虛擬機網絡的?

Use case #2: Launch a VM

從Horizon或者命令行建立並啓動一個虛擬機,下圖是從Horzion建立的例子:

launch-instance


掛載網絡並啓動虛擬機:

attach-network
一旦虛擬機啓動並運行,咱們發下nova支持給虛擬機綁定IP:

# nova list
+--------------------------------------+--------------+--------+------------+-------------+-----------------+
| ID                                   | Name         | Status | Task State | Power State | Networks        |
+--------------------------------------+--------------+--------+------------+-------------+-----------------+
| 3707ac87-4f5d-4349-b7ed-3a673f55e5e1 | Oracle Linux | ACTIVE | None       | Running     | net1=10.10.10.2 |
+--------------------------------------+--------------+--------+------------+-------------+-----------------+

nova list命令顯示虛擬機在運行中,並被分配了IP 10.10.10.2。咱們經過虛擬機定義文件,查看下虛擬機與虛擬機網絡之間的鏈接性。虛擬機的配置文件在目錄/var/lib/nova/instances//下能夠找到。經過查看虛擬機定義文件,libvirt.xml,咱們能夠看到虛擬機鏈接到網絡接口「tap53903a95-82」,這個網絡接口鏈接到了Linux網橋 「qbr53903a95-82」:

<interface type="bridge">
      <mac address="fa:16:3e:fe:c7:87"/>
      <source bridge="qbr53903a95-82"/>
      <target dev="tap53903a95-82"/>
    </interface>

經過brctl查看網橋信息以下:

# brctl show
bridge name     bridge id               STP enabled     interfaces
qbr53903a95-82          8000.7e7f3282b836       no              qvb53903a95-82
                                                        tap53903a95-82

網橋有兩個網絡接口,一個鏈接到虛擬機(「tap53903a95-82 「),另外一個( 「qvb53903a95-82」)鏈接到OVS網橋」br-int"。

# ovs-vsctl show
83c42f80-77e9-46c8-8560-7697d76de51c
    Bridge "br-eth2"
        Port "br-eth2"
            Interface "br-eth2"
                type: internal
        Port "eth2"
            Interface "eth2"
        Port "phy-br-eth2"
            Interface "phy-br-eth2"
    Bridge br-int
        Port br-int
            Interface br-int
                type: internal
        Port "int-br-eth2"
            Interface "int-br-eth2"
        Port "qvb53903a95-82"
            tag: 3
            Interface "qvb53903a95-82"
    ovs_version: "1.11.0"

咱們以前看過,OVS網橋「br-int"鏈接到"br-eth2",經過veth pair(int-br-eth2,phy-br-eth2 ),br-eth2鏈接到物理網卡eth2。整個流入以下:

VM  ->  tap53903a95-82 (virtual interface)  ->  qbr53903a95-82 (Linux bridge)  ->  qvb53903a95-82 (interface connected from Linux bridge to OVS bridge br-int)  ->  int-br-eth2 (veth one end)  ->  phy-br-eth2 (veth the other end)  ->  eth2 physical interface.

與虛擬機相連的Linux bridage主要用於基於Iptables的安全組設置。安全組用於對虛擬機的網絡隔離進行加強,因爲iptables不能用於OVS網橋,所以咱們使用了Linux網橋。後邊咱們會看到Linux網橋的規則設置。

VLAN tags:咱們在第一個use case中提到過,net1使用VLAN標籤1000,經過OVS咱們看到qvo41f1ebcf-7c使用VLAN標籤3。VLAN標籤從3到1000的轉換在OVS中完成,經過br-eth2中實現。 總結以下,虛擬機經過一組網絡設備連入虛擬機網絡。虛擬機和網絡之間,VLAN標籤被修改。

Use case #3: Serving a DHCP request coming from the virtual machine

以前的use case中,咱們看到了一個叫dhcp-的namespace和虛擬機,二者最終鏈接到物理網絡eth2。他們都會被打上VLAN標籤1000。咱們看到該namespace中的網絡接口使用IP 10.10.10.3。由於虛擬機和namespace彼此鏈接並在相同子網,所以能夠ping到對方。以下圖,虛擬機中網絡接口被分配了IP 10.10.10.2,咱們嘗試ping namespace中的網絡接口的IP:
vm-console

namespace與虛擬機之間連通,而且能夠互相ping通,對於定位問題很是有用。咱們能夠從虛擬機ping通namespace,可使用tcpdump或其餘工具定位網絡中斷問題。

爲了響應虛擬機的dhcp請求,Neutron使用了」dnsmasq「的Linux工具,這個工具是一個輕量的DNS、DHCP服務,更多的信息請查看(http://www.thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html)。咱們能夠在控制節點經過PS命令看到:

dnsmasq --no-hosts --no-resolv --strict-order --bind-interfaces --interface=tap26c9b807-7c --except-interface=lo --pid-file=/var/lib/neutron/dhcp/5f833617-6179-4797-b7c0-7d420d84040c/pid --dhcp-hostsfile=/var/lib/neutron/dhcp/5f833617-6179-4797-b7c0-7d420d84040c/host --dhcp-optsfile=/var/lib/neutron/dhcp/5f833617-6179-4797-b7c0-7d420d84040c/opts --leasefile-ro --dhcp-range=tag0,10.10.10.0,static,120s --dhcp-lease-max=256 --conf-file= --domain=openstacklocal


DHCP服務在namespace中鏈接到了一個tap接口(「--interface=tap26c9b807-7c」),從hosts文件咱們能夠看到:

# cat  /var/lib/neutron/dhcp/5f833617-6179-4797-b7c0-7d420d84040c/host
fa:16:3e:fe:c7:87,host-10-10-10-2.openstacklocal,10.10.10.2

以前的console輸出能夠看到虛擬機MAC爲fa:16:3e:fe:c7:87 。這個mac地址與IP 10.10.10.2 關聯,當包含該MAC的DHCP請求到達,dnsmasq返回10.10.10.2。在這個初始過程(能夠重啓網絡服務觸發)中從namespace中看,能夠看到以下的DHCP請求:

# ip netns exec qdhcp-5f833617-6179-4797-b7c0-7d420d84040c tcpdump -n
19:27:12.191280 IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from fa:16:3e:fe:c7:87, length 310
19:27:12.191666 IP 10.10.10.3.bootps > 10.10.10.2.bootpc: BOOTP/DHCP, Reply, length 325

總之,DHCP服務由dnsmasq提供,這個服務由Neutron配置,監聽在DHCP namespace中的網絡接口上。Neutron還配置dnsmasq中的MAC/IP映射關係,因此當DHCP請求時會受到分配給它的IP。

總結

本文,咱們基於以前講解的各類網絡組件,分析了三種use case下網絡如何連通的。這些use cases對了解整個網絡棧以及瞭解虛擬機/計算節點/DHCP namespace直接如何連通頗有幫助。根據咱們的分析,咱們確信啓動虛擬機、虛擬機發出DHCP請求、虛擬機收到正確的IP後這個網絡按照咱們預想的工做。咱們看到一個包通過一長串路徑最終到達目的地,若是這一切成功,意味着這些組件功能正常。下一篇文章中,咱們會學習更復雜的neutron服務並分析他們如何工做。

相關文章
相關標籤/搜索