漫步云中網(wǎng)絡(luò)
閱讀本文前,最好能先了解以下的知識:
了解 OpenStack 將有助于對本文的理解。本文講解的是 Linux 虛擬網(wǎng)絡(luò)中的一般原理方法 , 雖不僅限于應(yīng)用在 OpenStack 之中 , 但本文的實驗是以 OpenStack 為基礎(chǔ)的。OpenStack 是一個開源的 IaaS 云 , 您可以從 devstack 腳本 ( http://devstack.org/) 開始熟悉它。
了解 QEMU 也將有助于對本文的理解。QEMU 是一種支持多種 CPU 的機器模擬器 , 本文采用 QEMU 來創(chuàng)建虛擬機驗證本文中的試驗。
什么是云?
什么是云?我的理解是,為多租戶提供各層次上的服務(wù)(如操作系統(tǒng)層、中間件層、應(yīng)用軟件層等)的可動態(tài)水平擴展的服務(wù)器集群稱之為云。所以云具有大規(guī)模、高可擴展性、按需服務(wù)、自動化、節(jié)能環(huán)保、高可靠性等特點。下圖1從軟件堆棧視角勾畫了云的架構(gòu):
圖 1. 云的架構(gòu)

- IaaS, Infrastructure as a Service,基礎(chǔ)設(shè)施即服務(wù):您可以簡單理解為將可伸縮的操作系統(tǒng)(虛機或?qū)崣C)實例作為基礎(chǔ)設(shè)施服務(wù)賣給多租戶,然后按需計算費用。當然,將操作系統(tǒng)作為基礎(chǔ)設(shè)施服務(wù)只是 IaaS 中的一種,且是最主要的一種,我怕大家概念混淆所以就只重點提了這種。實際上,只要是基礎(chǔ)設(shè)施提供服務(wù)了從概念上講都應(yīng)該叫 IaaS,比如說關(guān)系型數(shù)據(jù)庫,如果是集群部署的話,它也是基礎(chǔ)設(shè)施提供服務(wù)了,也應(yīng)該叫 IaaS。這類產(chǎn)品如 IBM 的 Smart Cloud Entry,如開源的 OpenStack。
 - PaaS, Platform as a Service, 平臺即服務(wù):您可以簡單理解為將可伸縮的中間件資源作為平臺服務(wù)賣給多租戶,然后按需計算費用。舉個例子,如果 SaaS 應(yīng)用程序的并發(fā)瞬間加大的話,PaaS 可以自動實時地啟動一個由 IaaS 提供的操作系統(tǒng)實例,然后自動在它上面部署中間件應(yīng)用服務(wù)器(如 IBM 的 WebSphere),最后再部署一套該 SaaS 應(yīng)用實例,并自動將它們納入到負載均衡體系之中,從而實現(xiàn)平臺服務(wù)的自動伸縮,這就是 PaaS。這類產(chǎn)品如 IBM 的 IWD,如 Google 的 App Engine。
 - SaaS, Software as a Service, 軟件即服務(wù):您可以簡單理解為可伸縮的分布式軟件作為軟件服務(wù)為用戶提供某種在線服務(wù),如視頻服務(wù),地圖服務(wù)等。
 - XaaS, X as a Server, 一切即服務(wù):只要是給多租戶按需提供服務(wù)都可以叫 XaaS, 像在 OpenStack 中,將網(wǎng)絡(luò)部分代碼單獨抽出來組成 Quantum 工程,就可以叫網(wǎng)絡(luò)即服務(wù)(NaaS, Network as a Service);像使用 xCat 自動部署裸機可以叫裸機即服務(wù)(MaaS, Bare-metal as a Service)。#p#
 
什么是云中網(wǎng)絡(luò)?
在傳統(tǒng)的數(shù)據(jù)中心中,每個網(wǎng)口對應(yīng)唯一一個物理機;有了云,一臺物理網(wǎng)卡可能會承載多個虛擬網(wǎng)卡。物理網(wǎng)卡與虛擬網(wǎng)卡之間的關(guān)系無外乎就是下列三種情況:
一對一,一個物理網(wǎng)卡對應(yīng)對一個虛擬網(wǎng)卡,是下面一對多情況的一種特例
一對多,一個物理網(wǎng)卡對應(yīng)多個虛擬網(wǎng)卡,是本文要介紹的情況
多對一,多個物理網(wǎng)對應(yīng)一個虛擬網(wǎng)卡,即我們常說的 Bonding,用作負載均衡
圖 2. 虛擬網(wǎng)絡(luò)的主要內(nèi)容

上圖 2 顯示了虛擬網(wǎng)絡(luò)的主要內(nèi)容:
目前,對網(wǎng)絡(luò)的虛擬化主要集中在第 2 層和第 3 層
在 Linux 中,第 2 層通常使用 TAP 設(shè)備來實現(xiàn)虛擬網(wǎng)卡,使用 Linux Bridge 來實現(xiàn)虛擬交換機
在 Linux 中,第 3 層通常是基于 Iptable 的 NAT,路由及轉(zhuǎn)發(fā)
對于網(wǎng)絡(luò)隔離,可以采用傳統(tǒng)的基于 802.1Q 協(xié)議的 VLAN 技術(shù),但這受限于 VLAN ID 大小范圍的限制,并且需要手動地在各物理交換機上配置 VLAN;也可以采用虛擬交換機軟件,如 Openvswitch,它可以自動創(chuàng)建 GRE 隧道來避免手動去為物理交換機配置 VLAN。
下面將結(jié)合一個生產(chǎn)環(huán)境中的網(wǎng)絡(luò)實例來講解如何實現(xiàn)一個虛擬網(wǎng)絡(luò)。#p#
云中網(wǎng)絡(luò)實驗
在生產(chǎn)環(huán)境中,按通用做法一般將云中網(wǎng)絡(luò)劃分為三大部分,公共網(wǎng)絡(luò)、管理&存儲網(wǎng)絡(luò)、服務(wù)網(wǎng)絡(luò)。
公共網(wǎng)絡(luò):用于云向外部租戶提供 API 調(diào)用或者訪問
管理網(wǎng)絡(luò):用于云中各物理機之間的通信
存儲網(wǎng)絡(luò):用于 iSCSI 服務(wù)端與客戶端之間的流量,一般與管理網(wǎng)絡(luò)同
服務(wù)網(wǎng)絡(luò):虛機內(nèi)部使用的網(wǎng)絡(luò)
為了將上述網(wǎng)絡(luò)的實現(xiàn)原理講清楚,我們選擇了兩臺物理機做實驗,并將采用 NAT、Linux Bridge、VLAN 技術(shù)分步實現(xiàn)一個典型的 OpenStack 云的網(wǎng)絡(luò)拓撲。當然,這種網(wǎng)絡(luò)的原理是通用的,并不僅限于 OpenStack 云。
臺式機 (node1), 雙有線網(wǎng)卡, 將作為控制節(jié)點、存儲節(jié)點及一個計算節(jié)點
筆記本 (node2),一有線網(wǎng)卡,將作為一個計算節(jié)點
路由器,家中 ADSL 寬帶出口
交換機 , 用于連接各物理機
值得一提的是,如果采用了 VLAN 技術(shù)進行網(wǎng)絡(luò)隔離,且想要兩臺物理機上的虛機能夠互訪的話,交換機必須是支持 VLAN 的,且需要手動將交換機相應(yīng)的端口配置成 Trunk 模式。因為我沒有支持 VLAN 的物理交換機,在本實驗中,我是采用直連線直接連接兩臺實驗機器的。
下圖 3 顯示了實驗網(wǎng)絡(luò)拓撲:
圖 3. OpenStack 實驗網(wǎng)絡(luò)拓撲
  
公共網(wǎng)絡(luò):192.168.99.0/24 網(wǎng)段,外網(wǎng)用戶通過公共網(wǎng)絡(luò)上提供的服務(wù)來訪問云。注意:在實際的生產(chǎn)環(huán)境中,公共網(wǎng)絡(luò)一般采用外網(wǎng) IP,因為我沒有外網(wǎng) IP,所以用 192.168.99.0 網(wǎng)段模擬。將臺式機的一有線網(wǎng)卡 eth1 與 TP-Link 路由器相連即可。
管理&存儲網(wǎng)絡(luò):172.16.99.0/24 網(wǎng)段,管理網(wǎng)絡(luò)用于 OpenStack 各組件以及 DB、MQ 之間進行通信;存儲網(wǎng)絡(luò)用于存儲節(jié)點和需要使用外部存儲的計算節(jié)點之間的通信。將臺式機的另一有線網(wǎng)卡 eth0 和筆記本電腦的有線網(wǎng)卡 eth0 連接到交換機即可。
服務(wù)網(wǎng)絡(luò):10.0.0.0/8 網(wǎng)段,用于虛機內(nèi)部。
兩個節(jié)點的基本網(wǎng)絡(luò)配置如下:
清單 1. node1 的基本網(wǎng)絡(luò)配置
- root@node1:/home/hua# cat /etc/network/interfaces
 - auto lo
 - iface lo inet loopback
 - auto eth1
 - iface eth1 inet dhcp
 - up iptables -t nat -A POSTROUTING -s 172.16.99.0/24 -o eth1 -j MASQUERADE
 - auto eth0
 - iface eth0 inet static
 - address 172.16.99.108
 - netmask 255.255.255.0
 - network 172.16.99.0
 - broadcast 172.16.99.255
 
清單 2. node2 的基本網(wǎng)絡(luò)配置
cat /etc/sysconfig/network-scripts/ifcfg-eth0
- DEVICE=eth0
 - HWADDR=00:21:86:94:63:27
 - ONBOOT=yes
 - BOOTPROTO=static
 - USERCTL=yes
 - PEERDNS=yes
 - IPV6INIT=no
 - NM_CONTROLLED=yes
 - TYPE=Ethernet
 - NETMASK=255.255.255.0
 - IPADDR=172.16.99.109
 - NETWORK=172.16.99.0
 - GATEWAY=172.16.99.108
 - DNS1=202.106.195.68
 - DNS2=202.106.46.151
 
我雖然只用了兩臺物理機來模擬實際生產(chǎn)環(huán)境的部署模型, 但文中的這種部署結(jié)構(gòu)是典型的,如果是大規(guī)模部署的話,只需要將控制節(jié)點上的每一個進程(如 DB、MQ、glance、keystone、nova-api、nova-schedule、nova-network 等)分布部署在每一臺物理機即可。想要進一步的 HA 的話,可以:
- 將 DB 配置成集群模式
 - 將 MQ 配置成集群模式
 - 采用 multi-host 模式,將 nova-network 同時安裝在計算節(jié)點 (nova-compute) 上
 - 將 nova-api、nova-schedule 這些無狀態(tài)的服務(wù)也同時部署在計算節(jié)點上,再加上負載均衡器分發(fā)負載
 - 采用多網(wǎng)卡做 Bonding
 
NAT
node2 可以通過 NAT 方式訪問外網(wǎng),數(shù)據(jù)流向如下:
1、node2 中需設(shè)置網(wǎng)關(guān)指向 node1 的 eth0,例:
- GATEWAY=172.16.99.108
 
2、在 node1 中打開 ipv4 轉(zhuǎn)發(fā)功能,這樣,node1 會相當于一臺路由器,在 eth0 收到來自 node2 的數(shù)據(jù)之后,會將數(shù)據(jù)包轉(zhuǎn)發(fā)到其他網(wǎng)卡 eth1,
- sysctl -w net.ipv4.ip_forward=1
 
3、在 node1 上設(shè)置 NAT 規(guī)則,這樣,從 node2(172.16.99.0/24 網(wǎng)段)發(fā)出的數(shù)據(jù)包看來起就像從 node1 的 eth1 發(fā)出的一樣:
- iptables -t nat -A POSTROUTING -s 172.16.99.0/24 -o eth1 -j MASQUERADE
 
Linux Bridge
網(wǎng)橋 ( Bridge ) 工作在二層,了解鏈路層協(xié)議,按幀轉(zhuǎn)發(fā)數(shù)據(jù)。就是交我們常說的交換機,所以連接到網(wǎng)橋的設(shè)備處于同一網(wǎng)段。
圖 4. 網(wǎng)橋示例

上圖 4 顯示了 node1 網(wǎng)橋中的 VM1 與 node2 網(wǎng)橋中的 VM2 是如何通信的。在 openstack 中,這是典型的 multi-host 模式,即每一個計算節(jié)點均部署了網(wǎng)絡(luò)服務(wù)來提供網(wǎng)關(guān)服務(wù)。Linux Bridge 充當了交換機的功能,而將 sysctl -w net.ipv4.ip_forward 設(shè)置為 1 也相當于 node1 同時充當了一個路由器(路由器的實質(zhì)就是一個具有多個網(wǎng)卡的機器,因為它的多網(wǎng)卡同時具有這些不同網(wǎng)段的 IP 地址,所以它能將一個網(wǎng)絡(luò)的流量路由轉(zhuǎn)發(fā)到另一個網(wǎng)絡(luò))。
網(wǎng)橋,交換機,是用來連接兩個 LAN 的。 是根據(jù) MAC 與端口的映射進行轉(zhuǎn)發(fā)的,而在虛機的網(wǎng)卡都是知道的,若從轉(zhuǎn)發(fā)數(shù)據(jù)庫知道目的 MAC 地址,以太網(wǎng)幀就只會正確的網(wǎng)橋端口傳輸,否則,就會擴散到網(wǎng)橋設(shè)備的所有端口。
因為網(wǎng)橋工作在第二層,所以 eth0.1, tap0, tap1 這些網(wǎng)卡均不需要設(shè)置 IP(因為對于上層路由器來說,它們是同一個子網(wǎng),只需要將 IP 設(shè)置在 br1 上即可)。同時, 對 Linux 而言,網(wǎng)橋是虛擬設(shè)備,因此,除非將一個或多個真實設(shè)備綁定到網(wǎng)橋設(shè)備上,否則它就無法接收或傳輸任何東西。所以需要將一個真實設(shè)備(如 eth0)或者真實設(shè)備的 vlan 接口(如 eth0.1) 加入到網(wǎng)橋。對于前一種情況,將 eth0 加入到網(wǎng)橋之后,eth0 便不再具有 IP,這時候它與 tap0 這些虛擬網(wǎng)卡均通過 br1 處于 10.0.1.0/24 網(wǎng)絡(luò),當然我們也可以為網(wǎng)橋 br1 設(shè)置一個別名讓它也具有 172.16.99.0/24 網(wǎng)管網(wǎng)段的 IP 地址。)
下面,我們來實現(xiàn)這個示例網(wǎng)橋,在 node1 與 node2 上分別執(zhí)行下述腳本(對重要命令的描述請參見注釋):
清單 3. node1 與 node2 的 Linux Bridge 配置腳本
- #!/bin/sh
 - TAP=tap0
 - BRIDGE=br1
 - IFACE=eth0
 - MANAGE_IP=172.16.99.108
 - SERVICE_IP=10.0.1.1
 - GATEWAY=10.0.1.1
 - BROADCAST=10.0.1.255
 - # 設(shè)置物理網(wǎng)卡為混雜模式
 - ifdown $IFACE
 - ifconfig $IFACE 0.0.0.0 promisc up
 - # 創(chuàng)建網(wǎng)橋,并物理網(wǎng)卡加入網(wǎng)橋,同時設(shè)置網(wǎng)橋的 IP 為服務(wù)網(wǎng)絡(luò)網(wǎng)段
 - brctl addbr $BRIDGE
 - brctl addif $BRIDGE $IFACE
 - brctl stp $BRIDGE on
 - ifconfig $BRIDGE $SERVICE_IP netmask 255.255.255.0 broadcast $BROADCAST
 - route add default gw $GATEWAY
 - # 在網(wǎng)橋上設(shè)置多 IP,讓它同時具有管理網(wǎng)段的 IP
 - ifconfig ${BRIDGE}:0 $MANAGE_IP netmask 255.255.255.0 broadcast 172.16.99.255
 
注意,上述黑體的一句在 node2 中需要作相應(yīng)修改,其余不變,如下:
- MANAGE_IP=172.16.99.109
 
VLAN
圖 4 同樣適用于 VLAN 網(wǎng)絡(luò),下面我們來實現(xiàn)它。在 node1 與 node2 上分別執(zhí)行下述腳本:
清單 4. node1 與 node2 的 VLAN 配置腳本
- MAC=c8:3a:35:d7:86:da
 - IP=10.0.1.1/24
 - ip link add link eth1 name eth1.1 type vlan id 1
 - ip link set eth1.1 up
 - brctl addbr br1
 - brctl setfd br1 0
 - brctl stp br1 on
 - ip link set br1 address $MAC
 - ip link set br1 up
 - brctl addif br1 eth1.1
 - ip addr add $IP dev br1
 
注意,上述黑體的一句在 node2 中需要作相應(yīng)修改,其余不變,如下:
- MAC= c8:3a:35:d7:86:db
 
測試
我們采用 QEMU 創(chuàng)建虛擬機來進行測試,其中網(wǎng)絡(luò)部分的配置為:
- <interface type='bridge'>
 - <mac address='52:54:00:00:01:89'/>
 - <source bridge='br1'/>
 - <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
 - </interface>
 
我們使用一個現(xiàn)成的鏡像,下載地址:
- curl http://wiki.qemu.org/download/linux-0.2.img.bz2 -o /bak/kvmimages/linux-0.2.img
 
在 node1 與 node2 上分別用下列配置定義兩個虛機,注意,下面打粗體的部分(<mac address='52:54:00:00:01:89'/>)在兩個節(jié)點中請設(shè)置不一樣的值。
cat /etc/libvirt/qemu/test.xml
清單 5. node1 與 node2 的虛機定義文件
- <domain type='qemu'>
 - <name>VM1</name>
 - <uuid></uuid>
 - <memory>393216</memory>
 - <currentMemory>393216</currentMemory>
 - <vcpu>1</vcpu>
 - <os>
 - <type arch='i686' machine='pc-1.0'>hvm</type>
 - <boot dev='hd'/>
 - </os>
 - <features>
 - <acpi/>
 - </features>
 - <clock offset='utc'/>
 - <on_poweroff>destroy</on_poweroff>
 - <on_reboot>restart</on_reboot>
 - <on_crash>destroy</on_crash>
 - <devices>
 - <emulator>/usr/bin/qemu-system-i386</emulator>
 - <disk type='block' device='disk'>
 - <driver name='qemu' type='raw'/>
 - <source dev='/bak/kvmimages/linux-0.2.img'/>
 - <target dev='hda' bus='ide'/>
 - <address type='drive' controller='0' bus='0' unit='0'/>
 - </disk>
 - <controller type='ide' index='0'>
 - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
 - </controller>
 - <interface type='bridge'>
 - <mac address='52:54:00:00:01:89'/>
 - <source bridge='br1'/>
 - <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
 - </interface>
 - <input type='tablet' bus='usb'/>
 - <input type='mouse' bus='ps2'/>
 - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'>
 - <listen type='address' address='127.0.0.1'/>
 - </graphics>
 - <video>
 - <model type='cirrus' vram='9216' heads='1'/>
 - <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
 - </video>
 - <memballoon model='virtio'>
 - <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
 - </memballoon>
 - </devices>
 - </domain>
 
然后用上述配置創(chuàng)建虛機(virsh define /etc/libvirt/qemu/test.xml ),接著啟動虛機( virsh start test ),最后設(shè)置虛機的 IP 和默認網(wǎng)關(guān), 如下:
VM1:
- ifconfig eth0 10.0.1.2 netmask 255.255.255.0 broadcast 10.0.1.255
 - route add default gw 10.0.1.1
 
VM3:
- ifconfig eth0 10.0.1.3 netmask 255.255.255.0 broadcast 10.0.1.255
 - route add default gw 10.0.1.1
 
這時候在一虛機上 ping 另一虛機 , 如果能夠 ping 通,成功。若想要 ping 外網(wǎng)的話,還需在 /etc/resolv.conf 文件中添加域名,如下圖 5 所示:
圖 5. 驗證實驗是否成功
 #p#
OpenStack 云中網(wǎng)絡(luò)拓撲配置示例
在掌握了上述基本原理之后,應(yīng)該不難理解下面 OpenStack 云中的網(wǎng)絡(luò)拓撲。
在 OpenStack 中,目前存在著 nova-network 與 quantum 兩種網(wǎng)絡(luò)組件。nova-network 僅支持下列三種網(wǎng)絡(luò)拓撲:
FlatManager, 不支持 VLAN,也不支持 DHCP 的扁平網(wǎng)絡(luò)
FlatDHCPManager,不支持 VLAN,但支持 DHCP 的扁平網(wǎng)絡(luò)
VlanManager,支持 VLAN,也支持 DHCP 的 VLAN 隔離網(wǎng)絡(luò)
如今 nova-network 的代碼已經(jīng)全部挪到了 Quantum 工程中,但在網(wǎng)絡(luò)拓撲方面,二者的原理是一致的,所以下面只給出一個典型的 nova-network 的網(wǎng)絡(luò)配置,有了上面的基礎(chǔ),現(xiàn)在看這段配置是否會感到很親切呢?
清單 6. /etc/nova/nova.conf 中的網(wǎng)絡(luò)配置示例
- ##### nova-network #####
 - network_manager=nova.network.manager.VlanManager
 - public_interface=eth1
 - vlan_interface=eth0
 - network_host=node1
 - fixed_range=10.0.0.0/8
 - network_size=1024
 - dhcpbridge_flagfile=/etc/nova/nova.conf
 - dhcpbridge=/usr/bin/nova-dhcpbridge
 - force_dhcp_release=True
 - fixed_ip_disassociate_timeout=30
 - my_ip=172.16.99.108
 - routing_source_ip=192.168.99.108
 
相關(guān)參數(shù)說明如下:
network_manager,目前支持 VlanManager、FlatManager、FlatDHCPManager 三種拓撲
public_interface, 接外網(wǎng)的物理網(wǎng)卡 , floating ip 功能需要用到它
valn_interface, 用于劃分 VLAN 的物理網(wǎng)卡
fixed_range, 服務(wù)網(wǎng)絡(luò),即虛機內(nèi)部所用的網(wǎng)絡(luò)地址
my_ip,管理網(wǎng)絡(luò),用于安裝 Openstack 組件的物理機之間的通信。例如:本實驗中的控制節(jié)點同時具有外網(wǎng)網(wǎng)絡(luò)地址 192.168.99.108 與管理網(wǎng)絡(luò)地址 172.16.99.108,另一計算節(jié)點的管理網(wǎng)絡(luò)地址為 172.16.99.109,所以 my_ip 應(yīng)該設(shè)置為 172.16.99.108
routing_source_ip, NAT 映射后的公共網(wǎng)絡(luò) IP,設(shè)置了此參數(shù),會自動執(zhí)行 NAT 命令:
- iptables -t nat -A POSTROUTING -s 172.16.99.0/24 -o eth1 -j SNAT --to 192.168.99.108
 
結(jié)論
云中網(wǎng)絡(luò)一般被劃分為公共網(wǎng)絡(luò)、管理網(wǎng)絡(luò) & 存儲網(wǎng)絡(luò)與服務(wù)網(wǎng)絡(luò)三大類。虛擬網(wǎng)絡(luò)拓撲一般有 NAT、Bridge、VLAN 三種情形。我們手工一步一步地通過 NAT、Bridge、VLAN 三個試驗簡單實現(xiàn)了一個上述典型的云中網(wǎng)絡(luò)。原理都是相通的,您再看 OpenStack 云中網(wǎng)絡(luò)或才其他云的網(wǎng)絡(luò)時都會倍感親切。















 
 
 

 
 
 
 