1. 程式人生 > >OpenStack網路指導手冊 -基本網路概念

OpenStack網路指導手冊 -基本網路概念

[前言]

無論學習OpenStackCloudStack或是其他的雲平臺產品,網路都是舉足輕重的概念和技術。但是網路知識本身就很龐大和複雜,學習起來非常困難,不知道從何處下手。前段時間翻看OpenStack的文件,發現裡面的文章寫的網路基本入門知識非常淺顯易懂,但是沒有中文版本。好東西當然要分享,便在閒暇時間將這篇文章翻譯過來了,希望對渴望瞭解網路知識的人提供一點幫助。同時由於水平有限,裡面的錯誤和疏漏之處也大家批評指正。

原文地址http://docs.openstack.org/networking-guide/intro_basic_networking.html

乙太網(Ethernet

乙太網是一種基於IEEE802.3標準的網路協議。大部分以有線接入通訊的網絡卡(NICS)使用的都是乙太網協議。

OSI七層網路模型中,乙太網位於第二層,即資料鏈路層。當我們討論乙太網時,會經常聽到諸如本地網路,第二層,鏈路層,資料鏈路層等概念。

在以太網中,連線到網路中的主機之間通過交換資料幀通訊。每一臺主機使用MAC地址作為網路中的唯一標識。在OpenStack環境中,每一個虛擬機器例項擁有一個單獨的MAC地址,並且不同於計算節點的MAC地址。每個MAC地址的長度是48位,通常以十六進位制的方式表示,如08:00:27:b9:88:74。每塊網絡卡在出廠時就會被注入MAC地址,現在的網絡卡可以通過工具或者程式設計的方式修改

MAC地址。在Linux系統中,可以通過IP命令獲取一塊網絡卡的MAC地址。

$ ip link show eth0

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000

    link/ether 00:0c:29:de:4b:31 brd ff:ff:ff:ff:ff:ff

理論上說,可以將乙太網理解為一個網路上所有主機連線的匯流排。最初的時候,乙太網是用同軸電纜實現的,每一臺主機通過介面連線到同軸電纜上。現代的乙太網絡不再採用這種方法了,而是將主機直接連線到一個叫做交換機的網路裝置上。但是這個概念模型是有用的,在網路圖中

包括OpenStackDashboard網路圖,乙太網就表現為一個單獨的匯流排。我們會經常聽到一個乙太網網路被稱為一個2層網段。

在同一個乙太網網路中,這個網路上的每臺主機都可以直接向其它的主機發送資料幀。乙太網也支援廣播,所以一臺主機可以通過向一個特殊的MAC地址ff:ff:ff:ff:ff:ff傳送的方式將資料幀傳送給該網路上的所有主機。ARPDHCP是使用乙太網廣播的兩個典型的協議。因為乙太網支援廣播,有時我們會把一個乙太網網路稱為一個廣播域。

當一個網絡卡收到一個乙太網資料幀時,這個網絡卡預設會檢查目的MAC地址是否與網絡卡的MAC地址匹配(或是廣播地址),如果不匹配就會丟棄這個乙太網資料幀。對於一個計算主機,這種行為是不期望的,因為這個資料幀可能是傳送給計算節點上一個例項的。網絡卡可以配置為混雜模式,即使MAC地址不匹配,也可以將所有的乙太網資料幀傳送給作業系統。因此,計算節點應當將特定的網絡卡配置為混雜模式。

正如之前提到的,現代乙太網使用交換機作為網路上主機的互聯裝置。一個交換機是一個有很多個埠的網路硬體盒子,乙太網通過交換機將乙太網資料幀從一個主機轉發到連線到交換機上的另一個主機。當主機第一次通過交換機發送資料幀時,交換機不知道哪個MAC地址連線到了哪個埠。如果一個乙太網資料幀指向一個的MAC地址,交換機會將資料幀廣播到所有的埠。交換機埠通過觀察資料流學習哪個MAC地址關聯到哪個埠。一旦這個埠知道了MAC地址和埠的關聯關係,它可以直接將乙太網資料幀傳送到正確的埠而不必再廣播了。交換機維護MAC地址和交換機埠的對應表,這個表稱之為一個轉發表或轉發資訊庫(FIB)。交換機之間可以通過daisy-chained(菊花鏈)的方式連線到一起,這樣做的結果就是主機和交換機就像連線到了一個網路上。

虛擬區域網(VLANs

VLAN是一種虛擬網路技術,它可以將一臺物理交換機劃分成多個邏輯交換機,使得每個邏輯交換機同獨立的物理交換機一樣。這樣,連線到同一臺物理交換機上的兩臺主機如果屬於不同的VLAN,則它們之間彼此看不到對方的網路流量。OpenStack利用VLAN的這個特性隔離不同租戶的網路通訊,即使不同租戶的例項在同一臺計算主機上執行。每一個VLAN都有一個關聯的ID號,VLAN ID14095中的一個數字。我們說“VLAN 15”就表明這個VLAN關聯的ID15

要理解VLAN是如何工作的,可以參照VLAN在傳統IT環境下是如何應用的,物理主機連線到物理交換機,不引入虛擬化。想象一個場景,你只有一臺物理交換機,但是想建立3個網路。網路管理員會選擇3VLAN ID,例如101112,並且將VLAN ID與交換機上的埠關聯起來。例如,交換機埠2VLAN10關聯,埠3VLAN 11關聯,等等。當一個埠配置一個特定的VLAN,這個埠就被稱為訪問埠(Access口)。這臺交換機相應就保證了VLAN之間網路流量是隔離的。

我們再考慮一個場景,第一臺交換機的所有埠都已經被使用了,單位又買了第二臺交換機並且與第一臺交換機連線起來以擴充套件交換機埠的數量。第二臺交換機也支援VLAN 101112。設想連線到第一臺交換機配置為VLAN 10埠的主機A傳送一個以太網資料幀給主機B主機B連線到了第二臺交換機配置為VLAN 10的埠。當第一臺交換機向第二臺交換機轉發轉發資料幀時,它必須標記資料幀與VLAN ID10關聯。

如果兩臺交換機連線在了一起,並且它們都配置了VLAN,連線兩臺交換機的埠必須配置為允許任何VLAN的資料幀轉發到另外一臺交換機上。此外,傳送資料的交換機必須為每個乙太網資料幀打VLAN ID標籤,這樣接收交換機可以保證只有與VLAN匹配的主機接受到資料幀。當一個交換機埠被配置為通過所有VLAN的資料幀並且將這些資料幀打上VLAN ID標籤時,這個埠就被稱為Trunk口。IEEE 802.1Q網路標準描述了應用trunk時,VLAN標籤如何在乙太網資料幀編碼的。

需要注意的是,在OpenStack雲中,如果你使用在物理交換機上劃分VLAN的方式實現多租戶隔離,必須保證所有的交換機埠都配置為trunk埠。

確保在雲中選擇使用沒有被使用的VLAN範圍。例如,預計你的雲將會支援最大100個專案,需要選擇一個大於100VLAN範圍,比如VLAN 200-299OpenStack和所有處理租戶網路的物理網路基礎架構必須支援這個VLAN範圍。

trunk是為了連線不同的交換機。每個trunk使用一個標籤標識使用了哪個VLAN。這樣就保證了同一VLAN的交換機可以通訊。

子網和地址解析協議(Subnets and ARP

網絡卡使用MAC地址標識網路中的主機,然而TCPIP應用使用IP地址。地址解析協議(ARP)通過將IP地址轉換為MAC地址的方式將二者之間的縫隙連線起來。

IP地址分為網路號和主機號兩個部分。如果兩個主機有共同的網路號,則它們處於同一個子網中。回憶一下兩臺主機只有在同一個本地網路中才能通過乙太網直接通訊。ARP認為在同一個子網內的主機都在同一個本地網路上。網路管理員在為主機分配IP地址和子網掩碼時必須注意任意兩臺同一子網的主機必須在相同的本地網路上,否則ARP就不能正常解析IP地址。

通過IP址的子網掩碼可以計算IP地址的網路號。子網掩碼錶示32位的IP地址中有多少位標記網路號。

子網掩碼的兩種表示方法:

●        點分符號法

●        無類域間路由(CIDR)法

考慮一個IP地址192.168.1.5,它的前24位表示網路號。用點分方法的寫法是255.255.255.0CIDR表示法包含IP地址和子網掩碼,這個IP可以寫為192.168.1.5/24

注意:

在OpenStack環境中建立CIDR子網不能包含多播地址或者本地環路地址。例如不支援使用224.0.0.0/16或者127.0.1.0/24建立子網。

有時我們想要表示一個子網,但是並不指定子網上具體的IP地址。一個通用的做法是把所有的主機標識設為0。例如,如果一個主機的IP地址是10.10.53.24/16,我們說這個子網是10.10.0.0/16

要理解ARP如何將IP地址轉換為MAC地址的,考慮下面這個例子:假設主機AIP地址是192.168.1.5/24MAC地址是fc:99:47:49:d4:a0,並且主機A想要向主機B傳送一個包,主機BIP地址是192.168.1.7。注意,這兩臺主機的網路號是一樣的,所以主機A可以直接向主機B傳送資料幀。

第一次,主機A想要與主機B通訊,目的MAC地址是不知道的。主機A向本地網路發起一個ARP請求。這個ARP請求發起一個如下的廣播訊息:TOeverybody(ff:ff:ff:ff:ff:ff)。我正在尋找一臺IP地址為192.168.1.7的計算機。簽名:MAC地址fc:99:47:49:d4:a0

主機B做如下回應

To: fc:99:47:49:d4:a0。我有IP地址192.168.1.7。簽名: MAC address 54:78:1a:86:00:a5

主機A向主機B傳送乙太網資料幀。

你可以使用arping命令手工發起一個ARP請求。例如,向IP地址172.16.28.2傳送ARP請求:

$ arping 172.16.28.2

ARPING 172.16.28.2 from 172.16.28.241 eth0

Unicast reply from 172.16.28.2 [00:50:56:E6:47:5F]  0.818ms

Unicast reply from 172.16.28.2 [00:50:56:E6:47:5F]  0.797ms

Unicast reply from 172.16.28.2 [00:50:56:E6:47:5F]  0.757ms

Sent 3 probes (1 broadcast(s))

Received 3 response(s)

為了減少ARP請求的次數,作業系統維護了一個ARP快取,包含了IP地址向MAC地址的對映。在Linux機器上,可以使用arp命令檢視ARP快取裡的內容:

$ arp -n

Address                  HWtype  HWaddress           Flags Mask            Iface

172.16.28.2              ether      00:50:56:e6:47:5f      C                     eth0

172.16.28.1              ether      00:50:56:c0:00:08    C                     eth0

DHCP

主機可使用動態主機配置協議DHCP)自動獲取網路IP地址。DHCP伺服器負責將IP地址分發到網路上的主機,這些主機稱為DHCP客戶端。

DHCP客戶端通過68埠向255.255.255.255這個地址的67埠傳送一個UDP包來定位DHCP伺服器。地址255.255.255.255為本地網路的廣播地址:本地網路上的所有的主機都可以看到傳送到這個地址的UDP包。然後,這些資料包不會轉發到其他網路上。所以,DHCP伺服器必須與DHCP客戶端在同一個網路上,否則DHCP伺服器就收不到來自客戶端的廣播包。DHCP伺服器通過從67埠傳送一個到客戶端68UDP包來響應客戶端的請求。客戶端與伺服器端的資料交換大體如下:

1.   客戶端傳送一個發現請求(我是一個在MAC地址08:00:27:b9:88:74上的客戶端,我需要一個IP地址)

2.   伺服器端提供服務(好的,08:00:27:b9:88:74,我為你提供了10.10.0.112這個IP地址)

3.   客戶端傳送一個請求(伺服器10.10.0.131,我將會使用10.10.0.112這個IP地址)

4.   伺服器傳送一個確認(好的,08:00:27:b9:88:7410.10.0.112這個IP地址是你的了)

OpenStack使用了一個叫做dnsmasq的第三方程式實現了DHCP伺服器。DnsmasqDHCP的請求和應答寫入到了syslog,我們可以在syslog中檢視。

$ Apr 23 15:53:46 c100-1 dhcpd: DHCPDISCOVER from 08:00:27:b9:88:74 via eth2

Apr 23 15:53:46 c100-1 dhcpd: DHCPOFFER on 10.10.0.112 to 08:00:27:b9:88:74 via eth2

Apr 23 15:53:48 c100-1 dhcpd: DHCPREQUEST for 10.10.0.112 (10.10.0.131) from 08:00:27:b9:88:74 via eth2

Apr 23 15:53:48 c100-1 dhcpd: DHCPACK on 10.10.0.112 to 08:00:27:b9:88:74 via eth2

當排查一臺例項無法通過網路訪問時的問題時,可以通過檢查這個日誌來驗證DHCP協議的四個步驟來幫助我們解決問題。

IP

網際網路協議(IP)規定如何在兩臺連線在不同本地網路上的主機之間路由資料包。IP依賴稱為路由或閘道器的特殊主機。一個路由器是一臺連線到至少兩個本地網路上的主機,並且可以將IP資料包從一個本地網路轉發到另外的本地網路。一個路由器有多個IP地址:每一個IP地址對應與其連線的網路。

OSI七層網路模型上,IP位於第三層,這一層被稱為網路層。當我們討論IP是,會經常聽到諸如第三層,L3和網路層這樣的詞彙。

當一臺主機向一個IP地址傳送資料包時,它首先會查詢自己的路由表,然後決定將資料包傳送到本地網路的哪臺主機上。一個路由表維護了這臺主機所連線的本地網路的子網清單,以及這些本地網路上的路由器的清單。

在一臺Linux機器上,下面的任何一條命令都可以顯它的示路由表:

$ ip route show

$ route –n

$ netstat -rn

下面時使用ip route show輸出路由表的例子:

$ ip route show

default via 10.0.2.2 dev eth0

10.0.2.0/24 dev eth0  proto kernel  scope link  src 10.0.2.15

192.168.27.0/24 dev eth1  proto kernel  scope link  src 192.168.27.100

192.168.122.0/24 dev virbr0  proto kernel  scope link  src 192.168.122.1

第一行的輸出指定了預設路由的位置,當其他的路由規則都不匹配時由它作為一個有效的路由。連線在預設路由上的路由器(上面例子中的10.0.2.2)有時會作為預設的閘道器。DHCP伺服器一般會將預設閘道器的IP地址以及客戶端IP和子網掩碼傳輸給客戶端。

第二行輸出表示在10.0.2.0/24子網中的IP處於與網絡卡eth0連線的本地網路上。

第三行輸出表示在192.168.27.0/24子網中的IP處於與網絡卡eth1連線的本地網路上。

第四行輸出表示在192.168.122/24子網中的IP處於與網絡卡virbr0連線的本地網路上。

Route –n netstatrn命令的輸出格式只有細微的差別。下面這個例子展示了使用這兩個命令的輸出格式:

$ route -n

Kernel IP routing table

Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface

0.0.0.0         10.0.2.2        0.0.0.0         UG        0 0          0 eth0

10.0.2.0        0.0.0.0         255.255.255.0   U         0 0          0 eth0

192.168.27.0    0.0.0.0         255.255.255.0   U         0 0          0 eth1

192.168.122.0   0.0.0.0         255.255.255.0   U         0 0          0 virbr0

Ip route get命令輸出目的IP地址的路由。下面的例子中,目的IP地址10.0.2.14在本地網路的eth0網絡卡上,可以直接傳送:

$ ip route get 10.0.2.14

10.0.2.14 dev eth0  src 10.0.2.15

目的IP地址93.184.216.34沒有在主機連線的任何本地網路上,將會轉發到10.0.2.2這個預設閘道器上。

一個IP包通過多個路由器跳轉到達目的地址是通常發生的情況。在一個Linux主機上,traceroute和最近的mtr程式可以打印出一個IP包經過的每個路由器的IP地址。

TCP/UDP/ICMP

網路軟體程式通過IP網路通訊,它們需要使用IP層之上的協議。這些協議位於OSI模型的第四層,被稱為傳輸層或第四層。可參考由網際網路數字分配機構(IANA)維護的Protocol Numbers這個網頁,這個網頁列出了IP協議智商的協議列表和它們關聯的協議號。

傳輸控制協議(TCP)是最常用的4層協議。TCP是一個面向連線的協議:它使用客戶端-伺服器端模型,客戶端連線到伺服器端,伺服器端啟動收到連線的應用程式。基於TCP的應用程式典型的互動過程如下:

1.   客戶端向伺服器端發起連線請求

2.   客戶端羽伺服器端交換資料

3.   客戶端與伺服器端斷開連線

因為一個網路主機可能會有多個基於TCP的應用在執行,TCP使用一個叫做埠的地址模式來唯一標識基於TCP的應用。TCP埠的範圍為1-65535,作業系統強制限制在同一時間主機上僅能有一個應用程式使用同一個埠。

一個TCP服務監聽一個埠。例如,SSH服務通常監聽22埠。一個客戶端使用TCP連線到一個伺服器,這個客戶端必須同時知道伺服器的IP地址和TCP埠。

TCP客戶端程式的作業系統自動為客戶端分配一個埠號。這個客戶端將會保留這個埠號直至TCP連線中斷,之後作業系統會回收這個埠號。這類埠稱為臨時埠。

IANA維護了很多基於TCP服務的埠號記錄表,以及使用埠號的其他四層協議。註冊一個TCP埠號是不必要的,但是註冊一個埠號對於避免與其他服務衝突是有幫助的。請參考附錄B:OpenStack配置指南的防火牆與預設埠部分檢視部署一個OpenStack環境相關的不同服務使用的預設埠號。

寫基於TCP程式最常用的軟體程式設計介面是伯克利sockets,另外的稱謂是BSD sockets 或簡稱sockets。Sockets API為TCP程式釋放面向流的介面:從程式設計師的視角來,通過TCP連線傳送資料類似於向一個檔案寫位元組流。作業系統的TCP/IP實現將資料流分解組合成IP資料包。作業系統也負責重傳丟棄的資料包,並且負責流量控制,從而保證傳送的資料不會超出傳送資料快取、接收資料快取和網路傳輸能力。最終,作業系統在接受端將資料包按照正確的順序重組成資料流。因為TCP檢測並重傳丟失的資料包,所以它被稱為可靠的協議。

使用者資料報協議(UDP)是另一種四層協議,它是很多著名網路協議的基礎。UDP是一個無連線的協議:兩個通過UDP通訊的應用程式在交換資料中前無需建立連線。UPD協議同時也是一個不可靠的協議。作業系統不會監測或重傳丟失的UDP資料包。作業系統同樣不保證接受到的資料包順序與傳送順序一致。

UDPTCP一樣,使用埠的概念區分執行在同一個系統上的不同應用。需要注意的是作業系統對待UDP埠與TCP埠是分開的。例如一個程式使用TCP16543,另一個程式可以使用UDP16543

TCP一樣,Socket API是寫基於UDP程式的最常用的介面。Sockets APIUDP程式提供了一個面向訊息的介面:一個程式通過傳送一個固定大小的訊息在UDP傳送資料。如果一個程式需要重傳丟失的資料包或者需要定義良好的接收順序,需要在應用中依靠程式自己來實現這些功能。

DHCP,域名系統(DNS),網路時間協議(NTP)和虛擬可擴充套件區域網(VXLAN)是在OpenStack環境中使用UDP協議的典型例子。

UDP支援一對多的通訊,向多臺主機發送一個數據包。通過將接收端IP地址設為特殊的IP廣播地址255.255.255.255,應用可以向同一網路中所有主機發送一個UDP廣播包。應用也可以使用IP多播將一個UDP資料包傳送到一組接收主機。接收端應用程式通過將UDP socket繫結到一個特殊的有效多播組IP地址就可以加入到一個多播組。接收端主機並不一定與傳送端主機在一個本地網路中,但是中間的路由器必須配置為支援IP多播路由。VXLAN就是一個基於UDP協議使用IP多播的例子。

Internet控制報文協議是一個通過IP網路傳送控制報文的協議。例如,如果一個路由器在它的路由表中找不到對應的目的地址(ICMP編碼1,目的主機不可達)或者IP資料包太大以至於超出了路由器的處理能力(ICMP編碼4,需要分段並且沒有置位分段標識),這臺路由器就會向源主機發送一個ICMP包。

pingmtrLinux命令列工具是網路應用使用ICMP的兩個例子。