一個關於linux與java的學習筆記,當然還有作者自己的心情紀錄。

2011年7月26日星期二

NIC Bonding and IP Aliasing on Linux

IP Aliasing

IP aliasing是把多個IP關聯到同一張網卡的一種技術。一般的使用狀態下,一張網卡只需要一組IP位置,但是有許多時候我們為了安全性/管理方便,會希望一張網卡能有一個以上的IP,因此會使用IP aliasing。
假設主機原本的public IP為182.168.150.124/24,想要再額外指定一個private IP 192.168.150.124/24:
  • for Debian/Ubuntu/LinuxMint/B2D users:
  • 請注意在Linux底下控制網路有兩種方法:利用NetworkManager以及傳統ifup/ifdown的方式。在Debian系統的邏輯裡,如果有設定檔就會以設定檔為主,因此NetworkManager與ifup/ifdown的控制權不那麼明顯。但在Ubuntu的邏輯裡,一律都以NetworkManager來管理網路,系統並不會去讀取設定檔。由於在固定IP的環境裡,就沒有使用NetworkManager的必要,因此無論是Debian或是Ubuntu,我的建議都是停止這個daemon:
    /etc/init.d/network-manager stop
    chkconfig network-manager off
    如果是Debian的使用者可以再加上
    chkconfig networking on
    停止了惱人的network-manager之後,修改/etc/network/interfaces:
    # The loopback network interface
    auto lo eth0 eth0:1
    iface lo inet loopback
    
    iface eth0 inet static
    address 182.168.150.124
    netmask 255.255.255.0
    gateway 182.168.150.254
    
    iface eth0:1 inet static
    address 192.168.150.124
    netmask 255.255.255.0
    紅色字體是額外新增的部份。儲存後,重新啟動你的網路:
    /etc/init.d/networking restart
    想要新增更多個IP是可行的,只要繼續往下附加上新的位置即可。甚至主要IP以dhcp取得也行:
    # The loopback network interface
    auto lo eth0 eth0:1
    iface lo inet loopback
    
    iface eth0 inet dhcp
    #address 182.168.150.124
    #netmask 255.255.255.0
    #gateway 182.168.150.254
    
    iface eth0:1 inet static
    address 192.168.150.124
    netmask 255.255.255.0


  • for RHEL/CentOS/Fedora/SL/OracleLinux users:
  • 請先關閉NetworkMnager:
    service NetworkManager stop
    chkconfig --level 2345 NetworkManager off
    複製/etc/sysconfig/network-scripts/ifcfg-eth0為ifcfg-eth0:1並修改ifcfg-eth0:1為自己要alias的IP即可。原本的ifcfg-eth0大致如下:
    DEVICE="eth0"
    BOOTPROTO=static
    NM_CONTROLLED="no"
    ONBOOT="yes"
    IPADDR=182.168.150.124
    NETMASK=255.255.255.0
    GATEWAY=182.168.150.254
    修改過的ifcfg-eth0:1如下
    DEVICE="eth0:1"
    BOOTPROTO=static
    NM_CONTROLLED="no"
    ONBOOT="yes"
    IPADDR=192.168.150.124
    NETMASK=255.255.255.0
    GATEWAY=
    除了IP位置以及裝置名稱有變動之外,其餘均保持不變。儲存後,重新啟動你的網路:
    service network restart
    其中的NM_CONTROLLED變數即是決定是否交由NetworkManager來控制,由於我們已經關閉NM,這個項目僅明確表示不使用NM。Fedora使用者需注意:較新版本的Fedora一旦開啟NM,所有設定都不會寫進設定檔裡,即使寫了設定檔也是無效的,因此強烈建議啟用ip aliasing之前先關閉NM。如果想要新增更多個IP是可行的,只要複製ifcfg-eth0為範本並以:附加數字即可。


  • for SLES/SLED/OpenSuSE users:
  • 修改/etc/sysconfig/network/ifcfg-eth0:
    BOOTPROTO='static'
    ETHTOOL_OPTIONS=''
    IPADDR='182.168.150.124/24'
    MTU='1500'
    NAME='82540EM Gigabit Ethernet Controller'
    STARTMODE='auto'
    USERCONTROL='no'
    IPADDR1='192.168.150.124/24'
    請注意在SuSE系列裡所有路由方式都設定在/etc/sysconfig/network/routes裡。
    echo "default 182.168.150.254 - -" >> /etc/sysconfig/network/routes
    除了IP位置有變動之外,其餘均保持不變。儲存後,重新啟動你的網路:
    rcnetwork restart
    此處的USERCONTROL變數則是決定是否將此設定交由NetworkManager,因此可以不必關閉這個服務。想要新增更多個IP是可行的,只要繼續附加IPADDR變數即可。

由於第二個IP位置是供LAN使用,並無法route到WAN,因此不需要設定gateway。其實還有更加簡單的設定方法:
ip a add 192.168.150.124/24 dev eth0
ifconfig eth0 192.168.150.124 netmask 255.255.255.0
這樣就不用在乎每套distributions都有不同設定檔的問題了,只是重開機或重啟網路後設定又失效了,所以還是乖乖的寫設定檔吧。



NIC Bonding

NIC bonding,其真實意義是link aggregation,熟悉Cisco的人可能會比較接受trunking這個說法。白話而言就是把兩張(或以上)獨立的NIC關聯成同一個IP,與上面的IP aliasing剛好相反。不過這個觀念被許多廠商實作出來而成為業界標準,trunking的範圍可以實作在Layer1~4。

觀念上,每張NIC在bonding之後都稱之為slave,組合後的bond為master;對核心來說參與封包傳送的裝置不再是eth0,而是bond0。在Linux底下的NIC bonding共有七種模式,有些使用標準的IEEE 802.3,也採用IEEE的802.3ad/802.1ax的標準,也就是Link Aggregation Control Protocol(LACP)。Linux底下的NIC bonding實作在Layer 2(Data Link Layer),根據Linux Ethernet Bonding Driver HOWTO的說明,NIC bonding的七種模式如下:
ModeNameInterpretationLoad BalancingFault Tolerance
0Round-Robin
(balance-rr)
所有參與bonding的NIC輪流擔任封包的傳送,但同一時間只有一張NIC真正有作用。普通switch即可啟用。YESYES
1Active-Backup
(active-backup)
參與bonding的NIC只有一張有作用,其餘都處於備援狀態;當其中一張NIC失效後,另一張網卡(slave)才會取而代之。普通switch即可啟用。NOYES
2XOR
(balance-xor)
XOR算是mode0的進化版:當主機進行多個連線時,同一個NIC會負責同一個來源位置--也就是盡可能讓同一張NIC負責同一個位置越久越好。普通switch即可啟用。YESYES
3Broadcast
(broadcast)
封包以廣播的方式丟給所有的NIC,所有的NIC也同時接收/傳送所有封包。這個mode擁有最快速的的fault tolerance。普通switch即可啟用。NOYES
4IEEE 802.3ad Dynamic Link Aggregation (802.3ad)使用這個業界標準的模式擁有真正的outgoing/incoming balancing,只是不僅在linux主機上需要設定,還需要支援802.3ad/802.1ax的switch才行。YESYES
5Adaptive Transmit Load Balancing (balance-tlb)這個模式只有outgoing traffic擁有load balancing,incoming只有其中一張NIC負責。當負責incoming的那張NIC失效時,另一個slave才會負責incoming traffice。此模式常用於file/mail server。NOYES
6Adaptive Load Balancing
(balance-alb)
利用ARP協商達成每張NIC的incoming balancing--即balance tlb+incoming balancing。他不但是真正的outgoing/incoming balancing,也只要普通的switch就能達此要求。也是大部分中小企業主機所選擇的模式。YESYES

以下幾個重要的options,參考自Linux Ethernet Bonding Driver HOWTO

Bonding OptionsExpression
miimonMII的監控頻率(以millisecond為單位)。當其中一張NIC失效時,MII能多快發現並把工作交給下一張NIC。HOW-TO的建議值為100,預設值為0。
arp_intervalARP的監控頻率(以millisecond為單位)。功能相當於miimon,HOW-TO的建議值為100,預設值為0。設定此變數還必須設定arp_ip_target。
arp_ip_target指定ARP要監控的IP。此值必須在有指定arp_interval且該值>0才有意義。這個變數會以arp_interval指定的頻率發出請求至指定的位置以決定連線狀態是否正常。多個ip以,作分隔。
mode就是上表。指定mode可以寫數字或是簡稱,例如mode=4等同於mode=802.3ad。未指定時預設值為0(balance-rr)
downdelayMII監控下,從發現異常到關閉所需的時間(以millisecond為單位)。
updelayMII監控下,從發現恢復正常到啟用所需的時間(以millisecond為單位)。

本文預設使用mode=6(也可以寫作mode=balance-alb)來作為範例,假設你要bond eth0, eth1兩張NIC到182.168.150.124/24:

  • for Debian/Ubuntu/LinuxMint/B2D users:
    1. 安裝bonding介面卡管理程式:ifenslave
    2. aptitude install ifenslave chkconfig -y
    3. 修改/etc/modprobe.d/aliases.conf
    4. 新增下列幾行:
      alias bond0 bonding
      alias eth0 e1000
      alias eth1 e1000
      options bonding miimon=100 mode=6
      在一些比較早期的版本裡可能需要寫在/etc/modprobe.conf。
    5. 關閉NetworkManager並啟動bonding:
    6. 如果你是ubuntu系列的使用者,請務必移除network-manager。Ubuntu永遠都預設使用network-manager來管理網路,如果不移除他則你的設定永遠都無法生效。
      aptitude remove network-manager network-manager-gnome
      modprobe bond0 eth0 eth1
      如果你是debian系列的使用者,則不需移除network-manager,只要停用即可:
      invoke-rc.d network-manager stop
      chkconfig network-manager off
      chkconfig network on
      modprobe bond0 eth0 eth1
    7. 修改/etc/network/interfaces:
    8. # The loopback network interface
      #auto lo eth0 eth0:1
      #iface lo inet loopback
      
      #iface eth0 inet static
      #address 182.168.100.124
      #netmask 255.255.255.0
      #gateway 182.168.100.254
      
      #iface eth0:1 inet static
      #address 192.168.150.124
      #netmask 255.255.255.0
      
      #auto eth1
      #iface eth1 inet dhcp
             
      auto bond0
      iface bond0 inet static
      address 182.168.150.124
      netmask 255.255.255.0
      gateway 182.168.150.254
      dns-nameservers 182.158.150.1
      post-up ifenslave bond0 eth0 eth1
      pre-down ifenslave -d bond0 eth0 eth1
      需注意此時在interfaces裡都不可以出現任何關於eth0/eth1定義的entry,否則一定會啟動失敗。另外如果是早期的Ubuntu/Debian,其bond的設定可能如下:
      up ifenslave bond0 eth0 eth1
      down ifenslave -d bond0 eth0 eth1

      這幾行設定在Ubuntu/Debian也適用,詳細考古文章可以參考Ubuntu Bonding合併網卡-Debian and ubuntu with a 2.6 kernel
    9. 重新啟動網路服務:
    10. /etc/init.d/networking restart
      如果沒有錯誤訊息的話,使用ip a指令來查看一切是否設定正確:
      1: lo:  mtu 16436 qdisc noqueue state UNKNOWN 
          link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
          inet 127.0.0.1/8 scope host lo
          inet6 ::1/128 scope host 
             valid_lft forever preferred_lft forever
      2: eth0:  mtu 1500 qdisc pfifo_fast master bond0 state UP qlen 1000
          link/ether 08:00:27:cf:b4:63 brd ff:ff:ff:ff:ff:ff
      3: eth1:  mtu 1500 qdisc pfifo_fast master bond0 state UP qlen 1000
          link/ether 08:00:27:74:2e:35 brd ff:ff:ff:ff:ff:ff
      4: bond0:  mtu 1500 qdisc noqueue state UP 
          link/ether 08:00:27:cf:b4:63 brd ff:ff:ff:ff:ff:ff
          inet 182.168.150.124/24 brd 182.168.150.255 scope global bond0
          inet6 fe80::a00:27ff:fecf:b463/64 scope link 
             valid_lft forever preferred_lft forever
      5: pan0:  mtu 1500 qdisc noop state DOWN 
          link/ether 4e:dd:55:ad:83:6d brd ff:ff:ff:ff:ff:ff
      
      在Debian/Ubuntu系列的bonding並不會把所有網卡都統一MAC位置,但是bonding確實是成功的,可以查看bonding狀態:
      cat /proc/net/bonding/bond0
      看起來會是這個樣子:
      Ethernet Channel Bonding Driver: v3.5.0 (November 4, 2008)
      
      Bonding Mode: adaptive load balancing
      Primary Slave: None
      Currently Active Slave: eth0
      MII Status: up
      MII Polling Interval (ms): 100
      Up Delay (ms): 0
      Down Delay (ms): 0
      
      Slave Interface: eth0
      MII Status: up
      Link Failure Count: 0
      Permanent HW addr: 08:00:27:cf:b4:63
      
      Slave Interface: eth1
      MII Status: up
      Link Failure Count: 0
      Permanent HW addr: 08:00:27:74:2e:35
      不過Debian/Ubuntu的bonding並不能使用DHCP取得IP,這是我自己測試的結果;如果你知道如何在dhcp環境下使用bonding,麻煩告知筆者一聲!


  • for RHEL/CentOS/Fedora/SL/OracleLinux users:
    1. 修改/etc/modprobe.d/dist.conf
    2. 新增下列兩行:
      alias bond0 bonding
      options bond0 miimon=100 mode=6
      在一些比較早期的版本裡可能需要寫在/etc/modprobe.conf。
    3. 關閉NetworkManager並啟動bonding:
    4. service NetworkManager stop
      chkconfig --level 2345 NetworkManager off
      chkconfig network on
      modprobe bond0
    5. 修改/etc/sysconfig/network-scripts內的設定檔:
    6. 為了方便表示,ifcfg-eth0, ifcfg-eth1以及ifcfg-bond0分別如下表:
      ifcfg-eth0ifcfg-eth1ifcfg-bond0
      DEVICE=eth0
      BOOTPROTO=none
      ONBOOT=yes
      MASTER=bond0
      SLAVE=yes
      USERCTL=no
      DEVICE=eth1
      BOOTPROTO=none
      ONBOOT=yes
      MASTER=bond0
      SLAVE=yes
      USERCTL=no
      DEVICE=bond0
      BOOTPROTO=static
      ONBOOT=yes
      IPADDR=182.168.150.124
      NETMASK=255.255.255.0
      GATEWAY=182.168.150.254
      USERCTL=no
      由於是手動設定IP,別忘了把名稱伺服器的資訊加進去吧:
      echo "nameserver 182.168.150.1" >> /etc/resolv.conf
    7. 重新啟動網路服務:
    8. service network restart
      如果沒有錯誤訊息的話,使用ip a指令來查看一切是否設定正確:
      1: lo:  mtu 16436 qdisc noqueue state UNKNOWN 
          link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
          inet 127.0.0.1/8 scope host lo
          inet6 ::1/128 scope host 
             valid_lft forever preferred_lft forever
      2: eth0:  mtu 1500 qdisc pfifo_fast master bond0 state UP qlen 1000
          link/ether 08:00:27:5f:14:fa brd ff:ff:ff:ff:ff:ff
      3: eth1:  mtu 1500 qdisc pfifo_fast master bond0 state UP qlen 1000
          link/ether 08:00:27:5f:14:fa brd ff:ff:ff:ff:ff:ff
      4: sit0:  mtu 1480 qdisc noop state DOWN 
          link/sit 0.0.0.0 brd 0.0.0.0
      5: bond0:  mtu 1500 qdisc noqueue state UP 
          link/ether 08:00:27:5f:14:fa brd ff:ff:ff:ff:ff:ff
          inet 182.168.150.124/24 brd 182.168.150.255 scope global bond0
          inet6 fe80::a00:27ff:fe5f:14fa/64 scope link 
             valid_lft forever preferred_lft forever

      使用bond0未必只能用static ip。你可以把bond0當成一張正常的網卡來使用dhcp,像是這樣:
      DEVICE=bond0
      BOOTPROTO=dhcp
      ONBOOT=yes
      USERCTL=no

    9. 檢查bonding狀態:
    10. cat /proc/net/bonding/bond0
      Ethernet Channel Bonding Driver: v3.5.0 (November 4, 2008)
      
      Bonding Mode: adaptive load balancing
      Primary Slave: None
      Currently Active Slave: eth0
      MII Status: up
      MII Polling Interval (ms): 100
      Up Delay (ms): 0
      Down Delay (ms): 0
      
      Slave Interface: eth0
      MII Status: up
      Link Failure Count: 0
      Permanent HW addr: 08:00:27:ca:ca:69
  • for OpenSuSE 11.2 and later users:
    1. 修改/etc/sysconfig/network/內的設定檔:
    2. SLES/OpenSuSE已經具有bonding模組,不需要再額外設定(I love SuSE!)。新增ifcfg-bond0的空檔,其內容如下:
      ifcfg-eth0ifcfg-eth1ifcfg-bond0
      STARTMODE='off'
      BOOTPROTO='none'
      IPADDR=
      USERCONTROL='no'
      STARTMODE='off'
      BOOTPROTO='none'
      IPADDR=
      USERCONTROL='no'
      STARTMODE='onboot'
      BOOTPROTO='static'
      USERCONTROL='no'
      BONDING_MASTER=yes
      BONDING_SLAVE_1='eth0'
      BONDING_SLAVE_2='eth1'
      BONDING_MODULE_OPTS='mode=balance-alb miimon=100'
      IPADDR='182.168.150.124/24'
      
      SuSE系列的gateway統一設定在routing table裡:
      echo "default 182.168.150.254 - -" >> /etc/sysconfig/network/routes
    3. 重新啟動網路並檢查bonding狀態:
    4. rcnetwork restart
      cat /proc/net/bonding/bond0
      結果會像是這樣:
      Ethernet Channel Bonding Driver: v3.7.0 (June 2, 2010)
      
      Bonding Mode: adaptive load balancing
      Primary Slave: None
      Currently Active Slave: eth0
      MII Status: up
      MII Polling Interval (ms): 100
      Up Delay (ms): 0
      Down Delay (ms): 0
      
      Slave Interface: eth0
      MII Status: up
      Speed: 1000 Mbps
      Duplex: full
      Link Failure Count: 0
      Permanent HW addr: 08:00:27:df:86:2d
      Slave queue ID: 0
      
      Slave Interface: eth1
      MII Status: up
      Speed: 1000 Mbps
      Duplex: full
      Link Failure Count: 0
      Permanent HW addr: 08:00:27:83:11:83
      Slave queue ID: 0
      透過ip a指令看到的網路卡狀態會像是:
      1: lo:  mtu 16436 qdisc noqueue state UNKNOWN 
          link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
          inet 127.0.0.1/8 brd 127.255.255.255 scope host lo
          inet 127.0.0.2/8 brd 127.255.255.255 scope host secondary lo
          inet6 ::1/128 scope host 
             valid_lft forever preferred_lft forever
      2: eth0:  mtu 1500 qdisc pfifo_fast master bond0 state UP qlen 1000
          link/ether 08:00:27:df:86:2d brd ff:ff:ff:ff:ff:ff
      3: eth1:  mtu 1500 qdisc pfifo_fast master bond0 state UP qlen 1000
          link/ether 08:00:27:83:11:83 brd ff:ff:ff:ff:ff:ff
      6: bond0:  mtu 1500 qdisc noqueue state UP 
          link/ether 08:00:27:df:86:2d brd ff:ff:ff:ff:ff:ff
          inet 182.168.150.124/24 brd 182.168.150.255 scope global bond0
      想要用此bond0裝置在dhcp環境也是可行的,你的ifcfg-bond0可能如下:
      STARTMODE='onboot'
      #dhcp4=dhcp for ipv4
      BOOTPROTO='dhcp4'
      USERCONTROL='no'
      BONDING_MASTER=yes
      BONDING_SLAVE_1='eth0'
      BONDING_SLAVE_2='eth1'
      BONDING_MODULE_OPTS='mode=balance-alb miimon=100'

  • for SLES/SLED/OpenSuSE 11.1 and before users:
    1. 修改/etc/sysconfig/network/內的設定檔:
    2. SLES以及早期的OpenSuSE使用相當嚴謹的命名方式:
      ifcfg-eth-id-MAC_Address
      以筆者自己的設定檔為例:
      ifcfg-eth-id-08:00:27:df:86:2difcfg-eth-id-08:00:27:83:11:83ifcfg-bond0
      BOOTPROTO='none'
      BROADCAST=''
      ETHTOOL_OPTIONS=''
      IPADDR=''
      MTU=''
      NAME='82540EM Gigabit Ethernet Controller'
      NETMASK=''
      NETWORK=''
      REMOTE_IPADDR=''
      STARTODE='off'
      UNIQUE='rBUF.+XOL8ZCSAQC'
      _nm_name='bus-pci-0000:00:03.0'
      ETHTOOL_OPTIONS=''
      BOOTPROTO='none'
      BROADCAST=''
      ETHTOOL_OPTIONS=''
      IPADDR=''
      MTU=''
      NAME='82540EM Gigabit Ethernet Controller'
      NETMASK=''
      NETWORK=''
      REMOTE_IPADDR=''
      STARTODE='off'
      UNIQUE='rBCF.+ZOK5ZCSUJD'
      _nm_name='bus-pci-0000:00:08.0'
      ETHTOOL_OPTIONS=''
      STARTMODE=’onboot’
      BOOTPROTO='static'
      IPADDR=’182.168.150.124/24′
      USERCONTROL='no'
      BONDING_MASTER=’yes’
      BONDING_MODULE_OPTS=’mode=6 miimon=100′
      BONDING_SLAVE0=’bus-pci-0000:00:03.0′
      BONDING_SLAVE1=’bus-pci-0000:00:08.0′
      當然BONDING_SLAVE0可以指定成eth0/eth1,也可以在dhcp環境內使用bond0。NIC的bus-pci編號可以就藉由
      lspci | grep Ethernet
      來確認。SuSE系列的gateway統一設定在routing table裡:
      echo "default 182.168.150.254 - -" >> /etc/sysconfig/network/routes
    3. 別忘了重新啟動網路:
    4. rcnetwork restart
      Shutting down network interfaces:
          bond0     is still used from interfaces   eth0 eth1
          eth0      device: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 02)
          eth1      device: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 02)
          bond0     now going down itself
          bond0     
          bond0                                                                            done
          eth0      device: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 02)
          eth0                                                                             done
          eth1      device: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 02)
          eth1                                                                             done
      Shutting down service network  .  .  .  .  .  .  .  .  .                             done
      Setting up network interfaces:
          eth0      device: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 02)
          eth0      Startmode is 'off'
          eth0                                                                             skipped
          eth1      device: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 02)
          eth1      Startmode is 'off'
          eth1                                                                             skipped
          bond0     
          bond0     enslaved interface: eth0
          bond0     enslaved interface: eth1
          bond0     Starting DHCP4 client. . .  
          bond0     IP address: 182.168.150.124/24
          bond0                                                                            done
      Setting up service network  .  .  .  .  .  .  .  .  .  .                             done

附註:

  1. 如果你使用虛擬機器新增網卡,你的網卡編號可能會一直爆增。想要修改網卡編號可以修改這個檔案:
  2. /etc/udev/rules.d/70-persistent-net.rules
  3. 撰寫options時,必須要指定『miimon』或『arp_interval與arp_ip_target』
  4. 這兩者是options必要的欄位,雖然他們有預設值,但你仍然必須賦值才能使bonding生效。
  5. updelay與downdelay只有在指定miimon才有效:
  6. updelay/downdelay是MII程式所需要的變數,如果你使用的是arp_interval+arp_ip_target這組options,則是無效的。
  7. 更多靈活運用:
  8. -- 若你的主機跟switch狀況許可,你可以做許多個bonding來玩,每個bonding可以有不同數量的NIC/mode。
    -- 如果你還是有IP Aliasing的需求,可以在bonding之後繼續做IP aliasing。
    -- bonding後還可以搭配VLAN,這樣下去根本玩不完...Advanced Configuration for bonding and teaming with vlans

參考文章:

0 意見: