heartbeat

(作成:2013/11)

サーバの冗長化環境を作るためにMySQLをレプリケーションしたりlsyncdでファイル同期をしておくのも大事なんだけれど、実際にサーバ障害発生したらどうなのよ、てなわけで。BIG-IPとか持ってたらソレ任せでも良いんだけれど、f5 networks社のは個人じゃ手出し出来ないからナー。元々個人で使うモンじゃねーけど。

Install on CentOS

下記のように2台のサーバがあるとする。

提供するサービスは、あまり良い例ではないけれど仮に memcached として話を進めよう。要件としてはごくごく単純に、マスタが斃れたらスレイヴを昇格してフェイルオーバ、旧マスタ復活の際にフェイルバックはさせないものとする。
NW設定は以下のような感じで。
(VIP) sv1 sv2
eth0 172.16.0.1 172.16.0.2 172.16.0.3
eth1 192.168.0.2 192.168.0.3

取り敢えず必要なパッケージを2台のサーバにぶっ込む。EPELなら最新版が導入できるのでそちらで。EPELの使い方は拙サイト「yum」を参照。

yum
(作成:2012/03) CentOSなどRedHat系OSでパッケージ管理をするソフト。ここでは標準設定よりも少し便利にするための設定...
# yum install --enablerepo=epel heartbeat

サクッと設定。

#### /etc/ha.d/ha.cf of sv1

logfile        /var/log/ha-log

keepalive    2
deadtime    30
warntime    10
initdead    120

udpport        694
ucast        eth1 192.168.0.3

auto_failback    off
watchdog    /dev/watchdog

node        sv1
node        sv2

ping        172.16.0.254

##respawn        hacluster /usr/lib/heartbeat/ipfail
respawn        root /usr/local/sbin/ha-chk-memcached.sh

apiauth        ipfail gid=haclient uid=hacluster
#### /etc/ha.d/ha.cf of sv2

logfile        /var/log/ha-log

keepalive    2
deadtime    30
warntime    10
initdead    120

udpport        694
ucast        eth1 192.168.0.2

auto_failback    off
watchdog    /dev/watchdog

node        sv1
node        sv2

ping        172.16.0.254

##respawn        hacluster /usr/lib/heartbeat/ipfail
respawn        root /usr/local/sbin/ha-chk-memcached.sh

apiauth        ipfail gid=haclient uid=hacluster

取り敢えずこんな感じの初期設定。違うトコロは ucast のIPアドレス。 ここは冗長化相手のIPアドレスを指定する 。自分のIPじゃないので間違わないように。
ping 172.16.0.254 はサービス側の通信確認用。 respawn はサービス監視コマンドで後述。

これ以降は両サーバ共通設定。さくさく設定しよう。

#### /etc/ha.d/haresources

sv1      memcached 172.16.0.1/24
#### /etc/ha.d/authkeys

auth 1
1 crc
# chmod 600 /etc/ha.d/authkeys

監視コマンドはなるべく穴の無いように作り込みたいね。こんな感じで足りるかな……。

#! /bin/bash

#### /usr/local/sbin/ha-chk-memcached.sh

INTERVAL=30
STB_INTV=40

VIP=172.16.0.1

while true; do
    /etc/ha.d/resource.d/IPaddr ${VIP} status >/dev/null 2>&1
    if [ $? -ne 0 ]; then
        sleep ${INTERVAL}
        continue
    fi

    ## Process check
    kill -0 `cat /var/run/memcached/memcached.pid` >/dev/null 2>&1
    if [ $? -ne 0 ]; then
        /usr/lib/heartbeat/hb_standby
    fi
    (echo 'stats'; sleep 1; echo 'quit'; sleep 1;) | telnet localhost 11211 2> /dev/null | grep -q "STAT pid"
    if [ $? -ne 0 ]; then
        /usr/lib/heartbeat/hb_standby
    fi

    sleep ${STB_INTV}
done

無限ループでブン回してチェックするらしい。
L9 IPaddr によるチェックは、自分自身がマスタかどうかを確認している。自分がスレイヴの場合、特にチェックする事は無いので continue
L16 kill -0 はプロセス存在確認。L20 は telnet での stats 結果確認。この2つの確認で memcached が使える状態にあるかを判断する。 INTERVALSTB_INTV はチェック速度に関わるので、サーバ負荷状況を見つつ値を調整しても良いかも。

ここまできたらマスタ、スレイヴ共に起動する。

# /etc/init.d/heartbeat start

動作確認

インタフェースを見てみよう。

(sv1)# /sbin/ifconfig
eth0      Link encap:Ethernet  HWaddr XX:XX:XX:XX:XX:XX  
          ...

eth0:0    Link encap:Ethernet  HWaddr XX:XX:XX:XX:XX:XX  
          inet addr:172.16.0.1  Bcast:172.16.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

lo        Link encap:Local Loopback  
          ...

# ps -ef | grep memcached
...
102      26838     1  0 19:07 ?        00:00:00 memcached -d -p 11211 -u memcached -m 64 -c 1024 -P /var/run/memcached/memcached.pid -v
...
(sv2)# /sbin/ifconfig 
eth0      Link encap:Ethernet  HWaddr XX:XX:XX:XX:XX:YY
          ...

          (VirtualIP無し)

lo        Link encap:Local Loopback  
          ...

# ps -ef | grep memcached
...
(memcachedプロセス無し)

こんな感じで、マスタの方にサービス提供用の仮想IPが割り振られ、/etc/ha.d/haresources で定義した通り memcached が起動している。
ここで sv1memcached を手動停止すると、フェイルオーバして立場が逆転する。

(sv1)# /etc/init.d/memcached stop
memcached を停止中:                                        [  OK  ]
# /sbin/ifconfig 
eth0      Link encap:Ethernet  HWaddr XX:XX:XX:XX:XX:XX
          ...

          (VirtualIP無し)

lo        Link encap:Local Loopback 
          ...

# ps -ef | grep memcached
...
(memcachedプロセス無し)
(sv2)# /sbin/ifconfig 
eth0      Link encap:Ethernet  HWaddr XX:XX:XX:XX:XX:YY
          ...

eth1:0    Link encap:Ethernet  HWaddr XX:XX:XX:XX:XX:YY  
          inet addr:172.16.0.1  Bcast:172.16.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

lo        Link encap:Local Loopback  
          ...

# ps -ef | grep memcached
...
102      23456     1  0 19:22 ?        00:00:00 memcached -d -p 11211 -u memcached -m 64 -c 1024 -P /var/run/memcached/memcached.pid

てな感じ。これでまた sv2 側で memcached を落とすと、 sv1 側にフェイルオーバしてくれる。
また sv1 側で heartbeat を再起動したりしても、 sv2sv1 への切り替わりは発生しない(結果は割愛)。これで auto=failback off の設定が効いている事も確認できる。

もう少し詳しい動作は /var/log/ha-log を参考にすると良い。