よかろうもん!

アプリからインフラまで幅広くこなすいまどきのクラウドエンジニアが記す技術ブログ

keepalivedを利用する際に気をつけておくこと

非常に基本的なことではありますが、今回30分程度考え込んでしまうことになってしまったので、今後同じ失敗をしないためにもミスを記録しておきます。

以下のような構成でkeepalivedを使用し、仮想IPをサービスセグメント/バックエンドセグメントのそれぞれ割り当てます。

f:id:interu:20080916005141p:image

各セグメントは以下のような定義です。

  • サービスセグメント:利用者からアクセスがあるセグメントで80番ポートのみ開放
  • バックエンドセグメント:利用者からアクセスできない内部セグメントであり、主にデータのやり取りで使用し、FWの設定はなし

server1とserver2でkeepalived.confは共通のものとし(下記を参照)、はじめにkeepalivedが起動した方がMASTERとなり仮想IPを保持するようにします。
また、vrrp_sync_groupの設定を追加しておくことで、eth0(SERVICE)に障害が発生しても自動的にeth1(BACKEND)も切り替わるようにしておきます。
#server1がMASTERであった場合、eth0の仮想IPがserver2のeth0に引き継がれ、eth1の仮想IPもserver2に引き継がれるようにしておきます。

vrrp_instance SERVICE {
state BACKUP
interface eth0
garp_master_delay 5
virtual_router_id 51
priority 100
nopreempt
advert_int 3
authentication {
auth_type PASS
auth_pass password
}
virtual_ipaddress {
192.168.2.1/24
192.168.2.2/24
}
}

vrrp_instance BACKEND {
state BACKUP
interface eth1
garp_master_delay 5
virtual_router_id 52
priority 100
nopreempt
advert_int 3
authentication {
auth_type PASS
auth_pass password
}
virtual_ipaddress {
10.1.2.1/24
}
}

vrrp_sync_group VG {
group {
SERVICE
BACKEND
}
notify_master "/bin/sh /var/scripts/failover.sh active"
notify_backup "/bin/sh /var/scripts/failover.sh backup"
notify_fault "/bin/sh /var/scripts/failover.sh backup"
}

このような設定で、server1のkeepalivedを起動してからserver2でもkeepalivedを起動します。
すると最初にkeepalivedを起動したserver1に仮想IPが割り当てられているはずですので、ipコマンドで仮想IPが割り振られているサーバを確認します。

[server1] $ ip addr
eth0
inet 192.168.2.1/24 scope global secondary eth0
inet 192.168.2.2/24 scope global secondary eth0
eth1
inet 10.1.2.1/24 scope global secondary eth1

#一部分のみ抜粋

このような状態になっていればOKなのですが、数秒後に再度ipコマンドで確認してみると、server2に仮想IPが割り振られていました。

[server2] $ ip addr
eth0
inet 192.168.2.1/24 scope global secondary eth0
inet 192.168.2.2/24 scope global secondary eth0
eth1
inet 10.1.2.1/24 scope global secondary eth1

さらに数秒後に確認すると次はserver1に割り振られ、このような動作が繰り返していることに気づきました。
vrrp_sync_groupの設定を追加する前までは確かに正常に動作していたことを確認していたので、vrrp_sync_groupの設定をコメントアウトし、再度動作確認をしてみることに。
すると、eth0側にてMASTER/BACKUPが頻繁に切り替わっており、eth1は特に切り替わっていないということが判明しました。
なのでvrrp_sync_groupの設定を追加したことで、eth1もeth0につれられて状態が変更していたということがわかりました。
「では、どうしてこのような動作をするの?」と考えてみること5分。
vrrp_sync_groupの設定以外にどのようなオペレーションをしたかと、keepalivedの仕組みを思い出すことで原因が判明しました。

keepalivedのMASTERとなっているserverは、VRRPパケットを定期的に送出しすることで自身が正常に動作しているということをBACKUPノードに伝えます。
そのため、BACKUPとなっているノードはVRRPパケットがMASTERから送られてこなければMASTERに障害が発生したと思い、BACKUPからMASTERへ昇格します。

もうお分かりになったかと思いますが、eth0にてVRRPパケットがBACKUPノードに到達していなかったためこのような動作をしたのです。
FireWallにて、eth0では80番ポートのみ許可しており、eth1では何も制限していなかったため、eth0のみおかしな挙動をしたのです。

そういうわけで、iptablesの設定で以下のルールを追加してあげましょう。
RedHatGUIでルールを作成した場合

  • A RH-Firewall-1-INPUT -m state --state NEW -p vrrp -j ACCEPT

これで解決するはずです。

私はiptablesの存在を忘れがちになってしまうことが多々あるため、このエントリーを書くことで、同じ失敗をしないよう肝に銘じておきます。