一文理解OpenStack網路

摘要:如果你能理解OpenStack的網路,那麼對於其他雲平臺的網路,應該也可以透過分析後理解掌握了。

本文分享自華為雲社群《《跟唐老師學習雲網絡》 - OpenStack網路實現-雲社群-華為雲》,作者: tsjsdbd 。

整體設計

首先,OpenStack是用來管理大量的VM的“上帝”。他的目的是要像掌控物理世界一樣,去管理大量的VM。即:可以給VM分組,同一個組裡面的VM,在同一個網路內,可以互通通訊。不同組的VM,則相當於在不同的網路中,互相不能通訊。

一文理解OpenStack網路

至於為什麼要分組,

1、是跟物理伺服器一樣,那麼多機器,按照不同機房的伺服器,連到不同的網路。

2、是我可以把不同組的VM,賣給不同的“使用者”,這樣,組1的VM屬於張三,組2的VM屬於李四,這樣他們倆互相隔離,互不感知。於是我就可以化身成為雲廠商,對外提供雲平臺服務了。

當然你作為雲廠商,也肯定要允許一個使用者,可以擁有2個網路嘛。萬一該客戶人傻錢多,就是買了一堆VM,分著玩呢,是吧。

邏輯檢視

現實中,2個機房的伺服器,網路要想連通,是要靠路由器來幫忙的。在虛擬世界中也是類似的。

所以,邏輯上,VM世界的網路就是長這個樣。

一文理解OpenStack網路

張三的VM的網路,要想和李四VM的網路 互通,或者張三自己的2個獨立網路互通。就得透過一個叫做 Router 的“虛擬路由器”來完成。

物理檢視

上面的邏輯檢視,在物理上,則是這個樣子的:

一文理解OpenStack網路

至於如何在一根網線上面,同時跑多個虛擬網路的報文。這個就是在一根網線上的報文,有不同門派的意思。具體的可以回去看VLAN/VxLAN章節。

另外,這裡你可以看到,虛擬網路裡面的一個“Router”,其實不是什麼具體的虛擬路由器裝置,而僅僅是一個“網路名稱空間+轉發規則”就達成了,下面會細講。

簡單模型

假設現在你來設計OpenStack的網路實現。

那從我們之前學到的OVS章節,可以知道,為了達成上面提到的OpenStack的網路虛擬化目的。最簡單的實現是給每個物理伺服器上增加一個OVS虛擬交換機;然後每個VM都連到OVS埠上,每個埠則按照分組,打上對應的VLAN標籤。就可以達成基本要求。

一文理解OpenStack網路

但是,這個初始1。0版本的實現,有個不牛批的地方,就是沒法給VM設定安全組。你作為想成為雲平臺偉大目標,平臺怎麼能沒有安全組這個能力呢(雖然,在VM裡面,可以設定firewell或者iptables規則,但是VM裡面,那是已經賣給使用者的了,你跑人家房間裡面,去設定規則並不合適,可能和使用者自己的業務規則衝突)。

所以第2個版本,改進之。我們要在VM的外面設定安全組:

一文理解OpenStack網路

於是,我們在每個VM大門口,增加一個Bridge網橋,任何VM的流量,都會經過這個Bridge。這樣,透過在Bridge上面,增加iptables規則,就可以達到給VM設定安全組的目的了。(注意,這個時候,VM的報文還沒有到OVS,所以報文還是沒有打VLAN標籤的原始報文,所以iptables規則也好實現)。

這就是咱們的OpenStack網路2。0版本。

但是,在實踐中,你發現這個獨苗OVS,要設定埠轉發規則有2部分:

上半部分。即:給VM設定Tag標籤。

每增加一臺VM時,就給這個埠打標籤,插拔虛擬網線等配置動作。這一部分邏輯比較固定,不怎麼變化。

下半部分。即:透過物理網線,怎麼給報文打“門派”標記。

這一部分變化很大,有時候物理網路,咱得走GRE,有時候要走VLAN,有時候又得VxLAN。還有時候,得走專用的網路裝置。平臺得根據部署的機房網線,定製不同的規則。

這樣這2類OVS的規則不好管(都放openflow的轉發表裡面),本著程式設計師的“分庫分表”(或者咱們寫程式碼時的,“抽取函式”的邏輯)的思路,咱們把1個獨苗OVS,分成多個VOS。分別做不同的事情。

一文理解OpenStack網路

於是,咱們到了3。0版本,這個版本就比較通用了。基本可以和實際OpenStack的網路比較接近了。不過在網路節點部分,還得再增強一下。就是咱們的VM,除了互訪之外(流量還在幾臺物理伺服器之間轉悠),還得訪問外網呀(流量跑機房外部去)。 所以,還得繼續增強一下VM訪問外部網路的能力:

一文理解OpenStack網路

這麼一來,就到了差不多4。0版本了。後面咱們介紹的OpenStack網路,就是照著這個版本來的。在OpenStack網路裡面,對各種ovs,bridge,介面的命名,有一套自己的規範。不像上面這麼隨意的取名。

控制節點

有了上面這些給VM設定虛擬網路用的模型,那麼要搞成自動化(即:每建立一個VM,給它設定好配套的虛擬網線連線)。 你得寫個主控程式,用來控制這些計算節點上面的行為吧。如下:

一文理解OpenStack網路

所以,按照OpenStack官方的架構,它需要有3種節點:管節點,計算節點,網路節點。

每個節點上面,部署了一堆agent,用來接收老大的控制命令。老大就是Master管理節點了。

注:之前章節也提過,分散式系統,可靠的控制都需要有個“代理商”,比如RabbitMQ(OpenStack選了這個),ETCD(Kubernetes選了這個),ZooKeeper(Hadoop選了這個)這種。

一文理解OpenStack網路

(1)首先是最上面紅色的線,就是“主控邏輯”用來控制Agent幹活的,簡稱管理面網路。

(2)然後是中間綠色的線,那就是VM們在這根網線上面,傳送大量的“自己門派”的報文,即VM間互相通訊,都要走的網路,資料量很大。簡稱資料面。

為了確保管理面和資料面隔離,互不影響(即:VM瘋狂發包,別把管理命令的報文給衝沒了)。每臺物理伺服器上面,得有2塊網絡卡,一塊用來走管理網線,一塊用來走資料網線。

(3)接著就是左下角的墨綠色線,這個是VM們訪問機房外部網路用的。只需要網路節點,有一個額外的網絡卡就行了。

(4)最後是紫色的線。你的主控邏輯,要不要包裝成API介面,對外部暴露訪問通道? 要的話,可以加上。不要的話,那就每次都登陸到主控節點裡面,手動敲命令控制也行。

計算節點

這裡咱們開啟一個OpenStack的計算節點,看看它的網路構造,遙記當年(2013年,OpenStack版本Havana)我學OS網路的時候,看到一個資料,對我幫助很大,這裡直接貼上來:

一文理解OpenStack網路

照著前文的“設計思路”,你應該可以看懂上圖的網路邏輯了吧。命名上,一般內部的ovs叫 br-int。隧道的叫 br-tun。如果你有環境的話,在節點上面查詢,使用各種網路命令(ip,ovs-vsctl,brctl等),你可以證實一下。

網路節點

同樣,網路節點,網路組成如下:

一文理解OpenStack網路

其中,上部的紅色虛線,表示一個 網路namespace。dnsmasq是一個DHCP伺服器(自動分配IP的程式,用來給VM分配IP地址)。

這個節點也使用各種網路命令來查詢檢視確認。

ps,由於該網路節點上有很多網路namespace,所以記得使用 ip netns exec命令來進入到對應的ns查詢這個虛擬空間裡面的詳情。

floating IP(EIP)

VM除了有自己的虛擬網路內的IP,還可以擁有一個floating IP(注:對應雲廠商,一般把這個叫做 EIP)。咱們來看下這個“浮動IP”是個什麼實現邏輯。

邏輯概念

首先,浮動IP,是物理網路世界的,即OpenStack的外部網路的。它是一個真實存在的IP地址(不跟VM一樣,那是你虛擬出來的IP)。

一文理解OpenStack網路

如上圖,對floating IP,我總結的一句話概況就是:VM對外的名號。

當你從外部網路,訪問這個“浮動IP”,就等於訪問這一臺VM。至於為什麼要叫“浮動”這個詞,是因為這個名號,會漂移。

舉個例子:“護國大法師”這個名號很響亮,當你一報你要找“護國大法師”這個人時,大家都知道你要找具體的誰。但是這個“護國大法師”名號,是可以從一個人身上轉移到另一個人身上的。

一文理解OpenStack網路

直接對應雲廠商的EIP,是不是就好理解了。

具體實現

我們關注點,直接聚焦到網路節點的一個namespace裡面。(本例的浮動IP是 192。168。101。3)。如下圖:

一文理解OpenStack網路

在網路節點,查詢ns。

root@netnode:/# ip netnsqdhcp-a7e512cf-1ca0-4ec7-be75-46a8998cf9caqrouter-4cdb0354-7732-4d8f-a3d0-9fbc4b93a62d複製

找到對應的 router 那個ns(上圖五角星處),然後查詢這個裡面的網絡卡資訊:

root@netnode:/# ip netns exec qrouter-4cdb0354-7732-4d8f-a3d0-9fbc4b93a62d ip address11: qg-1423ba35-7c: mtu 1500 qdisc noqueue state UNKNOWN inet 192。168。101。2/24 brd 192。168。101。255 scope global qg-1423ba35-7c inet 192。168。101。3/32 brd 192。168。101。3 scope global qg-1423ba35-7c12: qr-9f1fa61e-1e: mtu 1500 qdisc noqueue state UNKNOWN inet 172。17。17。1/24 brd 172。17。17。255 scope global qr-9f1fa61e-1e複製

可以看到,有個叫qg-xx的網絡卡,擁有了這個 floating IP地址。

然後我們查詢一下這個ns裡面的iptables規則:

root@netnode:/# ip netns exec qrouter-4cdb0354-7732-4d8f-a3d0-9fbc4b93a62d iptables -t nat -S複製

你會發現有這麼2條規則:

-A quantum-l3-agent-float-snat -s 172。17。17。2/32 -j SNAT ——to-source 192。168。101。3-A quantum-l3-agent-PREROUTING -d 192。168。101。3/32 -j DNAT ——to-destination 172。17。17。2複製

第1條是SNAT規則,就是把源IP地址換掉的意思。 具體內容是:如果源IP是 172。17。17。2 的(VM的),那麼把源IP換成192。168。101。3(floatingIP的)。

第2條是DNAT規則,就是把目的IP地址換掉。具體內容是:如果目的IP的192。168。101。3(floatingIP的),就把目的IP換成172。17。17。2 的(VM的)。

這樣一來,報文不就統統轉給了這個VM嘛。

一文理解OpenStack網路

於是,一個VM一旦擁有了floatingIP(也叫EIP),它就可以被外網訪問,也可以直接訪問外網。

不過,真正的外部IP,可能是有限的,得省著點用,這就有了下面的SNAT和DNAT功能。

SNAT功能

如果一臺VM,想訪問外部網路,但是又不給它分配floatingIP。這時候就可以使用SNAT。

一文理解OpenStack網路

還是上一節的這個ns,查詢這個ns裡面的網絡卡資訊,可以看到,還有一個 101。2 的IP。

root@netnode:/# ip netns exec qrouter-4cdb0354-7732-4d8f-a3d0-9fbc4b93a62d ip address11: qg-1423ba35-7c: mtu 1500 qdisc noqueue state UNKNOWN inet 192。168。101。2/24 brd 192。168。101。255 scope global qg-1423ba35-7c inet 192。168。101。3/32 brd 192。168。101。3 scope global qg-1423ba35-7c12: qr-9f1fa61e-1e: mtu 1500 qdisc noqueue state UNKNOWN inet 172。17。17。1/24 brd 172。17。17。255 scope global qr-9f1fa61e-1e複製

還是查詢一下這個ns裡面的iptables規則:

root@netnode:/# ip netns exec qrouter-4cdb0354-7732-4d8f-a3d0-9fbc4b93a62d iptables -t nat -S複製

你會發現有這麼1條規則:

-A quantum-l3-agent-snat -s 172。17。17。0/24 -j SNAT ——to-source 192。168。101。2複製

該規則是,所有源IP是 172。17。17。0/24 這個網段的報文(就是該網路內的所有VM),都把源IP地址換掉的意思。

所以,一旦給一個虛擬網路設定了SNAT功能,那麼這個網路裡面的所有VM,都可以訪問外網了。只是大家共用一個外部出口IP地址(本質還是EIP),這個就是省著點用的意思。

缺點是:只能從內部(虛擬網路)訪問外部(外部網路),外部不能訪問內部(畢竟,這個IP是大家共用的,不是某一臺VM的)。

DNAT功能

在本著省著點用的原則下(即好多VM共享一個外部IP)。如果希望外部訪問內部VM,還可以使用DNAT功能。

一文理解OpenStack網路

原理上,你應該想到了,就是在ns裡面增加一條,根據不同的埠,轉發不同目的IP地址的DNAT規則。

這一種省錢的辦法,缺點是:只能指定對應的目的埠。比如,外部埠80,分配給VM1佔用了。那麼VM2就不能用80了,它只能委屈下,使用外部埠號81(或其他)了。

一文理解OpenStack網路

省錢總得要失去點什麼,要不然,給每臺VM都買個EIP不就完了。

Router

OpenStack裡面的Router,是用來將“一個網路”,連線到“另一個網路”的。可以是2個虛擬網路,也可以是1個虛擬網路+1個實際外部網路。

一個Router本質是一個 網路namespace,同上一個章節描述浮動ip一樣,這個ns是一個虛擬的“中轉站”。 所有的網路連線,需要先到這個中轉站“休息打扮一下”,然後再前往目的網路。

一文理解OpenStack網路

注意,在同一個使用者的2個網路互聯,和2個不同使用者的網路互聯,在底層實現的技術上是一樣的。不同點是不同使用者的話,需要控制好許可權,不然張三不就可以隨便去連李四的網路了。

Router概念,對應到雲廠商,一般叫 “VPC互聯”。產品各式各樣,比如以前的“vpc peering”,現在的“雲企業網路”“企業路由”“雲連線”等。

Metadata服務

metadata服務,就是允許每個VM去問上帝(OpenStack平臺):“你建立我的檔案上面,都寫了些什麼?”。 這是一個非常有意思的特性。

功能介紹

你(VM)去問上帝,你總得知道上帝在哪裡把?所以在OpenStack上,將上帝的地址,寫死了一個特殊的IP:169。254。169。254, 挺好記的。

詢問上帝的方法:

$ curl http://169。254。169。2541。02007-01-192007-03-012007-08-292007-10-102007-12-152008-02-012008-09-012009-04-04latest複製

你可以去試一下,如果發現這個IP可以訪問,說明你可以證明自己的機子是一臺被虛擬出來的VM,而不是一臺物理機了。

舉個例子,VM問:我被生出來後的啟動指令碼是什麼?

即問自己的 “userdata資訊”

$ curl http://169。254。169。254/openstack/latest/user_data#!/bin/bashecho ‘Extra user data here’複製

這個功能,還是比較有用的,特別是在做VM自動化的時候(ps,可以去查一下一個稱作 cloud-init 的東西)。

metadata特性應該是來自AWS。OpenStack為了相容AWS的這個“詢問上帝”的功能(當然,肯定也是認可這個功能還是有用的)。也支援了這個 metadata服務。

具體實現

我們知道創造&管理VM的元件,是叫Nova。也就是metadata特性,要從虛擬世界(VM裡面)去訪問物理世界(Nova的API),經過上面的介紹,這種情況下,肯定要經過一個“中轉站”的。

一文理解OpenStack網路

我們先看下VM內部,訪問169。254。169。254的時候,報文去哪裡了:

在VM裡面敲:

ip routedefault via 172。17。17。1 dev eth0172。17。17。0/24 dev eth0 src 172。17。17。5169。254。169。254 via 172。17。17。1 dev eth0複製

可以看到 訪問“上帝”時,報文去了 VM網路的閘道器IP(172。17。17。1)那了。

那麼閘道器IP在哪裡?在網路節點的namespace裡面:

root@netnode:/# ip netns exec qrouter-4cdb0354-7732-4d8f-a3d0-9fbc4b93a62d ip address複製

裡面有個網絡卡叫做:

12: qr-9f1fa61e-1e: mtu 1500 qdisc noqueue state UNKNOWN inet 172。17。17。1/24 brd 172。17。17。255 scope global qr-9f1fa61e-1e複製

我們再來看下,訪問169。254的報文,到這個“中轉站”後,被如何“拿捏”的。

root@netnode:/# ip netns exec qrouter-7a44de32-3ac0-4f3e-92cc-1a37d8211db8 iptables -S複製

可以看到,目的地址是169。254的報文,會轉給本地的 9697埠。

-A quantum-l3-agent-PREROUTING -d 169。254。169。254/32 -p tcp -m tcp ——dport 80 -j REDIRECT ——to-ports 9697-A quantum-l3-agent-INPUT -d 127。0。0。1/32 -p tcp -m tcp ——dport 9697 -j ACCEPT複製

那麼,誰在本地(這個namespace內)監聽 9697埠呢?答案是上帝的代理,一個agent在這裡偷聽呢。

root@netnode:/# ip netns exec qrouter-7a44de32-3ac0-4f3e-92cc-1a37d8211db8 netstat -anpttcp 0 0 0。0。0。0:9697 0。0。0。0:* LISTEN 11937/python 複製

看下這個程序號,具體的命令:。

root@netnode:/# ps -ef | grep 11937root 11937 1 0 08:43 ? 00:00:00 python /usr/bin/neutron-ns-metadata-proxy -metadata_proxy_socket=/var/lib/neutron/metadata_proxy複製

可以看到,有一個proxy程序監聽者9697埠,並將“訪問上帝的請求”,轉給了本地 unix domain socket 的監聽者(即agent)。

使用

root@netnode:/# netstat -lxp | grep metadata複製

或者

root@netnode:/# lsof /var/lib/neutron/metadata_proxy 複製

查詢到在監聽本地unix domain socket的程序ID

然後看下這個程序ID,是不是上帝的agent:

root@netnode:/# ps -ef | grep “具體程序ID”複製

邏輯上,整體過程如下:

一文理解OpenStack網路

具體可參考該圖:

一文理解OpenStack網路

所以,關鍵其實還是那個 namespace中轉站。

附,本段參考連結:

http://niusmallnan。com/_build/html/_templates/openstack/metadata_server。html

http://techbackground。blogspot。com/2013/06/metadata-via-quantum-router。html

DVR(分散式虛擬路由)

在上面的介紹中可以看到,所有的VM虛機,要訪問外網,都要經過網路節點。這樣也有不好地方,1是網路節點的網路流量壓力非常大;2是一旦網路節點異常,大量的VM都要受影響。所以,這裡能不能把網路節點的“中轉站”功能,複製一份到各個計算節點上去。然後在計算節點上面,增加判斷邏輯:

if (本地有“中轉站”) && (符合使用條件) {使用本地“中轉站”};else {繼續使用原來的網路節點的“中轉站”}。複製

答案就是DVR了。為了降低網路節點的負載,同時提高可擴充套件性,OpenStack在Juno版本引入了DVR特性,DVR部署在計算節點上。計算節點上的VM使用floatingIP訪問Internet,不必經過網路節點,直接從計算節點的DVR就可以訪問。

一文理解OpenStack網路

這樣網路節點只需要處理佔到整體流量一部分的 SNAT (無 浮動 IP 的 vm 跟外面的通訊)流量,大大降低了負載和整個系統對網路節點的依賴。

具體計算節點的if條件判斷,就是透過openflow規則,來控制的。這個有點太細節了,沒有細研究。可以去看看相應的文章:

https://www。cnblogs。com/sammyliu/p/4713562。html

https://docs。openstack。org/ocata/networking-guide/deploy-ovs-ha-dvr。html

所以你可以看到,原來網路節點的路由器,現在分散到各個計算節點上面了。原來一個人(網路節點的Router)要乾的活,現在分散給很多人(各計算節點的Router)幹。確實分散式路由器了。

總結

基本上,OpenStack的網路實現,是集成了目前所有的“網路虛擬化零件”,包括:ovs交換機,bridge網橋,veth網線,tap網線,patch網線,namespace空間,iptables規則等。也是唐老師我接觸過最複雜的網路實現(所以本文一直拖到最後)。如果你能理解OpenStack的網路,那麼對於其他雲平臺的網路,應該也可以透過分析後理解掌握了。

最後,基礎的雲網絡相關的課程,唐老師就只能教到此了。畢竟咱可以是一個入門導師,也不是專門負責網路開發的。所以在入門後,如果還要繼續深入研究雲網絡,甚至開始設計網路虛擬化方案的,還得靠你自己繼續修行。騷年,加油~

注:由於作者現階段主要專注於雲原生相關的業務(Kubernetes叢集),所以OpenStack網路資訊不就是最新的了。不過這個關係應該不大,因為其網路設計原理是繼承的。並且,咱們的課程,主要目的就是能看懂。要設計的話,還得自己再深入學習。So,本著能看懂OpenStack網路的原則,本文還是夠用的。

點選下方,第一時間瞭解華為雲新鮮技術~

華為雲部落格_大資料部落格_AI部落格_雲計算部落格_開發者中心-華為雲