お久しぶりです。
相変らず不定期更新で、作業メモばかりのブログです。
今回は (Debian系)Linux で、仮想 IP アドレスをフェイルオーバーする方法のメモです。
簡単に言うと、サーバ 2台の状態で片方がコケた時に残ってる方でサービスを継続したい時に使う手法です。って、全然簡単じゃないですね…
では下準備からです。
■材料
- サーバ 2台(もちろん仮想マシンでも可)
- ネットワーク 2個(つまり NIC 2枚ずつとハブ 2個)
- クライアントマシン 1台(切り替え状況をチェックします)
■準備手順
- サーバに Debian系OS(最近だと Ubuntu が多いですかね)を入れます
- サーバに fake パッケージをインストールします(send_arp コマンドが入ります)
- サーバに arping パッケージをインストールします
- サーバを 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)
- クライアントマシン(名前: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 キャッシュの更新通知を行います。
- 仮想 IP の存在チェック:「
srv2> arping -q -c 1 -I $DEV $VIP
」
- 仮想 IP の設定(srv1 の時と同様):「
srv2> ip addr add $VIP/24 dev $DEV
」
- 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 になってしまいました