About me

Tuesday, 2 August 2016

[Linux][Ubuntu][RedHat] bonding and teaming

Link aggregation

網路聚合(Link Aggregation),在電腦網路領域這個名詞代表的是將多重網路介面NIC(Network interfaces)用並列的方式結合來增進網路流量,也可以提高其容錯能力。主要的方式是建立一個LAG(Link Aggregation Group),而這個LAG群組底下會有多個實體的埠(port),每個port都有辦法處理高流量的封包,所以將這些port都結合在一起的話,就可以增加很大的彈性。


在Link Aggregation這個名詞底下又有衍生其他相同類型的字眼,像是『port trunking』,『link bundling』『Ethernet/network/NIC bonding』,『NIC teaming』..等等。這些衍生的專有名詞通常都環繞著各個廠商的標準像是,在『IEEE 802.1AX』,『IEEE 802.1aq』或是之前的『IEEE802.3ad』裡對乙太網路定義的『Link Aggregation Control Protocol(LACP)』等等。

網路架構上可以在OSI的最低三層來實現Link Aggregation的功能:
  • Layer 1 (實體層): 包含了使用電源線(e.g. IEEE 1901)和無線網路(e.g. IEEE 802.11)裝置來結合多重頻寬。
  • Layer 2 (連接層): 通常聚合會發生在跨埠口(switch ports),不管是實體的port還是由作業系統所管理的虛擬port。
  • Layer 3 (網路層): 在這一層可以使用『round-robin scheduling』或是從封包標頭檔所算得的『hash 』雜湊值,當然你也可以結合這兩項。

不管以上選擇如何實做,這都會在所有連結之間來平衡所有的網路流量,而大部分的方法都提供很大的容錯能力。而每個聚合都可以在多個介面之間分享單一個邏輯位址(i.e. ip)或是一個實體位址(i.e. MAC 位址),也允許每個NIC擁有自己的位址。


在多數比較高階的裝置上,都有部分支援Link Aggregation,又或者是有軟體的實作,像是BSD的lagg package,Linux的 bonding driver和teaming driver,還有Solaris 的dladm aggr等等。





Linux Bonding and Teaming


在這篇文張裡面,主要是要介紹在Linux底下,要怎麼去實作Link Aggregation的功能,這邊挑了兩個目前主要的技術-『bonding』和『teaming』,主要也是透過將多個實體NIC分配到單一個邏輯網路,這樣可以增加網路的流通量和穩定性和讀取平衡。舉例來說,可以將兩個NIC「eth0」和「eth1」組成一個群組「group1」,然後分配一個IP給這個群組,這樣的話,你就有兩倍的流量了,又或者是你也可以設置成備用的用途,像是如果eth0壞掉了,這個群組會自動的改走「eth1」。

目前Ubuntu上的技術採用Bonding,而RedHat則是主打Teaming,目前比較起來,似乎是Teaming比較好,在Red Hat的官方網站上,有比較兩邊的差異,有興趣請參考→ here for a full list of the differences.


Bonding in Ubuntu





安裝

sudo apt-get install ifenslave

介面組態


Step 1: 確保Kernel支援

在Ubuntu可以將你的NIC綁訂成一個群組之前,你必須要先確保你的核心模組(kernel module)-『bonding』已經正確的啟動,並且在開機時已經被讀取了。

編輯你的組態檔『/etc/modules』:
sudo vim /etc/modules

確保『bonding』模組已經被讀取了,如果沒有的話,就請填入如下圖一樣吧:

Step 2: 設定NIC組態


首先確認你有兩個以上的NICs,像我的是『enp0s3』和『enp0s8』如下:


在來就是確保你的網路已經關掉了:
sudo systemctl stop networking

然後讀取bonding的核心模組:
sudo modprobe bonding

加下來就要來準備設定你的NICs了,
大致的步驟會如下:

1. 選擇哪幾個NICs你要加入到群組裡 - (假設是enp0s3和enp0s8)。
2. 如往常般設定這些NICs。
3. 將這些NICs加入群組 - (bond0) :
  • 3.1 手動設定
  • 3.2 加入name bond-master
4. 設定這個NIC群組,把它當成一般的NIC就好。
5. 在這個NIC群組裡面加入一些額外的參數 - (假設mode是active-backup)。

所以根據以上的情境,我們就是要將『enp0s3』和『enp0s8』這兩個NIC給綁定成群組『bond0』的兩個slaves,模式設定為active-backup,然後主要介面為『enp0s3』,並且給予bond0一組static的IP。

編輯你的檔案:
sudo vim /etc/network/interfaces

    
#enp0s3 is manually configured, and slave to the "bond0" bonded NIC 
auto enp0s3 
iface enp0s3 inet manual 
bond-master bond0 
bond-primary enp0s3

#enp0s8 ditto, thus creating a 2-link bond.
auto enp0s8
iface enp0s8 inet manual
bond-master bond0

#bond0 is the bonding NIC and can be used like any other normal NIC.
#bond0 is configured using static network information.
auto bond0
iface bond0 inet static
address 192.168.1.29
gateway 192.168.1.1
netmask 255.255.255.0
bond-mode active-backup
bond-miimon 100
bond-slaves none
    
          

如果你想要了解更多的選項,請參考『BondingModuleDocumentation

最後,啟動你的網路:
sudo systemctl start networking

檢查bonding介面

到這一步應該已經設定好了,也啟動我們的NIC群組了,就來檢查一下:


    
# cat /proc/net/bonding/bond0

Ethernet Channel Bonding Driver: v3.7.1 (April 27, 2011)

Bonding Mode: fault-tolerance (active-backup)
Primary Slave: enp0s3 (primary_reselect always)
Currently Active Slave: enp0s3
MII Status: up
MII Polling Interval (ms): 100
Up Delay (ms): 0
Down Delay (ms): 0

Slave Interface: enp0s3
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
Permanent HW addr: 08:00:27:1e:b6:9a

Slave queue ID: 0

    
    


開啟/關閉bonding介面

啟動介面bonding,請輸入:
ifup bond0

關閉介面,請輸入:
ifdown bond0


Ethernet Bonding模式

在bonding裡面有許多不同的模式可以選擇,就像是上面的例子,我們選用的方式是:
bond-mode active-backup

底下是各個模式的描述介紹

Mode 0
blance-rr
將傳輸(傳送/接收)的網路封包依序的從第一個到最後一個分配,這個模式提供了平衡讀取和容錯能力。

Mode 1
active-backup
這個模式之下只會啟動一個slave,只有在這個已經啟動的slave失敗的狀態之下才會去啟動其他的slave。簡單來說就是其他的slave都是備用。這個bond的MAC址在外部只會看得到一個port,以防止切換的混亂。在這個模式之下提供了很高的容錯能力。在這個模式底下你可以利用選項『primary』來設定你預設啟動的主要slave。

Mode 2
balance-xor
傳輸的方式使用可選擇性的雜湊(hashing)演算法,預設的方式是簡單的來源+目的 MAC位址演算法。而其他替代的傳輸方式可經由選項『xmit_hash_policy』來選擇,balance-xor同樣也提供讀取平衡和容錯。

Mode 3
booadcast
會傳輸到所有的slave介面,只提供容錯能力。

Mode 4
802.2ad
IEEE 802.3ad動態網路聚合(Dynamic link aggregation),建立了分享相同速度和雙工(duplex)設定的聚合群組,根據802.3ad規格在『aggregator』群組裡面建立slave。

要使用這個模式的話,需要兩個先決條件:
  • 需要有Ethtool,因為底層的驅動程式就需要用它來取得各個slave的速率和多工狀態。
  • 你的switch需要支援IEEE802.3ad動態網路聚合。通常大部份的switch都需要某種的設定才能開啟這個功能。

Mode 5
balance-tlb
這個模式採用『Adaptive transmit load balancing』,向外傳送會根據目前各個slave的的平均負載來分配。接收的話則只會由目前的slave。如果目前的接收slave出問題了,則其它的slave將會將目前這個失敗的slave的MAC位址拿來自己用,並且開始充當接收slave的角色。

使用這個模式不需要任何特殊的switch支援,但是需要有Ethtool,因為底層的驅動程式就需要用它來取得各個slave的速率。

Mode 6
balance-alb
這個模式採用『Adaptive load balancing』,其中對於IPV4的流量包含了balance-tlb和receive load balancing(rlb),並且也不需要特殊的switch支援。這部份的rlb是透過ARP協商所完成的。bonding的驅動程式會攔截由主機所送出的封包的ARP回應,並且將我們某個slave的獨特的硬體位址給複寫到封包的來源硬體位址上去。

Descriptions of balancing algorithm modes

平衡演算法(balancing algorithm)是由選項『xmit_hash_policy』來設定的。
主要的內容為:

layer2  - 使用MAC位址的XOR來產生雜湊表(hash)。這個演算法將會把所有的流量給放置到相同slave上的特定端點上。

layer2+3 - 使用MAC位址和IP位址的XOR來產生雜湊表(hash)。 這個演算法將會把所有的流量給放置到相同slave上的特定端點上。

layer3+4 - 主要利用上層協定的資訊來產生雜湊表。這個演算法可以允許到特定端點的流量跨到多重的slave上,雖然單一個連線不會跨到多重的slave身上。

encap2+3 -  這個演算法使用的跟layer2+3一樣,但是它主要用『skb_flow_dissect』來獲取標頭欄位(header field),而這個欄位將會在你使用encapsulation protocol時,帶入到內部的標頭檔裡。

encap3+4 - 這個演算法使用的跟layer3+4一樣,但是它主要用『skb_flow_dissect』來獲取標頭欄位(header field),而這個欄位將會在你使用encapsulation protocol時,帶入到內部的標頭檔裡。

這些演算法的預設值為layer2。這個選項在版本2.6.3時就被加入了。在更早期的bonding版本裡,這個參數根本不存在,因為只有layer2一個而已。而layer2+3則是在版本3.2.2被加入的。






Teaming in RedHat


安裝Teaming Daemon

[root@ ~]yum install teamd -y




使用nmcli設定teaming的組態

「nmcli」是一套Network Manager的cmd工具,首先我們可以藉由底下的指令來顯示我們有的NIC
[root@ ~]nmcli con show
如上圖所示,我要將「enp0s8」和「enp0s9」組成「team0」,指令如下
[root@ ~]nmcli con add type team con-name team0

在一次看一下NIC,你會發現多一個叫「team 0」的nm-team 裝置檔:

下個步驟,將「enp0s8」和「enp0s9」加到「team0」裡面:
    
[root@ ~]nmcli con add type team-slave inname enp0s8 master team0
[root@ ~]nmcli con add type team-slave inname enp0s9 master team0   
    
    
    


在顯示NIC,會多兩個team-slave:
底下也可以看到系統已經自動幫我們建立了相關的組態:
這些自動產生的組態一開始是使用「dhcp」,但是如果你想要將它改成static ip的話,有兩種方式,你可以自行修改組態檔,只是改完後記得執行「nmcli con reload」更新一下,又或者使用底下的nmcli的方式來修改:
    
    
[root@ ~]nmcli con mod team0 ipv4.method manual
[root@ ~]nmcli con mod team0 ipv4.addresses 192.168.1.2/24
[root@ ~]nmcli con mod team0 ipv4.gateway 192.168.1.254
    
    
    




啟用team

到這一步我們的設定檔都已經處理好了,接下來就是啟用team,首先必須將裡面的兩個team-slave啟動:
    
[root@ ~]nmcli connection up team-slave-enp0s8
[root@ ~]nmcli connection up team-slave-enp0s8    
    
    
    

然後你的「nm-team」就會自動啟動了,根據這篇文章,如果你只是單純的啟動「nm-team」,這樣是不會有用的,一定要啟動底下所有的slave才行。






修改team

像這樣把複數個NIC綁在一起,那網路流量是怎麼送的呢?像是下圖所顯示,預設team會使用robin runner:


而這個runner是可以改變的,底下是四個演算法:
  • roundrobin : 這個演算法會輪流依序的將網路封包送給各個NIC。
  • broadcase : 將所有的封包同時送到每個介面。
  • activebackup : 啟用一個介面,然後將其中另一個介面設定為backup,使用中的介面將會被監視,如果它出問題的話就會自動的切換到另一個備用的介面。
  • loadbalance : 這個選項會根據你所有可取得的NIC Tx流量去平均分配。


在建立team時,你就可以指定以上四種的runner : 
[root@ ~] nmcli con add type team con-name team0 config '{ "runner": {"name": "broadcast"}}' 

如果你已經建立起你的team了,也可以藉由修改組態檔來達成這個目的:
[root@ ~] vim /etc/sysconfig/network-scripts/ifcfg-team0
加入底下這一行
TEAM_CONFIG='{"runner": {"name": "activebackup"}, "link_watch": {"name": "ethtool"}}'
重啟介面
[root@ ~] systemctl restart network
檢查runner
[root@ ~] teamdctl nm-team state






進階文件

如果想要知道進階的資訊的話,可以看一下:
man 5 nmcli-examples #尋找關鍵字 "team"

也可以藉由底下指令來看一下debugging的資訊
teamnl nm-team options




其他設定teaming的方式

對於許多人來說,要設定teaming,要那麼多指令,還有很多細節,這是很麻煩的,所以現在有兩套GUI的工具可以來設定,有興趣的人請自行參閱:





Ref:

No comments:

Post a Comment