仮想 IP アドレスをフェイルオーバーする方法

お久しぶりです。
相変らず不定期更新で、作業メモばかりのブログです。

今回は (Debian系)Linux で、仮想 IP アドレスをフェイルオーバーする方法のメモです。
簡単に言うと、サーバ 2台の状態で片方がコケた時に残ってる方でサービスを継続したい時に使う手法です。って、全然簡単じゃないですね…

では下準備からです。
■材料

  • サーバ 2台(もちろん仮想マシンでも可)
  • ネットワーク 2個(つまり NIC 2枚ずつとハブ 2個)
  • クライアントマシン 1台(切り替え状況をチェックします)

■準備手順

  1. サーバに Debian系OS(最近だと Ubuntu が多いですかね)を入れます
  2. サーバに fake パッケージをインストールします(send_arp コマンドが入ります)
  3. サーバに arping パッケージをインストールします
  4. サーバを 2つのネットワークに接続する設定をします(/etc/network/interfaces ですね)
    便宜上それぞれを WAN と LAN と呼びます。また、サーバ名は srv1、srv2 とします。

    • LAN(eth0):192.168.1.0/24, srv1(192.168.1.11), srv2(192.168.1.12)
    • WAN(eth1):10.0.0.0/24, srv1(10.0.0.11), srv2(10.0.0.12)
  5. クライアントマシン(名前:cli)を WAN に接続します(IP:10.0.0.20)

それで、実際に切り替える操作です。

  • 仮想 IP アドレス($VIP)を 10.0.0.1 とします
  • WAN側デバイス($DEV = eth1)の MAC アドレス($MAC)を次だとします
    • srv1(000011110000)
    • srv2(222200002222)

■メイン側サーバ(srv1)へ仮想 IP を付けます

srv1> ip addr add $VIP/24 dev $DEV

■クライアント側からチェックします

  • IP アドレス:「cli> ping $VIP
  • ARP キャッシュ:「cli> arp」(10.0.0.1 が 000011110000 になるはずです)

■仮想 IP をフェイルオーバーするコマンドです
ここでは仮想 IP の存在チェックを繰り返して、失敗したら 仮想 IP の設定と ARP キャッシュの更新通知を行います。

  1. 仮想 IP の存在チェック:「srv2> arping -q -c 1 -I $DEV $VIP
  2. 仮想 IP の設定(srv1 の時と同様):「srv2> ip addr add $VIP/24 dev $DEV
  3. ARP キャッシュの更新通知:「srv2> send_arp $VIP $MAC 255.255.255.255 ffffffffffff $DEV $MAC ffffffffffff reply

たぶん、実際には下に書いたようなスクリプトを実行することになります。

■srv1 の仮想 IP を外します
srv1> ip addr del $VIP dev $DEV

■クライアント側からチェックします
前と同様に ping と arp を実行します。
arp の表示で 10.0.0.1 が 222200002222 に変わっているはずです。


仮想 IP フェイルオーバー用スクリプト


#!/bin/bash

VIP="10.0.0.1"
DEV="eth1"
BCAST_IP="255.255.255.255"
BCAST_MAC="ffffffffffff" # f x 12

health_check() {
arping -q -c 1 -I $DEV $VIP
return $?
}

ip_failover() {
MAC=`ip link show $DEV | egrep -o '([0-9a-f]{2}:){5}[0-9a-f]{2}' | head -1 | tr -d \:`
ip addr add $VIP/24 dev $DEV
send_arp $VIP $MAC $BCAST_IP $BCAST_MAC $DEV $MAC $BCAST_MAC reply
}

while health_check; do
echo "health check ok!"
sleep 1
done
echo "fail over!"
ip_failover

もちろん、実際に使う時には echo の部分はコメントアウトする事になるでしょう。


また、作業中に気付いた点は以下の通りです。

  • 仮想 IP のチェックは 「arping -q -c 1 -I $DEV $VIP」 の方が 「ping -c 1 $VIP >/dev/null」 よりも早くダウンに気付きました
  • Web でクライアント(実際には WAN のルータ)に 「echo 1 > /proc/sys/net/ipv4/conf/all/arp_accept」 を設定した方が良いと書いてありましたが、今回は設定値が 0 でも期待通りに動きました
  • ARP キャッシュ更新に使う send_arp コマンドですが、Web で調べた 「send_arp $VIP $MAC $BCAST_IP $BCAST_MAC $DEV」 では期待する ARP Reply ではなく ARP Request になってしまいました