1. 程式人生 > >Neutron的基本原理與程式碼實現

Neutron的基本原理與程式碼實現

分享正文
大家好,很高興今天能與大家分享一些Neutron的知識。今天分享的思路是:Openstack網路基礎、Neutron的軟體實現、Nova虛擬機器啟動時的網路處理以及OVS流表分析。

一、Openstack網路基礎

下面對Openstack和Neutron的介紹,要從幾個關鍵詞入手。

1. 三代網路

在網路這一口,OpenStack經歷了由nova-network到Quantum再到Neutron的演進過程。我們直觀地來看看三代網路的對比分析:

 

出現

版本

支援組

網模式

優點

缺點

適用場景

Nova-network 早期
  • Flat
  • Flat Dhcp
  • VLAN
  • 效能出色
  • 工作穩定
  • 支援multi-host部署

以實現HA

  • 網路管理不獨立
  • 功能不夠靈活
  • 組網方式受限
對效能和穩定性要求比較高;中小規模網路;網路運維成本有限;私有云環境
Quantum Folsom
  • Flat
  • Flat Dhcp
  • VLAN
  • Overlay
  • 獨立的網路管理
  • 支援大二層
  • 支援多廠商外掛
  • 缺乏HA機制
  • 各廠商外掛無法

共同執行

基本上已經都跟進到了Neutron
Neutron Havana
  • Flat
  • Flat Dhcp
  • VLAN
  • Overlay
  • 繼承了Quantum的優點
  • 功能上更為豐富
  • 網路相容性強
  • 開始引入SDN的思想
  • 程式碼結構複雜
  • 工作不夠穩定
  • HA機制仍缺乏大規模商用的檢驗
對功能要求比較多或希望向SDN演進;大規模網路或對可擴充套件性要求高;有專業的網路運維團隊;公有云環境
  • Nova-network是隸屬於nova專案的網路實現,它利用了linux-bridge(早期,目前也支援OVS)作為交換機,具備Flat、Flat DHCP、VLAN三種組網模式。優點是效能出色,工作穩定,支援multi-host部署以實現HA;缺點是網路模組不獨立,功能不夠靈活,組網模式也比較受限。
  • Quantum作為獨立的網路管理專案出現在F版本,除了linux-bridge外還支援OVS,以及以及其他商業公司的外掛,組網模式上增加了對GRE和VxLAN兩個Overlay技術的支援。優點是功能靈活,支援大二層組網;缺點是集中式的網路節點缺乏HA,而且各廠商外掛無法同時在底層網路中執行。
  • Neutron出現在H版本,由來是Quantum和一家公司的名稱衝突而改名。Neutron對Quantum的外掛機制進行了優化,將各個廠商L2外掛中獨立的資料庫實現提取出來,作為公共的ML2外掛儲存租戶的業務需求,使得廠商可以專注於L2裝置驅動的實現,而ML2作為總控可以協調多廠商L2裝置共同執行。Neutron繼承了Quantum對大二層的支援,還支援L2 PoP,DVR,VRRP,HA等關鍵功能,集成了很多L4-L7的網路服務,一些blueprint也正在積極開發中,如SFC等。優點是開始引入SDN思想,功能上更為豐富,網路相容性強;缺點是程式碼結構複雜,工作不夠穩定,HA機制仍缺乏大規模商用的檢驗。

從應用場景來看,Nova-network組網模式過於簡單,一些複雜的網路需求無法實現(比如兩個公司合併,有大量IP重合的VM要遷移到一個平臺,而且要求遷移後都要用原來的IP)。不過由於其簡單穩定的特點,仍適合於中小型企業的生產環境;Quantum的實際部署目前基本都跟進到了Neutron;Neutron的大二層組網,適合於雲端計算規模的生產環境,但是由於分散式和HA機制仍不夠成熟,因此目前多見於私有云和小規模共有云的部署,大規模的公有云仍然難以使用Neutron實現。

2. 四種組網模型

說完了基本特徵與應用場景,下面開始對上述提到的一些網路問題進行詳細的描述。我們拋開技術,結合圖例來抽象地看看不同的組網模型。當然,以下模型的實現不僅僅侷限於三張圖中的方式。

  • Flat模型最為簡單,所有的虛擬機器共用一個私有IP網段,IP地址在虛擬機器啟動時完成注入,虛擬機器間的通訊直接通過HyperVisor中的網橋轉發,公網流量在該網段的閘道器上進行NAT(Nova-network實現為開啟nova-network主機核心的iptables,Neutron實現為網路節點上的l3-agent)。Flat DHCP模型與Flat區別在於網橋中開啟了DHCP程序,虛擬機器通過DHCP訊息獲得IP地址(Nova-network實現為nova-network主機中的dnsmaq,Neutron實現為網路節點上的dhcp-agent)。

  • VLAN模型引入了多租戶機制,虛擬機器可以使用不同的私有IP網段,一個租戶可以擁有多個IP網段。虛擬機器IP通過DHCP訊息獲取IP地址(Nova-network實現為nova-network主機中的dnsmaq,Neutron實現為網路節點上的dhcp-agent)。網段內部虛擬機器間的通訊直接通過HyperVisor中的網橋轉發,同一租戶跨網段通訊通過閘道器路由,不同租戶通過閘道器上的ACL進行隔離,公網流量在該網段的閘道器上進行NAT(Nova-network實現為開啟nova-network主機核心的iptables,Neutron實現為網路節點上的l3-agent)。如果不同租戶邏輯上共用一個閘道器,則無法實現租戶間IP地址的複用。

  • Overlay模型(主要包括GRE和VxlAN隧道技術),相比於VLAN模型有以下改進。1)租戶數量從4K增加到16million;2)租戶內部通訊可以跨越任意IP網路,支援虛擬機器任意遷移;3)一般來說每個租戶邏輯上都有一個閘道器例項,IP地址可以在租戶間進行復用;4)能夠結合SDN技術對流量進行優化。

3. 三類節點和三類網路

看過抽象的組網模型,下面我們來介紹組網具體的實現技術。下面的介紹都是針對Neutron的,對nova-network和Quantum將不做討論。

  • 3類節點——管理節點:實現映象、塊儲存、身份認證、前端等服務,執行nova-compute的排程模組以及nova api-server;計算節點:實現nova-compute,以及neutron的各種agent(一般不包括l3-agent,DVR除外);網路節點,:實現neutron各種agent。注意,由於OpenStack為分散式架構實現,因此neutron-server既可以執行在控制節點,也可以執行在網路節點。
  • 3種網路——OpenStack內部模組之間的交互發生在管理網路,虛擬機器之間的通訊發生在資料網路,而External Network/API Network網路是連線外網的,無論是使用者呼叫Openstack API,還是虛擬機器與外網間的互通都需要經過這個網路。


目前OpenStack通常採用out-of-bound方式進行部署,管理網路與另外兩個網路是獨立的,管理節點上一般也不會承載Openstack的業務流量,下面的分析中網路只涉及資料網路與External Network/API Network網路,節點只涉及計算節點和網路節點。

4. 兩張圖例

有了以上知識作為基礎,就可以來分析Openstack中的網路通訊了。由於OpenStack中容器的通訊機制目前尚不成熟,並且有專門的專案Kuryr去實現容器相關網路技術,以下內容將不涉及OpenStack中的容器通訊。

以下將通過兩張圖來分析Neutron中的VLAN組網模型,HyperVisor中的網路裝置以OpenvSwitch為例。這三張圖中每一個資訊都是有用的,把這些資訊完全弄懂了,Neutron的組網也就能基本掌握了,Overlay模型與VLAN模型的區別只在於將圖中的br-eth1替換成br-tun即可,具體隧道如何進行封裝,稍後我們再詳細介紹。

第一張圖是計算節點上的網路實現。以虛擬機發出流量方向為例,從虛擬機器處開始分析:

1)流量經由虛擬機器IP核心交給虛擬網絡卡處理,虛擬網絡卡由TAP軟體實現,TAP允許使用者態程式向核心協議棧注入資料,它可以運行於虛擬機器作業系統之上,能夠提供與硬體乙太網卡完全相同的功能。

2)TAP裝置並不是直接連線到OVS上的,而是通過linux bridge中繼到ovs br-int上,其原因在於ovs無法實現linux bridge中一些帶狀態的iptables規則,而這些規則往往用於以虛擬機器為單位的安全組(security group)功能的實現。qbr是quantum bridge的縮寫,Neutron中沿用了Quantum的叫法。

3)linux bridge與ovs br int間的連線通過veth-pair技術實現,qvb代表quantum veth bridge,qvo代表quantum veth ovs。veth-pair用於連線兩個虛擬網路裝置,總是成對出現以模擬虛擬裝置間的資料收發,其原理是反轉通訊資料的方向,需要傳送的資料會被轉換成需要收到的資料重新送入核心網路層進行處理。veth-pair與tap的區別可以簡單理解為veth-pair是軟體模擬的網線,而tap是軟體模擬的網絡卡。

4)ovs br-int是計算節點本地的虛擬交換裝置,根據neutron-server中OVS Plugin的指導,完成流量在本地的處理:本地虛擬機器送入的流量被標記本地VLAN tag,送到本地虛擬機器的流量被去掉本地VLAN tag,本地虛擬機器間的2層流量直接在本地轉發,本地虛擬機器到遠端虛擬機器、閘道器的流量由int-br-eth1送到ovs br-eth1上(在Overlay模型中送到ovs br-tun上)。注意,無論是VLAN模型還是Overlay模型,由於br-int上VLAN數量的限制,計算節點本地最多支援4K的租戶。

5)ovs br-int與ovs br-eth1間的連線通過veth-pair技術實現。

6)ovs br-eth1將該計算節點與其他計算節點、網路節點連線起來,根據neutron-server中OVS Plugin的指導,完成流量送出、送入本地前的處理:根據底層物理網路租戶VLAN與本地租戶VLAN間的對映關係進行VLAN ID的轉換(Overlay模型中此處進行隧道封裝,並進行VNI與本地租戶VLAN ID間的對映)。由於底層物理網路中VLAN數量的限制,VLAN模型最多支援4K的租戶,而Overlay模型中,24位的VNI最多支援16million的租戶。

7)ovs br-eth1直接關聯物理宿主機的硬體網絡卡eth1,通過eth1將資料包送到物理網路中。Overlay模型中ovs br-tun通過TUN裝置對資料包進行外層隧道封裝並送到HyperVisor核心中,核心根據外層IP地址進行選路,從硬體網絡卡eth1將資料包送到物理網路中。TUN與TAP的實現機制類似,區別在於TAP工作在二層,而TUN工作在三層。

第二張圖是網路節點上的網路實現,以流量流入網路節點方向為例,從底層物理網路流量通過eth1進入ovs br-eth1(Overlay模型中為ovs br-tun)開始分析:

1)ovs br-eth1將網路節點與計算節點連線起來,根據neutron-server中OVS Plugin的指導,完成流量送入網路節點前的處理:根據底層物理網路租戶VLAN與本地租戶VLAN間的對映關係進行VLAN ID的轉換(Overlay模型中此處進行解封裝,並進行VNI與本地租戶VLAN ID間的對映)。注意,雖然同一租戶在底層物理網路上的VLAN ID(Overlay模型中為VNI)唯一,但是在網路節點與計算節點,不同計算節點中同一租戶對應的本地VLAN ID可能有所不同。另外由於網路節點也要在ovs br-int上使用本地VLAN,而租戶跨網段流量與公網流量都要經過網路節點,因此使用單個網路節點時,Neutron最多能支援4K租戶,可採用部署多個網路節點的方式來解決這一問題。

2)送入網路節點的流量,由ovs br-eth1(ovs br-tun)通過veth-pair送給ovs br-int,ovs br-int連線了本地不同的namespace,包括實現dhcp功能的dhcp-agent——dnsmasq,以及實現路由功能的l3-agent——router。Dnsmasq負責給對應租戶的虛擬機器分配IP地址,而router負責處理租戶內跨網段流量以及公網流量。不同的租戶有不同的dnsmasq和router例項,因此不同租戶間可以實現IP地址的複用。

3)Router namesapce通過qr介面(Quantum Router)接收到租戶內跨網段流量以及公網流量,在ns的IP核心中對跨網段流量進行路由,改寫MAC地址並通過相應的qr介面向ovs br-int送出資料包。在ns的IP核心中對公網流量進行NAT,並通過qg介面(Quantum Gateway)傳送給ovs br-ex。

4)Ovs br-ex通過關物理聯宿主機的硬體網絡卡eth1將流量送至Internet路由器。

5)上述兩幅圖中,ovs br-int與ovs br-ex間有直連,據說主要是防止l3-agent出現問題時能夠保證流量不中斷,但實際上看來很少出現此問題。

5. Neutron網路全家福


上圖是在網上看過的更加細緻,更為全面的一張圖(http://blog.csdn.net/canxinghen/article/details/46761591#comments),圖中清晰地展示了Neutron對多種L2技術(VLAN、VxLAN、GRE)共同執行的支援。圖中的mellonax是intel等硬體廠商搞出的具備轉發功能的網絡卡,能夠避免虛擬交換機帶來的資源消耗,並能夠加快轉發速率。一塊這樣的網絡卡能虛擬出63個VF,每個VF就好像一個獨立的物理網絡卡一樣,通過將VF直接掛到虛擬機器上,能夠實現轉發效能的大幅度提高。

以上介紹了OpenStack中網路元件的演進,以及Neutron組網的基本原理。下面我們將對Neutron的軟體實現進行簡單的介紹。

二、Nova虛擬機器啟動時的網路處理

裝置啟動了,網路有了,可是現在還沒有虛擬機器。下面我們來看看nova虛擬機器啟動時的網路處理過程。

從頭開始講。虛擬機器的啟動通常來自於控制節點命令列的nova boot,該命令被組裝成REST API送到nova-api。Nova-api與neutron-server乾的是一樣的活:接收REST請求,調nova-scheduler跑一些排程機制,計算出虛擬機器部署的位置,然後通過rpc與相應計算節點上的agent——nova-compute進行通訊,而啟動虛擬機器的實際工作由nova-compute完成。

當然,以上過程與網路並沒有發生什麼關係,這裡不做深入分析,大家要是有興趣可參考http://www.linuxqq.net/archives/1277.html

假定nova-compute已經通過rpc收到了開始幹活的命令,我們就從這裡開始漫長的程式碼分析。在此之前,先來看一看OpenStack元件層面的呼叫流程。這裡借用OpenStack大神SammyLiu的一張圖吧,圖中1-6步驟依次做了這麼幾件事:

  • Nova-compute向neutron-server請求虛擬機器對應的Port資源。
  • Neutron-server根據neutron-database生成Port資源。
  • Neutron-server通知Dhcp agent虛擬機器資訊。
  • Dhcp agent將虛擬機器資訊通知給dhcp server。
  • 虛擬機器接入並啟動。
  • 虛擬機器從dhcp server處獲得IP地址。


最後一步就是傳統的dhcp的互動過程,這裡就不講了,下面來看1-5的實現。時間有限,程式碼不再一步步回溯了,詳見SDNLAB“網路虛擬化”專題的後續文章,這裡給出程式碼的主體思路。

  • Nova-compute向neutron-server傳送create_port的REST API請求,生成新的Port資源。
  • Neutron-server收到該REST請求,通過APIRouter路由到ML2的create_port方法。該方法中,獲得了neutron-database新生成的Port,並通知ML2 Mechanism Driver該Port的生成。
  • Nova-compute向neutron傳送update_port的REST API請求,
  • Neutron-server收到該REST請求,通過APIRouter路由到ML2的update_port方法。該方法中,在neutron-database更新該Port的狀態,並根據ML2 Mechanism Driver的不同,決定後續的處理:若Mechanism Driver為hyperv/linuxbridge/ofagent/openvswitch,則需要通過ML2的update_port方法中執行rpc遠端呼叫update_port;對於其餘的Mechanism Driver,ML2的update_port方法呼叫其的update_port_postcommit方法進行處理,這些Mechanism Driver可能使用非rpc方式與自身的agent通訊(如REST API、Netconf等)。
  • ML2執行完update_port方法後,Port資源在wsgi中對應的Controller例項通過DhcpAgentNotifyAPI例項rpc通知給網路節點上的dhcp agent(也可能通過一些排程機制通知給分佈在計算節點上的dhcp agent)。
  • Dhcp agent收到該rpc通知,通過call_driver方法將虛擬機器MAC與IP的繫結關係傳遞給本地的DHCP守護程序Dnsmaq。
  • Nova-compute通過libvirt driver的spawn方法將虛擬機器接入網路,然後啟動虛擬機器。

到這裡,虛擬機器啟動過程中的網路處理就都結束了,虛擬機器間就可以開始通訊了。下面開始介紹Neutron中OVS的流表邏輯,看看OVS是怎麼支援虛擬機器間的通訊的。

三、Neutron的軟體實現

5. 5類Neutron元件

在架構設計上, Neutron沿用了OpenStack完全分散式的思想,各元件之間通過訊息機制進行通訊,使得Neutron中各個元件甚至各個程序都可以執行在任意的節點上,如下圖所示。這種微核心的架構使得開發者可以集中精力在網路業務的實現上。目前Neutron提供了眾多的外掛與驅動,基本上可以滿足各種部署的需要,如果這些還難以支撐實際所需的環境,則可以方便地在Neutron的框架下擴充套件外掛或驅動。

  • Neutron-server可以理解為一個專門用來接收Neutron REST API呼叫的伺服器,然後負責將不同的rest api分發到不同的neutron-plugin上。
  • Neutron-plugin可以理解為不同網路功能實現的入口,各個廠商可以開發自己的plugin。Neutron-plugin接收neutron-server分發過來的REST API,向neutron database完成一些資訊的註冊,然後將具體要執行的業務操作和引數通知給自身對應的neutron agent。
  • Neutron-agent可以直觀地理解為neutron-plugin在裝置上的代理,接收相應的neutron-plugin通知的業務操作和引數,並轉換為具體的裝置級操作,以指導裝置的動作。當裝置本地發生問題時,neutron-agent會將情況通知給neutron-plugin。
  • Neutron database,顧名思義就是Neutron的資料庫,一些業務相關的引數都存在這裡。
  • Network provider,即為實際執行功能的網路裝置,一般為虛擬交換機(OVS或者Linux Bridge)。

6 兩類Plugin

  • Core-plugin,Neutron中即為ML2(Modular Layer 2),負責管理L2的網路連線。ML2中主要包括network、subnet、port三類核心資源,對三類資源進行操作的REST API被neutron-server看作Core API,由Neutron原生支援。其中:
Network 代表一個隔離的二層網段,是為建立它的租戶而保留的一個廣播域。subnet和port始終被分配給某個特定的network。Network的型別包括Flat,VLAN,VxLAN,GRE等等。
Subnet 代表一個IPv4/v6的CIDR地址池,以及與其相關的配置,如閘道器、DNS等等,該subnet中的 VM 例項隨後會自動繼承該配置。Sunbet必須關聯一個network。
Port 代表虛擬交換機上的一個虛機交換埠。VM的網絡卡VIF連線 port 後,就會擁有 MAC 地址和 IP 地址。Port 的 IP 地址是從 subnet 地址池中分配的。
  • Service-plugin,即為除core-plugin以外其它的plugin,包括l3 router、firewall、loadbalancer、VPN、metering等等,主要實現L3-L7的網路服務。這些plugin要操作的資源比較豐富,對這些資源進行操作的REST API被neutron-server看作Extension API,需要廠家自行進行擴充套件。

最開始曾經提到,“Neutron對Quantum的外掛機制進行了優化,將各個廠商L2外掛中獨立的資料庫實現提取出來,作為公共的ML2外掛儲存租戶的業務需求,使得廠商可以專注於L2裝置驅動的實現,而ML2作為總控可以協調多廠商L2裝置共同執行”。在Quantum中,廠家都是開發各自的Service-plugin,不能相容而且開發重複度很高,於是在Neutron中就為設計了ML2機制,使得各廠家的L2外掛完全變成了可插拔的,方便了L2中network資源擴充套件與使用。

ML2作為L2的總控,其實現包括Type和Mechanism兩部分,每部分又分為Manager和Driver。Type指的是L2網路的型別(如Flat、VLAN、VxLAN等),與廠家實現無關。Mechanism則是各個廠家自己裝置機制的實現,如下圖所示。當然有ML2,對應的就可以有ML3,不過在Neutron中L3的實現只負責路由的功能,傳統路由器中的其他功能(如Firewalls、LB、VPN)都被獨立出來實現了,因此暫時還沒有看到對ML3的實際需求。

===================== 程式碼分析 =========================
一般而言,neutron-server和各neutron-plugin部署在控制節點或者網路節點上,而neutron agent則部署在網路節點上和計算節點上。我們先來簡單地分析控制端neutron-server和neutron-plugin的工作,然後再分析裝置端neutron-agent的工作。

具體的程式碼這次分享沒有時間講了,只能講個大致的輪廓和思路。有興趣深入研究的同志,可以關注SDNLAB上“網路虛擬化”專題的後續更新。

(注意,以前廠商開發的L2 plugin跟ML2都存在於neutron/plugins目錄下,而可插拔的ML2裝置驅動則存在於neutron/plugins/ml2/drivers目錄下)

1. 控制端的實現

從neutron-server的啟動開始說起。neutron-server的啟動入口在neutron.server.__init__中,主函式中主要就幹了兩件事,第一是下圖l 48處啟動wsgi伺服器監聽Neutron REST API,第二是在l 52啟動rpc服務,用於core plugin與agent間的通訊,兩類服務作為綠色執行緒併發執行。從SDN的角度來看,wsgi負責Neutron的北向介面,而Neutron的南向通訊機制主要依賴於rpc來實現(當然,不同廠家的plugin可能有其它的南向通訊機制)。

  • 北向方面,Neutron的wsgi通過Paste工具進行模板化部署,它接收Neutron REST API的業務請求,然後通過APIRouter將其分發給對應的plugin。
  • Neutron內部,plugin與資料庫互動,獲取業務的全域性引數,然後通過rpc機制將操作與引數傳給裝置上的Agent(某些plugin和ML2 Mechanism Driver通過別的方式與Agent通訊,比如REST API、NETCONF等)。
  • RPC機制就可以理解為Neutron的南向通訊機制,Neutron的RPC實現基於AMPQ模型,plugins和agents之間通常採用“釋出——訂閱”模式傳遞訊息,agents收到相應plugins的***NotifyApi後,會回撥裝置本地的***CallBack來操作裝置,完成業務的底層部署。

2. 裝置端的實現

控制端neutron-server通過wsgi接收北向REST API請求,neutron-plugin通過rpc與裝置端進行南向通訊。裝置端agent則向上通過rpc與控制端進行通訊,向下則直接在本地對網路裝置進行配置。Neutron-agent的實現很多,彼此之間也沒什麼共性的地方,下面選取比較具有代表性的ovs-neutron-agent的實現進行簡單的介紹。

Ovs-neutron-agent的啟動入口為/neutron/plugins/openvswitch/agent/ovs-neutron-agent.py中的main方法,其中負責幹活的兩行程式碼在l 1471和l 1476。L 1471例項化了OVSNeutronAgent類,負責在本地配置OVS,而l 1476則啟動了與控制端的rpc通訊。

OVSNeutronAgent的例項化過程中依次幹了6個工作:啟動ovs br-int網橋;啟動rpc;啟動ovs br-eth1;啟動ovs br-tun;例項化OVSSecurityGroupAgent;開始rpc輪詢與監聽。

rpc_loop做的工作主要就是輪詢一些狀態,根據這些狀態,進行相應的操作。比如一旦探測到本地的OVS重啟了(l 1295,l 1309),就重新建立本地的網橋(l 1294-1300),並重新新增port(l 1336);再比如一旦rpc監聽到update_port事件(l 1309),則在本地使能相應的port(l 1336)。

ovs-neutron-agent的啟動也就是這些工作了,啟動完畢後,便開始了與相應plugin(OVS Plugin或者OVS Mechanism Driver)的rpc通訊。

================= 程式碼分析 ====================

Neutron的軟體實現就簡單地介紹到這裡了,下一節我們來具體看看Neutron中各個OVS上的流表邏輯是怎樣的。

四、Neutron OVS上的流表分析

在具體介紹OVS的工作機制之前,大家要先理解OVS並不是Neutron網路實現的唯一選擇。
實際上,Neutron中底層網路的實現千差萬別:有的agent本地是真正處理資料流的網路裝置(OVS,Router,LoadBalancer等),而有的agent本地是SDN控制器(如ODL、ONOS、OpenContrail、NSX等)。上述Neutron底層網路的兩種模型示意如下。

第一種模型中Neutron相當於SDN控制器,plugin與agent間的通訊機制(如rpc)就相當於簡單的南向協議。第二種模型中Neutron作為SDN應用,將業務需求告知SDN控制器,SDN控制器再通過五花八門的南向協議遠端控制網路裝置。當然,第二種模型中也可以把Neutron看做超級控制器或者網路編排器,去完成OpenStack中網路業務的集中分發。

以下我們講的是第一種模型中OVS處理資料流的工作機制。後一種模型中,SDN控制器也可以通過OpenFlow或者OVSDB來控制OVS處理資料流,對此本節暫時不進行討論,後續也會有文章會詳細介紹ODL和ONOS等SDN控制器對Openstack的支援。

================== 分隔線 ======================

以Overlay組網模型對OVS的工作機制進行介紹,具體分為兩個角度:OVS實現L2的基本連線,OVS對連線機制的優化。

(一)L2基本連線的實現

復原一下通訊場景,其中的網路基礎請參考“OpenStack網路基礎”一小節。圖中某租戶有兩個網段,分別用橙紅色和藍色表示,網段間的互通要經過網路節點中的Router,網段內的通訊不需要經過網路節點中的Router。網段間的互通可分為3步:橙紅色網段通過網段內通訊找到Router,Router進行路由,Router通過藍色網段的網段內通訊轉發給目的地。Router上的路由是linux核心實現的,我們不去關心,因此可以說租戶內部通訊都是基於網段內通訊實現的。

Overlay模型中,網段內通訊涉及ovs br-int和ovs br-tun,計算節點和網路節點中兩類網橋的實現沒有什麼區別。概括地說,br-int負責在節點本地的網段內通訊,br-tun則負責節點間的網段內通訊。

在本節的場景內br-int實現為普通的二層交換機,即完成VLAN標籤的增刪和正常的二層自學習與轉發,沒有必要進行過多的解釋,其程式碼實現請參考“Neutron的軟體實現”中agent部分。

Br-tun採用多級流表實現節點間的網段內通訊,下面直接通過圖示來看br-tun中多級流表的設計。圖中流表的序號不是固定的,可在neutron.plugins.openvswitch.agent.common目錄下的constants.py檔案中修改。

所有流經br-tun的資料包首先進入Table 0進行處理。Table 0對資料包的來源進行判斷,從與br-int相連的patch-int進入的資料包交給Table 1處理,從GRE或者VxLAN埠(不同節點間的隧道有不同的Port_ID)進入的分別交給Table 2、Table 3處理。Table 1根據資料包目的MAC地址判斷是否為單播,是則送往Table 20,否則送往Table 21,Table 20根據(VLAN_ID,MAC)到(PORT_ID,TUNNEL_ID)的對映關係將單播包送到特定的隧道,Table 21將非單播包複製後送到所有隧道。進入Table 2或者Table 3的資料包,首先判斷TUNNE_ID是否合法,是則新增本地VLAN_ID並送往Table 10,否則丟棄。Table 10記錄資料包的VLAN_ID,MAC、入埠以及TUNNEL_ID,將(VLAN_ID,MAC)到(PORT_ID,TUNNEL_ID)的對映關係寫入Table 20,然後將資料包從與br-int相連的patch-int送出。

可見,上述過程就是標準MAC自學習在隧道中的擴充套件,無非就是將(VLAN_ID,MAC)到PORT_ID的對映變為了(VLAN_ID,MAC)到(PORT_ID,TUNNEL_ID)的對映。這種自學習仍然要依賴於泛洪來完成,引入l2_population或者SDN控制器後可以避免掉泛洪。

(二)連線機制的優化
OVS上,連線機制的優化主要體現在l2_population機制,以及對DVR(Distributed Virtual Router,分散式L3-agent)的支援。

2.1 L2_population

虛擬機器在通訊前,會發送ARP請求去解析目的MAC與目的IP間的對映關係,這一過程需要傳送二層的廣播包。由(一)中的介紹可知,這會導致隧道上的泛洪,這顯然是不能令人滿意的。

傳統網路中ARP依賴於廣播泛洪的原因在於沒有一個集中式的控制平面,而Neutron中的資料庫存有所有虛擬機器MAC地址與IP地址間的對映,可以說是一個天然原生的控制平面。因此有人提出了將該對映關係注入到OVS本地,在本地處理ARP廣播,以避免隧道上的泛洪,這就是l2_population。

L2_population的實現並不複雜,就是在1介紹的流水線中增加一個ARP Table去處理ARP Request。ARP Table中會事先存好MAC與IP的對映關係,如果ARP Table中匹配ARP Request訊息中的目的IP,則構造一個 ARP 響應包,從ARP Request的入埠返回給虛擬機器。如果匹配失敗,則跳轉到 Table 21繼續泛洪。上述過程如下圖所示,之所以保留ARP Table到Table 21的跳轉,主要是為了防止l2_population出現問題。

L2_population的工作就是這麼簡單,卻可以大大減少不合意的隧道泛洪。其實dhcp也存在類似的問題,如果只在網路節點上放置dhcp-server,那麼所有的DHCP DISCOVER訊息都要靠隧道泛洪傳送到網路節點上。當然,dhcp訊息的數量和產生頻率遠遠趕不上arp,問題也不會那麼明顯。

解決dhcp存在的上述問題,一種思路是在Table 21上專門寫一條高優先順序的dhcp流表項去匹配dhcp廣播訊息,並將所有的dhcp訊息都封裝送到網路節點的隧道。另外,也可以採用類似於l2_population的思路,從Table 1上專門寫一條高優先順序的dhcp流表項去匹配dhcp訊息,這條流表項只需要將dhcp訊息通過相應的埠轉交給dhcp namespace即可。之所以用namespace實現,是因為Dhcp訊息封裝在應用層,OpenFlow流表無法直接支援dhcp訊息的封裝,因此這個活得由分佈在計算節點上的dhcp namespace來完成。

第一種思路優點是實現簡單,但是一旦網路節點發生單點故障,虛擬機器便無法正常使用dhcp獲取IP,不過kilo版本中已經有人在多個網路節點中實現了dhcp_loadbalance(https://blueprints.launchpad.net/neutron/+spec/dhcpservice-loadbalancing)。第二種思路實現複雜一些,但能夠避免網路節點單點故障帶來的問題,實現分散式dhcp。

2.2 DVR

上一小節簡略地提到了分散式的dhcp,這個工作社群有人提過但是反響並不是很大,而分散式的路由(Distributed Virtual Routing)卻很早就成為了社群的共識,並在Juno版本中給出了實現。

Neutron中Router用來實現同一租戶不同網段的虛擬機器間的通訊,這屬於東西向流量,具體可以分為兩種:1. 同一個物理節點上不同網段內的虛機之間的通訊;2. 不同物理節點上不同網段內的虛機之間的通訊。Router還用來實現虛擬機器與Internet間的流量,這屬於南北向流量,具體也可分為兩種:1. 虛擬機器訪問Internet的流量,通常需要經過SNAT處理;2. Internet訪問虛擬機器的流量,可能需要經過DNAT處理。

在Neutron較早的版本中,上述流量都需要通過經過網路節點上的Router來處理,一旦網路節點故障或者網路節點上的Router掛掉了,上述型別的流量也就都丟掉了。解決這一問題也有很多種思路:

  • 一種是通過部署多個網路節點,在多個網路節點間做排程的,不過這種很難實現各個Router本身狀態的一致性。
  • 於是,就有了通過在Router間跑應用層面的VRRP來同步Router狀態,這種方式是很不錯的,VRRP協議也比較成熟。但是問題在於,大部分流量仍然需要“繞彎子”進行傳輸,如同一個物理節點上不同網段內的虛機之間的通訊可能需要到另一個物理節點的Router上處理。
  • 再於是,DVR就出現了,通過把Router分佈在各個計算節點中,各類流量都可以得到最優的處理,也不會再有單點故障的問題了。

接下來對DVR的講解發生在下圖的場景中:某租戶有紅、綠兩個網段,兩臺虛擬機器vm1、vm2分屬兩個網段,分別位於計算節點CN1、CN2,租戶擁有一個DVR路由器r1,分佈在兩個計算節點之上。假定vm1已經通過ARP獲得了CN 1中r1在紅色網段介面的MAC地址r1 red mac,現在vm1發起向vm2的ping request。


拋開流表的格式與下發的過程,先按照圖中序號來看一看DVR流表下發後通訊各個階段的資料包特徵。這裡規定(源MAC,目的MAC,源IP,目的IP地址)為資料包的特徵4元組。

1)vm1發出的ping包特徵為(vm1 mac, r1 red mac, vm1 ip, vm2 ip),該資料包送至br-int-cn1。

2)br-int-cn1在之前ARP過程中學到了r1 red mac所在埠,將ping包直接轉發給CN1中的r1。

3)r1進行路由,得知目的虛擬機器連線在綠色網段上,而且r1中存有目的虛擬機器的靜態ARP表項,不需要進行ARP解析。於是CN1中的r1通過其綠色網段介面將ping包重新送回br-int-cn1。此時ping包特徵為(r1 grn mac, vm2 mac, vm1 ip, vm2 ip),br-int-cn1還不知道vm2連在哪裡,進行泛洪。

4)br-tun-cn1由br-int-cn1收到ping包,將源mac地址修改為全域性唯一的dvr cn1 mac,並封裝好隧道,標記綠色網段的TUNNEL_ID,直接送往CN2。此時ping包被封裝在外層包頭內,其特徵為(dvr cn1 mac, vm2 mac, vm1 ip, vm2 ip)。

5)br-tun-cn2收到後去掉外層包頭,打上綠色網段的本地VLAN標籤,送給br-int-cn2,此時ping包特徵仍為(dvr cn1 mac, vm2 mac, vm1 ip, vm2 ip)。

6)br-int-cn2識別出這是CN1經過綠色網段送過來的流量,於是將源mac地址改回r1 grn mac並剝掉VLAN標籤。br-int-cn2還不知道vm2連在哪裡,就將ping包泛洪。此時ping包特徵為(r1 grn mac, vm2 mac, vm1 ip, vm2 ip)。

7)vm2收到ping request,回覆ping echo,反向的通訊過程和上述基本一致。

上述步驟給出了通訊的外在特徵,下面說明某些步驟內在的實現原理。
1)“r1中存有目的虛擬機器的靜態ARP表項”,是因為各個部署了DVR的計算節點中,l3-agent都事先從neutron資料庫中獲取了虛擬機器的網路資訊,直接注入到了r1中。這是為了防止r1跨隧道泛洪獲取vm2的MAC地址(可以通過l2_population來實現)。

2)“將源mac地址修改為全域性唯一的dvr cn1 mac”,是因為在所有計算節點上,r1位於相同網段的介面mac地址是一致的,即CN1上的r1 red/grn mac與CN2上的r1 red/grn mac一致。因此為了防止對端br-tun上的混亂, Neutron為每個部署了DVR的計算節點分配了全域性唯一的dvr mac地址,br-tun在進行隧道傳輸前都需要進行源MAC地址的改寫。

“並封裝好隧道,標記綠色網段的TUNNEL_ID,直接送往CN2”,DVR要求開啟l2_population事先學習(VLAN_ID,MAC)到(PORT_ID,TUNNEL_ID)的對映,以避免隧道上的泛洪。

3)br-tun-cn2解封裝後,判斷流量由dvr cn1送過來,不進行自學習,直接將流量送給br-int-cn2。

4)br-int-cn2中實現存有所有部署了DVR的計算節點的全域性唯一的MAC地址,因而可以識別dvr cn1送過來的流量,完成源MAC地址的回寫後進行轉發。

流表的邏輯跳轉圖如下所示(注意,某些Table的ID發生了變化,且未表示l2_population)。

Table 0對資料包的來源進行判斷,從與br-int相連的patch-int進入的資料包交給Table 1處理,從VxLAN埠(以VxLAN為例)進入的交給Table 4處理。Table 1判斷資料包是否為發向r1的ARP,或者其他發給r1的二層幀,如果是則丟棄(為了保證虛擬機器送到r1的資料包只在本地轉發)。如果Table 1判斷資料包是由r1發出來的,則將源mac地址改為CN1的dvr mac地址(為了避免對端br-tun上的混亂),然後送往Table 2。Table 2根據資料包目的MAC地址判斷是否為單播,是則送往Table 20,否則送往Table 21。Table 20根據(VLAN_ID,MAC)到(PORT_ID,TUNNEL_ID)的對映關係將單播包送到特定的隧道,該對映關係可事先通過L2_populaiton學習到,也可以通過Table 10的觸發學習到。Table 21將非單播包複製後送到所有隧道。進入Table4的資料包,首先判斷TUNNE_ID是否合法,是則新增本地VLAN_ID並送往Table 9,否則丟棄。Table 9判斷資料包源mac地址是否屬於dvr mac地址(由於示例場景比較簡單,圖中示例流表只匹配了CN2的dvr-cn2-mac),如果是直接送給br-int-cn1處理,否則轉給Table 10進行學習。Table 10記錄資料包的VLAN_ID,MAC以及TUNNEL_ID,將(VLAN_ID,MAC)到(PORT_ID,TUNNEL_ID)的對映關係寫入Table 20,然後從與br-int相連的patch-int送出。下面給出各個流表項的標註,其中紅色的為新增的DVR表項。

DVR對於南北向流量的處理有兩種模型,第一種是SNAT在節點本地完成,第二種是SNAT仍需要到網路節點進行,兩種模型分別示意如下。在節點本地進行SNAT則需要在計算節點的qr上為虛擬機器分配浮動IP地址,而在網路節點完成SNAT比較節省公網IP資源,具體選擇哪種模型,要視使用者實際的業務需求而定。


講到這裡,對Neutron OVS上的流表分析就結束了。當然,Neutron的學問遠遠不止這些,看看目前社群已經完成的或正在進行的專案吧(https://wiki.openstack.org/wiki/Neutron)。下一節將簡單地對kilo、liberty、mitaka版本中Neutron的blueprint進行整理,方便大家掌握社群的最新動態,將來能夠共同學習。

Q&A

Q1:能說下在opnfv中為何放棄了tap這一套機制麼?
A1:NFV對IO效能的要求很高,TAP是軟體實現的,效能上肯定會有問題。NFV現在傾向於硬體IO,如SRIOV,DPDK。

Q2:感覺tap這套機制僅僅是為了插入linux bridge,好利用iptable而已
A2:有可能吧,但NFV應該不太會想用軟的裝置做IO。

Q3:ovs-br1是ovs建立網橋嗎, ovs-br1是ovs建立網橋嗎
A3:這個是VLAN模型中,連線不同節點的網橋,宿主機的物理網絡卡直接被add上去了,overlay模型中,沒有br-eth1,換成了br-tun。

Q4:可以連線本地namespace,實現dhcp.是通過控制器中轉的嗎?
A4:在Neutron的基本實現中,dhcp不做特殊處理。在Neutron的基本實現中,dhcp不做特殊處理。

Q5:網橋是linux自創的?還是ovs建立的?
A5:網橋看你用什麼裝置了,如果是linux-bridge就是linux-bridge-agent通過linux命令自建,如果是ovs,就是openvswitch-agent在裝置本地通過vsctl建立的。

Q6:你這個external網路也是vlan模式對吧。--provider:network_type vlan 這個external網路支援vxlan嗎?我看他可以建立gre vxlan vlan flat。
A6:其實無所謂,extenal是另外一個segment,可以是VLAN也可以是別的。沒關係,支援。都可以,external與別的segment並無本質區別。

相關推薦

Neutron基本原理程式碼實現

分享正文 大家好,很高興今天能與大家分享一些Neutron的知識。今天分享的思路是:Openstack網路基礎、Neutron的軟體實現、Nova虛擬機器啟動時的網路處理以及OVS流表分析。 一、Openstack網路基礎 下面對Openstack和Neutr

常見排序演算法的基本原理程式碼實現和時間複雜度分析

  排序演算法無論是在實際應用還是在工作面試中,都扮演著十分重要的角色。最近剛好在學習演算法導論,所以在這裡對常見的一些排序演算法的基本原理、程式碼實現和時間複雜度分析做一些總結 ,也算是對自己知識的鞏固。 說明: 1.本文所有的結果均按照非降序排列; 2.本文所有的程式均用c++實現,

機器學習之AdaBoost原理程式碼實現

1 2.000000 1.000000 38.500000 66.000000 28.000000 3.000000 3.000000 0.000000 2.000000 5.000000 4.000000 4.000000 0.0

機器學習之KNN原理程式碼實現

                                      KNN原理與程式碼實現 KNN原理 KNN(k-Nearest Neighbour):K-近鄰演算法,主要思想可以歸結為一個成語:物以類聚 工作原理 給定一個訓練資料集,對新的輸入例項,在訓練資料集中找到與該例項最鄰近的 k (k

vysor原理程式碼實現

看過 vysor原理以及Android同屏方案 , 我突然想到整個過程應該如何驗證的問題。於是反編譯了vysor 最新的apk, 其中的程式碼邏輯依然具有很強的借鑑意義。其中通過 shell 環境下呼叫 adb 獲取截圖許可權成為了全篇的亮點所在。以下文字簡要地記錄了個人的理解過程,同時希

希爾排序原理程式碼實現c++

希爾排序是直接插入排序的一種,一般直接插入排序適用於基本有序的排序表和資料量不大的排序表。 希爾排序的原理是,先將待排序表分割成若干個步長為dk的子表,舉個例子 下面的無序排列 8 0 4 1 5 3 7 6 2 9 初始的時候dk設定為陣列長度的一半也就是5,那麼第

Spring裝配基本屬性的原理分析程式碼實現

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-ins

防盜鏈的基本原理實現

rec eal limit ole 站點 new exceptio stub text 1. 我的實現防盜鏈的做法,也是參考該位前輩的文章。基本原理就是就是一句話:通過判斷request請求頭的refer是否來源於本站。(當然請求頭是來自於客戶端的,是可偽造的,暫不在本文

機器學習系列文章:Apriori關聯規則分析演算法原理分析程式碼實現

1.關聯規則淺談     關聯規則(Association Rules)是反映一個事物與其他事物之間的相互依存性和關聯性,如果兩個或多個事物之間存在一定的關聯關係,那麼,其中一個事物就能通過其他事物預測到。關聯規則是資料探勘的一個重要技術,用於從大量資料中挖掘出有價值的資料

歸併排序演算法原理分析程式碼實現

  歸併排序是建立在歸併操作上的一種有效的排序演算法。該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用,歸併排序將兩個已排序的表合併成一個表。 歸併排序基本原理

YAML的Java實現——JYAML基本原理示例(1)匯出資料為YAML格式檔案

1. Overview JYAML是YAML的Java實現,YAML的全稱是YAML Ain't Markup Language,是否定遞迴定義,和LINUX的Linux Is Not UniX是一個意思。其結構之簡單,常常成為匯出或匯入配置檔案、資料結構等應用場景的常用A

SM2演算法第五篇:socket的基本原理實現

一、為什麼要用到socket? 我的畢設題目是要實現客戶端與伺服器之間的祕鑰協商,也就是說,我需要用到客戶端與伺服器之間通訊的相關知識,而客戶端與伺服器通訊用到的就是網路程式設計——socket。 二、socket簡要介紹 1、什麼是socket? socket是在應

YAML的Java實現——JYAML基本原理示例(3)YAML對檔案流的處理

請您先閱讀: 1. FileOutputStream 以流的方式,將資料寫入到YAML檔案中。 /* Output data structure into a YAML file as a

Android 圖片三級快取載入框架原理解析程式碼實現

本文主要介紹三級快取的原理解析與實現方式。以前一直覺得三級快取圖片載入是一個很難理解的東西,但是自己看了一下午再試著寫了一遍之後感覺還是隻要沉下心思考還時很容易熟悉掌握的。 所謂三級快取:首先是記憶體-檔案(外存)-網路三級快取機制。 首先: 框架需要一個接入方法NGIm

Coursera deeplearning.ai 深度學習筆記1-4-Deep Neural Networks-深度神經網路原理推導程式碼實現

在掌握了淺層神經網路演算法後,對深度神經網路進行學習。 1. 原理推導 1.1 深度神經網路表示 定義:L表示神經網路總層數,上標[l]代表第l層網路,n[l]代表第l層的節點數,a[l]

第五篇:樸素貝葉斯分類演算法原理分析程式碼實現

1 #==================================== 2 # 輸入: 3 # 空 4 # 輸出: 5 # postingList: 文件列表 6 # classVec: 分類標籤列表 7 #=

Android實現MP4邊下邊播(邊快取邊播放、線上播放)原理程式碼

QQ群交流:425219113(計算機語言交流) 邊下邊播方法初試 **剛開始實現這個的時候,我第一下想到的是:**先將MP4檔案單純的從位元組的層次分為若干個檔案,然後播放的時候,不斷從伺服器一邊下載,一邊追加到一個原始檔裡面,最後直接播放這個原始檔就可

YAML的Java實現——JYAML基本原理示例(2)匯入YAML格式檔案

1. 定義好的YAML檔案testYaml.yaml --- &0 !com.sinosuperman.yaml.Person age: 24 children: &2 !com

程式碼實現原理程式碼分析

閒來無事,好奇程式碼雨是怎麼實現的,早就聽說是利用連結串列,但自己卻想不出實現的思路,花了兩個晚上把程式碼看完了,分析都在程式碼裡,先看下效果吧。 在貼程式碼之前先簡單說下程式碼,方便讀者加深理解。 程式碼雨所用到的知識=簡單的windows api + C/C++的迴圈

fasttext原理複習程式碼實現

一:fasttext原理 fastText簡而言之,就是把文件中所有詞通過lookup table變成向量,取平均後直接用線性分類器得到分類結果。fastText和ACL-15上的deep averaging network [1] (DAN,如下圖)非常相似,區別就是