背景 — Network Bondingが必要な理由
話は金曜日の深夜2時から始まる。データベースサーバーが突然ネットワーク接続を失った。アラートが画面を埋め尽くし、データベースが復旧しなければ翌朝50人以上の社員が仕事できなくなる状況だった。サーバールームに駆け込んで確認すると、NICが故障していることが判明した——サーバーをスイッチに接続していた唯一のカードだ。
あの瞬間、なぜnetwork bondingが存在するのかを初めて本当に理解した。
Network bonding(NIC teamingまたはlink aggregationとも呼ばれる)は、複数の物理NICを一つの論理インターフェースにまとめる技術だ。主なメリットは以下の通り:
- 自動フェイルオーバー:一方のカードが死んでも、もう一方がすぐに引き継ぐ——ダウンタイムなし
- 負荷分散:複数の回線にトラフィックを分散させる
- 帯域幅の向上:1Gbps×2枚 → モードによっては2Gbps aggregatedに到達可能
Linuxは7つのbondingモードをサポートしているが、実際に主に使うのは以下の2つだ:
- mode 1(active-backup):1枚のカードのみactiveで、残りはstandby。シンプルで特別なスイッチ不要——productionのデフォルト選択肢
- mode 4(802.3ad/LACP):LACPに対応したスイッチが必要だが、帯域幅を実質的に増加できる——高いスループットが必要なdatabase/storageサーバー向け
インストール
Ubuntu 20.04以降はbondingドライバーがカーネルにバンドルされている。ロードされているか確認:
modprobe bonding
lsmod | grep bonding
出力が空の場合は、手動でモジュールをロードしてブート時の自動ロードを設定する:
echo "bonding" >> /etc/modules
modinfo bonding
Ubuntu 18.04以前は追加でifenslaveをインストールする:
apt-get install ifenslave -y
CentOS/RHEL 8以降は追加作業不要——ドライバーはカーネルに内蔵されており、nmcliで設定するだけだ。
詳細設定
方法1:netplanを使う(Ubuntu 20.04+)
現在のUbuntuサーバーでよく使う方法だ。まず既存の設定ファイルを確認する:
ls /etc/netplan/
# 通常は: 00-installer-config.yaml または 01-netcfg.yaml
変更前に古いファイルをバックアップする:
cp /etc/netplan/00-installer-config.yaml /etc/netplan/00-installer-config.yaml.bak
active-backup bondingの完全な設定ファイル:
# /etc/netplan/00-installer-config.yaml
network:
version: 2
renderer: networkd
ethernets:
eth0:
dhcp4: false
dhcp6: false
eth1:
dhcp4: false
dhcp6: false
bonds:
bond0:
interfaces: [eth0, eth1]
addresses: [192.168.1.100/24]
gateway4: 192.168.1.1
nameservers:
addresses: [8.8.8.8, 1.1.1.1]
parameters:
mode: active-backup
primary: eth0
mii-monitor-interval: 100
注目すべき点がある:mii-monitor-interval: 100はカーネルがカードの状態を確認する間隔(ms)だ。以前200msに設定したとき、フェイルオーバーが明らかに遅くなるのを感じた——100msがproduction環境での適切な閾値だ。
設定を適用する——リモートサーバーで作業する場合は必ずnetplan tryを先に実行すること:
netplan try # 120秒間テスト、接続が失われた場合は自動ロールバック
netplan apply # 恒久的な適用を確定
netplan tryのステップを省略したせいで、productionサーバーから自分自身を締め出しそうになったことがある。絶対に省略しないこと。
802.3ad(LACP)モードの設定——実質的な帯域幅向上
スイッチ側でLACPを有効にしたport-channel/LAGを先に作成する必要がある。その後、netplanファイルのparametersセクションを変更する:
bonds:
bond0:
interfaces: [eth0, eth1]
addresses: [192.168.1.100/24]
gateway4: 192.168.1.1
parameters:
mode: 802.3ad
lacp-rate: fast
transmit-hash-policy: layer3+4
mii-monitor-interval: 100
transmit-hash-policy: layer3+4はIPとポートの両方を使ってトラフィックをハッシュする——MACのみでハッシュするデフォルトのlayer2より均等に負荷分散できる。
方法2:nmcliを使う(CentOS/RHEL/Rocky Linux)
# bond interfaceを作成
nmcli connection add type bond \
con-name bond0 \
ifname bond0 \
bond.options "mode=active-backup,miimon=100"
# eth0とeth1をslaveとして追加
nmcli connection add type ethernet \
con-name bond0-slave-eth0 \
ifname eth0 \
master bond0
nmcli connection add type ethernet \
con-name bond0-slave-eth1 \
ifname eth1 \
master bond0
# bond0に静的IPを割り当て
nmcli connection modify bond0 \
ipv4.addresses "192.168.1.100/24" \
ipv4.gateway "192.168.1.1" \
ipv4.dns "8.8.8.8,1.1.1.1" \
ipv4.method manual
# 有効化
nmcli connection up bond0
適用後に接続が確立されたことを確認する:
nmcli connection show
nmcli device status
確認とモニタリング
カーネルからbonding状態を読み取る
カーネルは/proc/net/bonding/bond0を通じてbondingの全状態を公開している——デバッグ時に最初に確認すべき場所だ:
cat /proc/net/bonding/bond0
両方のカードが正常な場合の出力:
Bonding Mode: fault-tolerance (active-backup)
Primary Slave: eth0 (primary_reselect failure)
Currently Active Slave: eth0
MII Status: up
MII Polling Interval (ms): 100
Slave Interface: eth0
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
Slave Interface: eth1
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
両方のslaveでMII Status: upが表示され、Currently Active SlaveがプライマリカードになっていればOKのサインだ。Link Failure Countを監視して断続的な障害を検出しよう——この数値が増え続けているのは、まだダウンしていなくてもカードが故障しかけているサインだ。
実際のフェイルオーバーテスト——絶対に省略できないステップ
設定が完了してもフェイルオーバーをテストしないのは、bondingがないのと同じだ。2つのターミナルを開く:
# ターミナル1: ゲートウェイへの継続的なping
ping -i 0.2 192.168.1.1
# ターミナル2: ハードウェア障害をシミュレートするためにactiveカードをシャットダウン
ip link set eth0 down
# ターミナル1を観察する——理想的にはpacket lossなし
# 1〜2パケットのドロップは正常、5パケット以上のドロップはmii-monitor-intervalを見直す必要あり
# テスト後に元に戻す
ip link set eth0 up
mii-monitor-interval: 100msの場合、フェイルオーバーは通常200〜300ms以内に発生する——TCP接続がリセットされないほど十分に速い。
リアルタイムモニタリングと便利なコマンド
# 状態を継続的に監視
watch -n 1 'cat /proc/net/bonding/bond0 | grep -E "Currently Active|MII Status|Link Failure"'
# 各カードの速度と物理的な状態を確認
ethtool eth0 | grep -E "Speed|Duplex|Link detected"
ethtool eth1 | grep -E "Speed|Duplex|Link detected"
# インターフェースごとのTX/RXバイト統計(トラフィック分散を確認)
ip -s link show eth0
ip -s link show eth1
# フェイルオーバーイベント発生時のカーネルログを確認
journalctl -k | grep -i "bond\|enslaved\|link failure"
Prometheus + node_exporterを使っている場合、メトリクスnode_network_up{device="bond0"}とnode_network_up{device="eth0"}が自動的にbondと各slaveの状態を追跡してくれる——追加設定は不要だ。
実際に遭遇した問題
50人規模のオフィスと小規模なdatacenterのネットワークを管理していて、bondingに関するあらゆる問題に直面してきた——自分と同じく夜を無駄にしないために記録しておく:
- LACPでのMACアドレスの競合:スイッチは各slaveのMACではなく、bond0のMACを認識する必要がある。古いスイッチがLACPを適切にサポートしていない場合、ループやポートのブロックが発生する。スイッチに確信が持てない場合は、mode 1(active-backup)の方が常に安全だ。
- 再起動後のインターフェース名の変更:bondingが正常動作していたのに、再起動後にudevがカードの検出順序を変更してeth0/eth1がeth2/eth3に変わってしまった経験がある。設定が完全に壊れ、デバッグできる明確なエラーもなかった。enp3s0のようなpredictableな名前を使い、eth0を信頼しないこと。
- bonding上のVLAN:完全にサポートされている。bond0上に通常通りVLANインターフェースを作成する——各slaveごとにVLANを作成する必要はない。
- VM内でのbonding:サーバーハイパーバイザーはホストレベルでbondして仮想NICをVMに提供する。ゲストVM内でbondしてはいけない——ハイパーバイザー層がすでにフェイルオーバーを処理しており、内部でさらにbondすると不必要な複雑さが増すだけだ。
あの深夜2時の夜以来、自分が管理する全productionサーバーにactive-backup bondingを導入した。この1年間でNICが3回故障したが、3回とも完全に無音でフェイルオーバーが完了した——誰も気づかず、supportチケットも一切上がらなかった。これが優れたインフラストラクチャのあるべき姿だ。

