LinuxにおけるNetwork Bonding:サーバーの帯域幅向上と自動フェイルオーバーの設定

Network tutorial - IT technology blog
Network tutorial - IT technology blog

背景 — 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に関するあらゆる問題に直面してきた——自分と同じく夜を無駄にしないために記録しておく:

  1. LACPでのMACアドレスの競合:スイッチは各slaveのMACではなく、bond0のMACを認識する必要がある。古いスイッチがLACPを適切にサポートしていない場合、ループやポートのブロックが発生する。スイッチに確信が持てない場合は、mode 1(active-backup)の方が常に安全だ。
  2. 再起動後のインターフェース名の変更:bondingが正常動作していたのに、再起動後にudevがカードの検出順序を変更してeth0/eth1がeth2/eth3に変わってしまった経験がある。設定が完全に壊れ、デバッグできる明確なエラーもなかった。enp3s0のようなpredictableな名前を使い、eth0を信頼しないこと。
  3. bonding上のVLAN:完全にサポートされている。bond0上に通常通りVLANインターフェースを作成する——各slaveごとにVLANを作成する必要はない。
  4. VM内でのbonding:サーバーハイパーバイザーはホストレベルでbondして仮想NICをVMに提供する。ゲストVM内でbondしてはいけない——ハイパーバイザー層がすでにフェイルオーバーを処理しており、内部でさらにbondすると不必要な複雑さが増すだけだ。

あの深夜2時の夜以来、自分が管理する全productionサーバーにactive-backup bondingを導入した。この1年間でNICが3回故障したが、3回とも完全に無音でフェイルオーバーが完了した——誰も気づかず、supportチケットも一切上がらなかった。これが優れたインフラストラクチャのあるべき姿だ。

Share: