ボンディング(ちょっとまとめ)

LinuxのBonding。
最近、触る機会が無いっていうか。。。
なんですが、ちょっとモードをまとめてみます。



Bondingとは。
Linux の kernel 2.4.12以降で実装された、NICをチーミング(Teaming)する機能。(ketnel 2.4.18以降で標準で組み込まれています)
複数のNICを論理的に1つのNICと見なして束ねることで、耐障害性を向上したり、送受信のパフォーマンスを(分散処理することによって)上げる技術。

NICを束ねたものとして仮想のデバイスを使用します。通常NICは/dev/eth0、/dev/eth1、/dev/eth2・・・というデバイス名を使用しますが、束ねたあとの仮想デバイスは/dev/bond0、/dev/bond1、/dev/bond2・・・というデバイス名を使用します。





簡単な設定方法


/etc/modprode.confにbondドライバの設定を記述します。
alias bond0 bonding
options bond0 mode=0 miimon=100
alias --- bond0をbondingドライバと紐付け
options bond0 --- bond0の設定を記述する。
※ mode等は後述しますが、スイッチの設定が必要な場合があったり、耐障害性/性能向上のどちらに重きを置いているかなどで7つばかりモードがあります。 又、NICの障害検出の方法も、リンク状態を確認する方法(mii)と通信疎通を確認する方法(arp)がありますので、実際にはもっと細かく設定の チューニングが行われる必要があります。


Teamingに参加させるNICを設定します。
(例としてeth0とeth1の2枚のNICをbond0として束ねる設定を行います)


1枚目のNICの設定
/etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=static
ONBOOT=yes
MASTER=bond0
SLAVE=yes

2枚目のNICの設定
/etc/sysconfig/network-scripts/ifcfg-eth1
DEVICE=eth0
BOOTPROTO=static
ONBOOT=yes
MASTER=bond0
SLAVE=yes

そしてbond0の設定。
/etc/sysconfig/network-scripts/ifcfg-bond0
DEVICE=bond0
BOOTPROTO=static
BROADCAST=192.168.10.255
IPADDR=192.168.10.1
NETMASK=255.255.255.0
NETWORK=192.168.10.0
ONBOOT=yes

あとはnetworkサービスを再起動するか、メンドウであればシステム再起動によりbond0インターフェースが仕様されるようになり、bondingで動作します。




bondingのmodeについてはHPのホームページにうまくまとまっていたので転記。


bondingのモードについて

mode 名称 負荷分散 冗長性 異なる speed/duplex 設定の混在 primary 指定  Switch 機能  監視 モード slave MAC アドレス注2
送信 受信 MII ARP
0 balance-rr SW依存   ×注3 × Ether Channel A
全スレーブを順繰り(ラウンドロビン)に使ってパケットを送信。 送信のみ負荷分散。
1 active-backup × × 不要 A,C
1つのスレーブのみを active interfaceとしパケットを送信。 active interfaceに障害が発生した場合、他の backup slave を active interfaceに切り替え、冗長性を確保。
2 balance-xor   △注1 SW依存   ×注3 × Ether Channel A
送信元/先 MACアドレスを元に送信スレーブを決定しパケットを送信。 送信のみ負荷分散。
3 broadcast SW依存 不明 × 要(設定不明) A
全スレーブに同一パケットを送信。 このモードは通常の用途で使用されないので無視。
4 802.3ad   △注1 SW依存   △注4 × 802.3ad × A
IEEE 802.3ad(LACP)に準拠したリンクアグリゲーション。
5 balance-tlb SW依存 不要 × B
スレーブの負荷に応じて送信スレーブを決定しパケットを送信。 送信のみ負荷分散。
6 balance-alb 不要 × B
balance-tlbの機能に加え、受信も負荷分散。












注1: 負荷分散アルゴリズムが XORスタイルのためトラフィックが偏る場合がある
注2: A = Master Interface の MACアドレスが設定される




B = 受信スレーブが失敗した場合、別スレーブが失敗した受信スレーブの MACアドレスを引き継ぐ




C = fail_over_macが有効な場合、slave interface自身の MACアドレスが設定される
注3: Ether Channel の仕様により speed/duplex設定は同一でなければならない
注4: LACP によって同一設定 NIC がグルーピングされる


という事で、闇雲にmode=0を利用するのは正しく無さそうですね。
mode=0、mode=2は、要するにLACPやPAgPと言ったネゴシエイションを行わない(CiscoのCatalyst風に言えばmode onでChannel-Groupを作った状態)でイーサチャネルを作った状態。なので、原則として相手先もEtherChannelの設定が必要です ね。(行わなくとも動くのは動きますが、スイッチでブロードキャスト/マルチキャストのフラッディングが行われることを考えると高負荷時の動作は好ましく ありません)
mode=0とmode=2の違いは、パケット送信時の振り分けのアルゴリズムが異なり、mode=0がラウンドロビン(一般的なスイッチではパケットの 順序が入れ替わる可能性があるため、このアルゴリズムはあまり用いられない)、mode=2が送信元/送信先のMACアドレスを組にしたテーブル(ハッ シュテーブル)をキーにして負荷分散を行う方法(一般的なスイッチでのEtherChannelはこちらの動作を行う)。

mode=1についてはActive/Standbyでの動作になりますので、NICの高速化は行えませんが、高可用性だけを求めるのであれば、一番簡単な実現方法になります。

mode=3は全てのインターフェースに同一のパケットを送信する方法で、利用方法というか利用する局面がイマイチ想定できません。(誰が、どうやって使うのでしょうか?) 思いつくところでは、たとえば、L2/L3レベルが同時に切り替わるActive/Standby構成のL3スイッチ(ESRPとかGSRPとか)にサーバを直接収容する・・・とか、、、でしょうかね?

mode=4は802.3ad(LACP)に準拠したネゴシエイションを行うEtherChannel。当然、相手先のスイッチもLACPで動作させる必要があります。(でも、判りやすいですね)

mode=5は送信時に負荷分散を行う方法。(受信は1つのアクティブインターフェースが受け持ちます)

mode=6は送信時はmode=5と同様で、受信時は相手先のIPアドレスに応じて、受信するインターフェースを切り替える方法。(受信時も負荷分散される)


mode=0、2、4については受信時のロードバランスはNIC側では行わない。(接続先のスイッチの送信時の負荷分散アルゴリズムに依存する) MAC アドレスはMasterインターフェースのアドレスをチームの全てのアダプタが引き継ぐ。 ←この部分がスイッチにEtherChannelの設定が必要 になる理由になります。スイッチ側がEtherChannelではないポートをりようした場合にはフラッディングの発生要因になります。。。

mode=5、6についてはNICごとに異なるMACアドレスを使用します。 mode=6の場合は更に相手先のIPアドレスに応じて受信するARP応答で使用するインターフェースのMACアドレスを切り替えることで相手が送信時に 使用するMACアドレスを振り返ることで負荷分散します。


という事で、簡単にまとめました。。。



個人的にですが、かなり前(カーネル2.6.9前後)ですがmode=1、ARP監視で検証を行ったときに不具合と思われる動作に遭遇した経験があります。

・eth0、eth1をチーミングして動作させる。(eth0がActiveに) = 正常に通信できる
・eth0のNICからLANケーブルを取り外す(eth0がBackupに、eth1がMasterに) = 正常に通信できる
・eth0のNICにLANケーブルを再接続する(ステータスは変更無し) = 正常に通信できる
・eth1のNICからLANケーブルを取り外す(eth1がActiveのままeth0もBackupのまま) = 通信切断
・eth1を一度down状態に(ifconfig eth1 down等)してから、up状態に(ifconfig eth1 up等)すると何故か正常な状態になって通信も再開する

結局、原因は突き止められず・・・だったのですが、MII監視では問題無かったので、そのように設定した記憶が・・・。(悩ましいですがMII監視の場合、リンクアップしてるけど通信できないという障害は検出できないので、、、)



-------------追試しました-------------

Asianux 2 SP2 (kernel 2.6.9-AX47smp)
上記現象が再現します。

Ubuntu 9.04 (kernel 2.6.28-11)
上記現象は発生しません。

カーネルバージョンによるものなんでしょうかね?
他の2.6.9でも試してみたいところではありますが。



せっかくなのでUbuntu9.04(Debian系)での設定方法も記載します。
/etc/modprobe.confが無くなっているので・・・ちょっとあせりましたが。
RedHatEnterpriseも5から(CentOSも5から)、modprobe.dを利用して書く方法になっているようです。


ifenslaveパッケージをインストールします
$ sudo apt-get install ifenslave

/etc/modprobe.d/bonding.confを作成します。
alias bond0 bonding
options bond0 mode=1 arp_interval=1000 arp_ip_address=192.168.10.254 primary=eth0

NICの設定を行います。
/etc/network/interfaces
auto lo
iface lo inet loopback

auto bond0
        iface bond0 inet static
        address 192.168.10.11
        netmask 255.255.255.0
        network 192.168.10.0
        gateway 192.168.10.254
        post-up ifenslave bond0 eth0 eth1
        pre-down ifenslave -d bond0 eth0 eth1

設定ファイルの書き方がちょっと違うだけで内容は同じです。


確認するとこんな感じ。
$ cat /proc/net/bonding/bond0
Ethernet Channel Bonding Driver: v3.3.0 (June 10, 2008)

Bonding Mode: fault-tolerance (active-backup)
Primary Slave: eth0
Currently Active Slave: eth0
MII Status: up
MII Polling Interval (ms): 0
Up Delay (ms): 0
Down Delay (ms): 0
ARP Polling Interval (ms): 1000
ARP IP target/s (n.n.n.n form): 192.168.10.254

Slave Interface: eth0
MII Status: up
Link Failure Count: 2
Permanent HW addr: 00:ZZ:ZZ:ZZ:ZZ:ZZ

Slave Interface: eth1
MII Status: down
Link Failure Count: 2
Permanent HW addr: 00:XX:XX:XX:XX:XX