Solaris8 でアクトスタンバイ
IPMPを使っているSolaris8を2台使って,簡単なアクトスタンバイ系を作る方法についてのメモです.IPアドレス,ホスト名とインタフェースが以下のようになっている場合を考えます.
サーバ#1 10.10.10.10 host00b2 代表アドレス, nodename 10.10.10.11 host01b0 bge0 に割り振るアドレス 10.10.10.12 host02b1 bge1 に割り振るアドレス
サーバ#2 10.10.10.13 host03b2 代表アドレス, nodename 10.10.10.14 host04b0 bge0 に割り振るアドレス 10.10.10.15 host05b1 bge1 に割り振るアドレス
ネットワークは10.10.10.0/24で,デフォルトゲートウェイは10.10.10.253だとします.そうすると,サーバ#1, #2 の/etc/hostname.*, /etc/nodename は以下のようになります.
サーバ#1 /etc/hostname.bge0 host00b2 netmask + broadcast + group IPMP1 up \ addif host01b0 deprecated -failover netmask + broadcast + up /etc/hostname.bge1 host02b1 netmask + broadcast + group IPMP1 deprecated -failover standby up /etc/nodename host00b2
サーバ#2 /etc/hostname.bge0 -- (1) host03b2 netmask + broadcast + group IPMP1 up \ addif host04b0 deprecated -failover netmask + broadcast + up /etc/hostname.bge1 host05b1 netmask + broadcast + group IPMP1 deprecated -failover standby up /etc/nodename host03b2
アクトスタンバイを作り出す方法として,サーバ#1のネットワークが切れた時にサーバ#2のIPアドレスを変更して,サーバ#1のIPアドレスに付け替えてみます.つまり,
サーバ#2 /etc/hostname.bge0 -- (2) host00b2 netmask + broadcast + group IPMP1 up \ addif host04b0 deprecated -failover netmask + broadcast + up
となっている状態を作りだすわけです.これを実現するshスクリプト(toggle_if)は以下のようになります.
#!/bin/sh # /etc/toggle_if GATE='10.10.10.253' case "$1" in # 引数は wakeup か sleep としています wakeup) # wakeupはサーバ#2のアドレスを使います /sbin/ifconfig bge0 unplumb /sbin/ifconfig bge1 unplumb # unplumbはインタフェースを削除します /sbin/ifconfig bge0 plumb /sbin/ifconfig bge1 plumb # plumbはインタフェースを新規作成します cp -f /etc/wakeup_hostname.bge0 /etc/hostname.bge0 # wakeup_hostname.bge0 は上記(1)です IFCMD=`cat /etc/hostname.bge0` /sbin/ifconfig bge0 $IFCMD > /dev/null 2>&1 # bge0 へのアドレス設定 IFCMD=`cat /etc/hostname.bge1` /sbin/ifconfig bge1 $IFCMD > /dev/null 2>&1 # bge1 へのアドレス設定 ping $GATE > /dev/null 2>&1 # 収容スイッチのARPテーブルを更新します /usr/bin/logger -p daemon.notice 'wakeup to #2 addr' # syslog に変更を登録します # kernel がIPアドレス変更を出力するので # それだけでも判断可能です ;; sleep) # sleepはサーバ#1のアドレスを使います /sbin/ifconfig bge0 unplumb /sbin/ifconfig bge1 unplumb # unplumbはインタフェースを削除します /sbin/ifconfig bge0 plumb /sbin/ifconfig bge1 plumb # plumbはインタフェースを新規作成します cp -f /etc/sleep_hostname.bge0 /etc/hostname.bge0 # wakeup_hostname.bge0 は上記(2)です IFCMD=`cat /etc/hostname.bge0` /sbin/ifconfig bge0 $IFCMD > /dev/null 2>&1 # bge0 へのアドレス設定 IFCMD=`cat /etc/hostname.bge1` /sbin/ifconfig bge1 $IFCMD > /dev/null 2>&1 # bge1 へのアドレス設定 /usr/bin/logger -p daemon.notice 'sleep to #1 addr' # 収容スイッチのARPテーブルを更新します ping $GATE > /dev/null 2>&1 # syslog に変更を登録します # kernel がIPアドレス変更を出力するので # それだけでも判断可能です ;; *) echo "Usage: $0 {wakeup | sleep}" # 引数が wakeup でも sleep でもなければ # 間違い exit 1 ;; esac
これでインタフェースアドレス変更をサーバリブートなしで実行できるようになりました.でもこれで終わりではありません.アクトスタンバイを実現するためには,サーバ#2からサーバ#1のインタフェースが生きているかどうかを確認する必要があります.サーバ#1でbge0, bge1に割り振ったアドレスはdeprecated 宣言しているので,このアドレスからのパケット送出はできませんが,外部からこのアドレスに対してパケットを受信した際にはこのアドレスからの返信は可能です.
つまり,10.10.10.11, 10.10.10.12 へのping が可能です.このため,両方へのping が止まったことで10.10.10.10がダウンしたと判断することができます.この方法を使ったスクリプト(ifwatchdog)は以下のようになります.
#!/bin/sh # /etc/ifwatchdog ## target configurations # TARGET_IF0: サーバ#1 の代表アドレス # TARGET_IF1: サーバ#1 bge0 に割り振ったアドレス # TARGET_IF2: サーバ#1 bge1 に割り振ったアドレス # GW: サーバ#1, #2を収容するスイッチのアドレス # IF_CFG: サーバ#2 bge0 の設定ファイル名 # IF_NAME: サーバ#2 のノード名 # TOGGLE: アドレス変更スクリプト # DEBUG: デバッグモード 0/1 (1: デバッグモードON) TARGET_IF0='10.10.10.10' TARGET_IF1='10.10.10.11' TARGET_IF2='10.10.10.12' GW='10.10.10.253' IF_CFG='/etc/hostname.bge0' IF_NAME='host03b2' TOGGLE='/etc/toggle_if' DEBUG=0 if [ $DEBUG -eq 1 ] then OUTPUT='' # デバッグ中は標準出力 else OUTPUT='/dev/null' # デバッグ中でなければ出力しない fi ## check interface mode # sleep: サーバ#1 のアドレスを使うモード # wakeup: サーバ#2 のアドレスを使うモード /usr/bin/grep $IF_NAME $IF_CFG > $OUTPUT 2>&1 RES_IF=$? # どちらのモードなのかを設定ファイルから判断 # 0 だとwakeup モード(サーバ#2アドレス) # 1 だとsleep モード (サーバ#1アドレス) if [ $RES_IF -eq 0 ] then MODE='WAKEUP' if [ $DEBUG -eq 1 ] then echo "using my, server#2's name" fi else MODE='SLEEP' if [ $DEBUG -eq 1 ] then echo "using server#1's name" fi fi ## check target interface # /usr/sbin/ping -g $GW -n $TARGET_IF1 3 > $OUTPUT 2>&1 RES_IF1=$? /usr/sbin/ping -g $GW -n $TARGET_IF2 3 > $OUTPUT 2>&1 RES_IF2=$? # サーバ#1 のインタフェースの死活監視 # -g $GW: 収容スイッチ経由(スイッチARPテーブル更新のため) # -n $TARGET*: 出力時にホスト名に変換しない # 3: 1秒に1回,全3回チェック ## do something # if [ $RES_IF1 -eq 0 ] || [ $RES_IF2 -eq 0 ] then # サーバ#1 は生きている if [ $MODE = 'SLEEP' ] then # サーバ#1 のアドレスを使っていたのでwakeupモードへ if [ $DEBUG -eq 1 ] then echo WAKEUP else $TOGGLE wakeup /usr/sbin/ping -n $TARGET_IF0 2 > /dev/null 2>&1 fi else # サーバ#2 のアドレスを使っているのでそのまま if [ $DEBUG -eq 1 ] then echo ALREADY WAKEUP: DO NOTHING fi fi else # サーバ#1 はダウンしている if [ $MODE = 'WAKEUP' ] then # サーバ#2 のアドレスを使っているのでsleepモードへ if [ $DEBUG -eq 1 ] then echo SLEEP else $TOGGLE sleep fi else # サーバ#1 のアドレスを使っているのでそのまま if [ $DEBUG -eq 1 ] then echo ALREADY SLEEP: DO NOTHING fi fi fi
ネットワークインタフェースを結線してからIPMPを使った代表アドレスが使えるようになるまではだいたい1分ぐらいかかります.詳しくはmpathdのマニュアルを参照してください.経験則では,監視スクリプトを2分ぐらいごとに動かせばよいようです.