1. 程式人生 > >鏈路層的網絡卡聚合-基於Linux bonding

鏈路層的網絡卡聚合-基於Linux bonding

     如果有一個問題擺在眼前,那就是關於linux bonding有什麼比較好的資料,答案就是linux核心的文件,該文件在$KERNEL-ROOT/Documentation/networking/bonding.txt,我覺得沒有任何資料比這個更權威了。
一、bonding簡介 
bonding是一個linux kernel的driver,載入了它以後,linux支援將多個物理網絡卡捆綁成一個虛擬的bond網絡卡,隨著版本的升級,bond驅動可配置的引數越來越多,而且配置本身也越來越方便了。
     我們在很多地方會使用到物理網絡卡埠匯聚的功能,比如我們想提升網路速率,比如我們想提供熱備份,比如我們想把我們的主機配置成一個網橋,並且使之支援802.3ad動態埠聚合協議等等,然而最重要的還是兩點,第一點是負載均衡,第二點就是熱備份啦。
二、驅動以及Changes介紹
 

linux的bonding驅動的最初版本僅僅提供了基本的機制,而且需要在載入模組的時候指定配置引數,如果想更改配置引數,那麼必須重新載入bonding模組;然後modprobe支援一種rename的機制,也就是在modprobe的時候支援使用-o重新為此模組命名 ,這樣就可以實現一個模組以不同的配置引數載入多次了,起初比如我有4個網口,想把兩個配置成負載均衡,兩個配置成熱備,這隻能手工重新將bonding編譯成不同的名稱來解決,modprobe有了-o選項之後,就可以兩次載入相同的驅動了,比如可以使用:
modprobe bonding -o bond0 mode=0
modprobe bonding -o bond1 mode=1
 
載入兩次bonding驅動,用lsmod看一下,結果是bond0和bond1,並沒有bonding,這是由於modprobe載入時命名了,然而最終,這個命名機制不再被支援了,因為正如modprobe的man手冊所敘述的一樣,-o重新命名機制主要適用於test。最後,bonding支援了sysfs的配置機制,對/sys/class/net/目錄下的檔案進行讀或者寫就可以完成對驅動的配置。
     不管怎樣,在sysfs完全支援bonding配置之前,如果想往某一個bonding網絡卡新增裝置或者刪除裝置的時候,還是要使用經典且傳統的ioctl呼叫,因此必然需要一個使用者態程式與之對應,該程式就是ifenslave。
     我想,如果linux的所有關於裝置的配置都能統一於sysfs,所有的關於核心和程序配置統一於procfs(核心是所有程序共享的地址空間,也有自己的核心執行緒以及程序0,因此對核心的配置應該在procfs中),對所有的訊息,使用netlink通訊,這就太好了,擺脫了命令式的ioctl配置,檔案式(netlink使用的sendto之類的系統呼叫也可以歸為檔案系統呼叫相關的)的配置將更加高效,簡單以及好玩!
三、bonding配置引數
 

在核心文件中,列舉了許多bonding驅動的引數,然後本文不是文件的翻譯,因此不再翻譯文件和介紹和主題無關的引數,僅對比較重要的引數進行介紹,並且這些介紹也不是翻譯,而是一些建議或者心得。
ad_select: 802.3ad相關。如果不明白這個,那不要緊,拋開Linux的bonding驅動,直接去看802.3ad的規範就可以了。列舉這個選項說明linux bonding驅動完全支援了動態埠聚合協議。
arp_interval和arp_ip_target: 以一個固定的間隔向某些固定的地址傳送arp,以監控鏈路。有些配置下,需要使用arp來監控鏈路,因為這是一種三層的鏈路監控 ,使用網絡卡狀態或者鏈路層pdu監控只能監控到雙絞線兩端的介面 的健康情況,而監控不到到下一條路由器或者目的主機之間的全部鏈路的健康狀況。
primary: 表示優先權,順序排列,當出現某種選擇事件時,按照從前到後的順序選擇網口,比如802.3ad協議中的選擇行為。
fail_over_mac: 對於熱備模式是否使用同一個mac地址,如果不使用一個mac的話,就要完全依賴免費arp機制更新其它機器的arp快取了。比如,兩個有網絡卡,網絡卡1和網絡卡2處於熱備模式,網絡卡1的mac是mac1,網絡卡2的mac是mac2,網絡卡1一直是master,但是網絡卡1突然down掉了,此時需要網絡卡2接替,然而網絡卡2的mac地址與之前的網絡卡1不同,別的主機回覆資料包的時候還是使用網絡卡1的mac地址來回復的,由於mac1已經不在網路上了,這就會導致資料包將不會被任何網絡卡接收。因此網絡卡2接替了master的角色之後,最好有一個回撥事件,處理這個事件的時候,進行一次免費的arp廣播,廣播自己更換了mac地址。
lacp_rate: 傳送802.3ad的LACPDU,以便對端裝置自動獲取鏈路聚合的資訊。
max_bonds: 初始時建立bond裝置介面的數量,預設值是1。但是這個引數並不影響可以建立的最大的bond裝置數量。
use_carrier: 使用MII的ioctl還是使用驅動獲取保持的狀態,如果是前者的話需要自己呼叫mii的介面進行硬體檢測,而後者則是驅動自動進行硬體檢測(使用watchdog或者定時器),bonding驅動只是獲取結果,然而這依賴網絡卡驅動必須支援狀態檢測,如果不支援的話,網絡卡的狀態將一直是on。
mode: 這個引數最重要,配置以什麼模式執行,這個引數在bond裝置up狀態下是不能更改的,必須先down裝置(使用ifconfig bondX down)才可以配置,主要的有以下幾個:
1.balance-rr or 0: 輪轉方式的負載均衡模式,流量輪流在各個bondX的真實裝置之間分發。注意,一定要用狀態檢測機制,否則如果一個裝置down掉以後,由於沒有狀態檢測,該裝置將一直是up狀態,仍然接受傳送任務,這將會出現丟包。
2.active-backup or 1: 熱備模式。在比較高的版本中,免費arp會在切換時自動傳送,避免一些故障,比如fail_over_mac引數描述的故障。
3.balance-xor or 2: 我不知道既然bonding有了xmit_hash_policy這個引數,為何還要將之單獨設定成一種模式,在這個模式中,流量也是分發的,和輪轉負載不同的是,它使用源/目的mac地址為自變數通過xor|mod函式計算出到底將資料包分發到哪一個口。
4.broadcast or 3: 向所有的口廣播資料,這個模式很XX,但是容錯性很強大。
5.802.3ad or 4: 這個就不多說了,就是以802.3ad的方式執行。
...
xmit_hash_policy: 這個引數的重要性我認為僅次於mode引數,mode引數定義了分發模式 ,而這個引數定義了分發策略 ,文件上說這個引數用於mode2和mode4,我覺得還可以定義更為複雜的策略呢。
1.layer2: 使用二層幀頭作為計算分發出口的引數,這導致通過同一個閘道器的資料流將完全從一個埠傳送,為了更加細化分發策略,必須使用一些三層資訊,然而卻增加了計算開銷,天啊,一切都要權衡! 
2.layer2+3: 在1的基礎上增加了三層的ip報頭資訊,計算量增加了,然而負載卻更加均衡了,一個個主機到主機的資料流形成並且同一個流被分發到同一個埠,根據這個思想,如果要使負載更加均衡,我們在繼續增加代價的前提下可以拿到4層的資訊。
3.layer3+4: 這個還用多說嗎?可以形成一個個埠到埠的流,負載更加均衡。然而且慢! 事情還沒有結束,雖然策略上我們不想將同一個tcp流的傳輸處理並行化以避免re-order或者re-transmit,因為tcp本身就是一個序列協議,比如Intel的8257X系列網絡卡晶片都在儘量減少將一個tcp流的包分發到不同的cpu,同樣,埠聚合的環境下,同一個tcp流也應該使用本policy使用同一個埠傳送,但是不要忘記,tcp要經過ip,而ip是可能要分段的,分了段的ip資料報中直到其被重組(到達對端或者到達一個使用nat的裝置)都再也不能將之劃為某個tcp流了。ip是一個完全無連線的協議,它只關心按照本地的mtu進行分段而不管別的,這就導致很多時候我們使用layer3+4策略不會得到完全滿意的結果。可是事情又不是那麼嚴重,因為ip只是依照本地的mtu進行分段,而tcp是端到端的,它可以使用諸如mss以及mtu發現之類的機制配合滑動視窗機制最大限度減少ip分段,因此layer3+4策略,很OK!
miimon和arp: 使用miimon僅能檢測鏈路層的狀態,也就是鏈路層的端到端連線(即交換機某個口和與之直連的本地網絡卡口),然而交換機的上行口如果down掉了還是無法檢測到,因此必然需要網路層的狀態檢測,最簡單也是最直接的方式就是arp了,可以直接arp閘道器,如果定時器到期閘道器還沒有回覆arp reply,則認為鏈路不通了。