數據驅動的網絡
從數據驅動的角度來看網絡,會發現一張現實中的網絡存在著各種數據。設計和管理一張網絡,主要是設計數據,存儲數據,管理數據和分析數據。網絡數據的規模、復雜度和變化速度,這3方面決定了數據處理的難度。對照下圖的SDN網絡結構,網絡數據按照用途可以分成下面幾類。
一個SDN VPC控制器,通常要管理成千上萬個虛擬交換機節點,其作用是存儲、計算和傳輸網絡數據。其中轉發數據是最重要的一類數據,直接決定了報文在網絡中的轉發行為。本文主要分析SDN控制器將轉發數據傳輸到虛擬機交換機的一些方法,希望從這個角度能介紹一下SDN網絡遇到的主要問題,以及如何設計一個SDN網絡控制器。
為了簡要描述,下文中的交換機,路由器和 偶爾會交替使用,他們都代表了具有路由功能的虛擬網絡轉發設備。
VPC 網絡轉發數據
云網絡內部根據數據面功能也分成多塊,本文主要介紹VPC網絡。下圖是一個VPC內的轉發數據。分別從控制器和虛擬交換機的視角來看,控制器內的轉發數據,和虛擬交換機內的轉發數據并不相同。控制器上是整個VPC1的轉發數據,而每個虛擬交換機內是本節點網卡相關的VPC轉發數據。
從控制器的視角看VPC1的轉發數據:VPC 1內有2個子網,子網1內有網卡1/2,子網2內有網卡3/4。
從虛擬交換機1的視角看VPC1內的轉發數據:
根據上面的例子,可以羅列一下VPC網轉發數據的幾個特點:
一個SDN VPC控制器,管理著成千上萬個虛擬交換機,以上面的例子為例,控制器需要將VPC1內的轉發數據,轉換成虛擬交換機期望的數據,并正確的傳輸到眾多虛擬交換機上。下面介紹控制器將轉發數據傳輸到虛擬交換機的3種方式,以及這3種方式下的數據一致性。
傳輸轉發數據
分布式系統,是通過分布式算法讓一群機器對外像一臺機器在工作。云網絡的特點,是通過分布式系統和網絡技術讓一群虛擬交換機邏輯上像一臺虛擬交換機在工作。
數據模型和格式
數據模型和格式,就是控制器將轉發數據以什么格式發送給虛擬交換機,例如json/xml/。
虛擬交換機的實現大多參考開源的,以協議和控制面交互轉發數據,以OVSDB和控制面交互管理信息。轉發數據以 Rule格式表示, Rule存儲在 Table中。控制面通過協議讀寫 Table,接收數據面上送的協議報文。協議支持數據面將一些流表更新事件和端口事件上報給控制面,類似于中斷通知。
如果控制面直接以協議傳輸轉發數據, Rule的表達是偏向轉發面的,沒法直接表示子網和路由表的關聯關系,以及網卡和安全組之間的關聯關系。另外為了表示控制面的一條路由,需要在rule中指定匹配條件和vxlan 的信息。當有多條路由數據指向同一條vxlan 時,會導致重復的vxlan 數據。例如下面,如果再新增一條路由,=192.168.1.30,=10.33.0.12,=1,那么這條數據會在轉發面重復存在。
ovs-ofctl add-flow br-tun "nw_dst=192.168.1.11 actions=set_field:10.33.0.12->tun_dst, set_field:1->tun_id, output:1
ovs-ofctl add-flow br-tun "nw_dst=192.168.1.12 actions=set_field:10.33.0.13->tun_dst, set_field:1->tun_id, output:1
ovs-ofctl add-flow br-tun "nw_dst=192.168.1.20 actions=set_field:10.44.0.24->tun_dst, set_field:1->tun_id, output:1
解決的辦法是,進一步對Open 的Table做拆分,獨立復用的數據。另外一些解決方案是控制器不直接對接虛擬交換機,不再直接發送原始的數據面轉發規則,而是引入一層proxy。控制器和proxy之間傳輸自定義格式的轉發數據,使用json或者,由proxy再翻譯成寫入虛擬交換機。
自定義的數據格式,對比表達上偏向控制器,可以減少控制器和虛擬交換機之間傳輸時的大量重復數據,也可以方便的自定義擴展。如下所示,如果使用自定義格式,只需要指定列出虛擬機和宿主機的IP地址列表,那么虛擬交換機可以將此翻譯成上面的 Rule,不存在重復的vxlan 。
hosts = vpcHosts {
vpcID = vpcxxxx,
vni = 1,
subnetID = subnetxxxx,
{

vmIP = "192.168.1.10/24",
hostIP = "10.22.0.16"
},
{
vmIP = "192.168.1.11/24",
hostIP = "10.33.0.12"
},
{
vmIP = "192.168.1.12/24"
hostIP = "10.33.0.13"
},
{
vmIP = "192.168.1.20/24"
hostIP = "10.44.0.24"

},
}
數據流
數據流是指控制器通過什么方式將轉發數據傳輸給虛擬交換機。目前有以下3種方式:
我們來具體分析使用上述3種方式實現控制面和數據面的數據同步。
via
使用數據庫來傳輸數據,需要清晰的定義數據在數據庫中的存儲的格式。一般是控制器來寫數據庫,虛擬交換機Agent來讀數據庫。數據庫的數據檢測到基于一致性的邏輯錯誤,表示的是轉發數據最新的狀態,沒有數據的歷史狀態。如果控制器出現錯誤,導致數據被篡改,一般要通過同時留存日志的方式,追溯出篡改的時間點和原始數據。同時要注意數據庫的事務,防止出現臟數據。
控制器需要和虛擬交換機Agent定義清楚數據庫轉發數據的版本,以及雙方軟件的版本,不然可能導致轉發面讀取數據庫出錯。一般這種情況是控制器在數據庫中添加了新字段,但是虛擬交換機Agent的版本還是舊的,此時無法提取新的字段,導致出現錯誤。
數據庫中的數據一般是持久化的,只要數據的寫入者不主動刪除數據,轉發數據就不會丟失,這樣即使數據面節點重啟了,還可以從數據庫中恢復出轉發面的狀態。
使用數據庫來傳輸數據,控制器和數據面是異步的,控制器寫入新數據到數據庫之后,數據庫無法通知數據面及時來讀取數據,導致新的轉發規則不能及時生效。但是現在出現了一些數據庫具備類似消息隊列的消息通知功能,數據面可以訂閱數據庫的某些消息來實現異步的通知,例如redis/etcd。但是使用數據庫模式,由于一般數據面Agent數目特別多,所以數據庫的讀性能以及并發連接數會是這個方案的一個瓶頸。
另外一種方式,是虛擬機交換機自帶數據庫,例如Open 自帶Open Flow Table,作用類似數據庫,報文轉發查找時會使用Table。控制面直接寫Open Flow Table,這種方式的好處在于轉發規則可以長久化,并且能立即生效,但是弊端在上一節已經提到,控制器需要關心Open Flow 規則的格式,維護的負擔過重,理解起來也比較困難,數據傳輸效率也不高。OVN控制器使用的就是這種方式。
via rpc
基于RPC的方式,控制器和每個數據面節點建立一對一的RPC連接。RPC通信模式下,一般有個服務端和客戶端,控制器和數據面都可以作為服務端。一般在數據面節點上會部署一個agent,用于和控制器之間建立RPC連接,由agent接收數據之后再寫入虛擬交換機中。
使用RPC,控制器和數據面agent之間的通信是同步的,控制器可以實時推送數據到數據面agent并確認數據面已經接收到數據。RPC的實現較為方便,只要定義好服務的接口和通信協議,控制器和數據面之間容易實現解耦,方便雙方獨立升級維護。
RPC一般是有通信方向的,例如客戶端主動訪問服務器端的服務,此時如果服務器想主動推送數據給客戶端,就很麻煩。grpc支持模式,但是也需要客戶端主動連接上來之后,以的形式再推送數據給客戶端,導致此時控制器無法基于具體的接口提供服務。
使用RPC的方式,Agent沒法很好的持久化保存轉發數據,因為控制器和數據面agent是通過網絡通信的,所以在一些數據消息丟失的情況下,Agent的狀態比較難排查。而且數據面agent重啟之后,為了快速恢復轉發狀態,必須做一次全量的數據同步。如果大量的agent在同一時刻重啟會對控制器會造成服務攻擊。解決辦法是可以在本地存儲對應的消息。但是這個消息需要有分布式算法來保證一致性。
agent需要負責轉發面Table中的數據正確性,必須確保所有數據正確的寫入轉發面的Table中。如果出現異常將導致網絡流量的中斷這對agent的設計要求比較高,盡量簡單和穩定,最好做到無狀態的。
via
控制器和數據面節點之間,可以使用消息隊列作為轉發數據的傳輸通道。消息隊列有生產者和消費者的角色。控制器作為生產者,往一個topic寫數據,數據面節點上的agent訂閱該topic,消息隊列會負責往所有訂閱該topic的數據面節點推送數據。控制器需要將轉發數據的類型劃分成不同的topic,并按照topic去發送數據。
消息隊列具備一對一和一對多通信的能力,容易實現控制器和數據面之間的解耦。控制器只需要將轉發數據寫入消息隊列后就不用管了,消息隊列自己會完成數據的傳輸工作。控制器可以方便的實現將同一份轉發數據,多播給多個數據面節點。
有些消息隊列支持消息的按序發送,但是轉發數據的順序只能在一個topic上保證,多個topic之間無法保證。消息隊列還支持消息的重傳。有些消息隊列支持消息的持久化保存,但是不能和數據庫比較,只是實現了有限的持久化功能。消息隊列支持消息的削峰功能,當轉發數據太多時,可以臨時緩存下來,避免系統過載。
消息隊列支持異步通信,消息隊列主動將消息或者事件及時的推送給數據轉發面。但是有一個問題,控制器將轉發數據寫入消息隊列之后,無法知道什么時候數據面收到了數據。解決辦法之一是數據面agent可以注冊一個topic,作為生產者將結果作為消息寫入消息隊列,控制器作為消費者來讀取結果。
消息總線是一種增量通信的機制,也就是說新轉發數據,總是以新消息的形式被追加到系統的消息流中,消息流也可以解讀為事件流。
目前VPC控制器一般以VPC和ENI作為topic,這樣每個虛擬交換機只需要訂閱自己關心的VPC topic,每次這個VPC的數據有更新,它都會收到新的消息,而不用關心別的VPC數據是否有更新,這樣可以減少重復數據的傳輸,減輕虛擬交換機的負擔。
via log
基于log的方式,結合了基于數據庫的數據可持久化功能,和rpc機制的實現。其實現方式可以抽象為,控制器將數據以遞增的方式追加log文件中,并附帶編號和數據的動作指令,例如是添加還是刪除一條數據。控制器負責將log文件同步到所有的數據面節點,并記錄每個數據面節點當前同步的位置,根據這個位置決定下一次同步的數據。如果數據面節點崩潰了,數據面節點可以使用本地快照恢復狀態,再根據log文件更新到最新狀態,并且再通過RPC和控制器同步自己最新數據的位置。控制器再同步最新的數據到數據面節點。所以控制器還需要定期和數據面節點sync本地快照。
轉發數據一致性
前面介紹了轉發數據的傳輸格式和傳輸方式,不同傳輸方式下實現數據一致性的方式和難度不一樣。
基于數據庫的實現方式,因為控制器將轉發數據直接寫入了數據庫中,所以數據轉發面節點可以直接讀取同樣最新的數據,這個數據一致性是由數據庫來保證的。關系型數據庫可以實現強一致性。這個場景下需要解決的問題主要是,控制器需要及時通知數據面節點來讀取數據,另外就是數據庫要承擔所有節點的讀寫請求,需要評估其性能。OVN控制器,使用基于數據庫的方式。
基于RPC的方式,控制器和數據面節點之間的狀態同步難以保證。需要依賴一些機制來實現數據的一致性。這個時候可以使用分布式共識算法,來保障控制器和數據面節點的狀態一致性,如下圖所示。控制器作為,agent作為。控制器控制保存每個數據面節點的同步狀態,控制數據面節點的同步,這個有點類似于via log的方式,每次同步的數據都有對應的編號。另外一種較為簡單的方式是使用版本號,但是這一般用于控制器和數據面節點之間同步全量數據。
基于消息隊列的方式,控制器和數據面節點之間的狀態同步依賴于消息隊列的消息持久化和重傳機制。這種事件驅動機制下,數據節點接收到的是增量數據,控制器無法直接知道數據面節點是否接收到數據。所以還依賴額外的機制來確保數據面節點和控制器之間數據的最終一致性,例如建立旁路的對賬檢測機制,定期檢查每個數據面節點的轉發數據是否和控制器的數據一致。為了做到數據面節點重啟快速恢復,數據面節點必須保存全量的轉發數據,否則重啟之后就只能接收新數據了。
解決方案探討
一個解決方案,是基于數據庫的改進模式,直接將一個虛擬交換機當成一個轉發設備,在控制器中對應每個轉發設備都有一個映射。控制器根據轉發數據模型和網絡事件,分別計算出每個轉發設備當前最新狀態檢測到基于一致性的邏輯錯誤,以及與歷史狀態比較的變更,然后再將變更增量寫入轉發設備的轉發表中。如果類比傳統路由器,控制器中的轉發設備數據可以類比CPU中的RIB和ARP Cache,而虛擬軟件交換機中的轉發設備數據,可以類比硬件交換芯片的轉發表項,在CPU中存在單獨的進程和交換芯片SDK來處理RIB和硬件交換芯片轉發表之間的同步。交換芯片SDK提供讀寫交換芯片的接口和通道,將CPU的讀寫格式翻譯成硬件交換芯片支持的格式,在各家交換芯片SDK之上通常還會有一個SDK適配層用來屏蔽各家SDK的差異。在SDN網絡中,協議起到的作用和交換芯片SDK類似,各種軟件交換機需要自己對協議做兼容。P4 是通過RPC的方式直接讀寫虛擬軟件交換機的轉發表,作用類似,區別在于P4的重點是想隨時可以改變交換機的解析和轉發行為,真正做到自定義交換機。傳輸通道和協議有了,控制器中的轉發設備數據有了,那么現在需要的就是在控制器這一側為每個轉發設備起一個單獨的線程,通過傳輸通道和協議將轉發數據寫入虛擬交換機的轉發表中。為了避免控制器維護過多連接,可以引入proxy。
在控制器中為每個虛擬交換機創建單獨的實例,該實例使用傳輸通道和傳輸協議和虛擬軟件交換機通信。虛擬交換機會發送一些網絡事件給控制器實例,例如虛擬交換機連接、添加一個虛擬機端口等。控制器綜合這些虛擬交換機上報的事件,以及來自上層的網絡配置信息,計算出每個虛擬交換機的當前轉發數據,然后和歷史數據比較得出差異數據。這個差異數據格式是控制器能夠識別的,再通過傳輸通道以及等傳輸協議轉換成虛擬機交換機支持的格式,寫入到虛擬交換機的轉發表中。由控制器實例來確認每次傳輸是否成功,如果失敗,需要重試來確保兩邊的一致性。為了支持控制器失聯時虛擬交換機仍然保持正常轉發,虛擬交換機支持fail-模式。
另一個解決方案,是基于rpc的改進模式。在控制器中對應每個轉發設備都有一個邏輯映射,控制器維護一份該轉發設備的邏輯數據。和上述模式的差別在于,控制器不再寫虛擬交換機的轉發表,而是在控制器和數據面Agent之間通過rpc同步邏輯數據,然后由Agent將邏輯數據翻譯成虛擬交換機支持的格式寫入轉發表中。在控制器和數據面Agent之間需要依賴分布式共識算法,來保證邏輯數據的同步。為了避免控制器維護過多連接,也可以引入proxy。這種方式和上面的方式對比,主要在于增加了一層Agent的緩存,相對復雜一些,帶來的好處是控制器不再關心底層虛擬交換機具體支持的格式。