keepalivedでvrrpを通してVIPを持つ構成にした時に、keepalivedの障害試験をしていて発覚したことのメモです。
概要
- keepalivedは、MASTER STATEの時に終了すると、自身のVIPをinterfaceから解放する
- 異常終了時(
kill -9
で強引に殺したり、サーバがダウンしたりなど)は、正常な終了処理ではないので、VIPを解放しないで持ち続ける - 次にkeepalivedを起動したときは、起動時のIPを正しいものとして認識してしまう
- 手動でVIPを解放しない限り、keepalivedはVIPを解放しない
設定
確認してみます。keepalived
のバージョンは以下です。
Keepalived v1.2.13 (03/19,2015)
-
192.168.33.11
: ノード1: keepalivedを構成。MASTER STATE -
192.168.33.12
: ノード2: keepalivedを構成。BACKUP STATE -
192.168.33.20
: vrrp VIP
vrrp_instance VI_1 {
state BACKUP
interface eth1
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.33.20
}
notify_master "/tmp/master.sh"
notify_backup "/tmp/backup.sh"
unicast_peer {
192.168.33.11
192.168.33.12
}
}
MASTER STATE側は、VIPが見えるようになります。
$ ip addr show eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:4e:29:d9 brd ff:ff:ff:ff:ff:ff
inet 192.168.33.11/24 brd 192.168.33.255 scope global eth1
inet 192.168.33.20/32 scope global eth1 # ← VIP
inet6 fe80::a00:27ff:fe4e:29d9/64 scope link
valid_lft forever preferred_lft forever
keepalived正常終了時
この状態で、keepalived
を正常に停止します。
$ sudo service keepalived stop
ログには以下のようなメッセージが出ます。
Aug 16 06:36:06 centos66-1 Keepalived[2785]: Stopping Keepalived v1.2.13 (03/19,2015)
Aug 16 06:36:06 centos66-1 Keepalived_vrrp[2788]: VRRP_Instance(VI_1) sending 0 priority
Aug 16 06:36:06 centos66-1 Keepalived_healthcheckers[2787]: Removing service [192.168.33.11]:80 from VS [192.168.33.20]:80
Aug 16 06:36:06 centos66-1 Keepalived_healthcheckers[2787]: Removing service [192.168.33.12]:80 from VS [192.168.33.20]:80
Aug 16 06:36:06 centos66-1 kernel: IPVS: __ip_vs_del_service: enter
Aug 16 06:36:06 centos66-1 Keepalived_vrrp[2788]: VRRP_Instance(VI_1) removing protocol VIPs. # ← VIP削除
VIPが取り除かれているようです。(VIPはnode2側に移動しています)
$ ip addr show eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:4e:29:d9 brd ff:ff:ff:ff:ff:ff
inet 192.168.33.11/24 brd 192.168.33.255 scope global eth1
inet6 fe80::a00:27ff:fe4e:29d9/64 scope link
valid_lft forever preferred_lft forever
この後、keepalived
を起動しても、当然正常に組み込まれます。
keepalived異常終了時
同じシチュエーションで、今度はkill -9
で強引にプロセスを殺します。
$ sudo pkill -9 -f keepalived
強引に殺しているので、syslogにも何も出ませんし、終了処理としてのVIPの解放も行われません。
$ ip addr show eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:4e:29:d9 brd ff:ff:ff:ff:ff:ff
inet 192.168.33.11/24 brd 192.168.33.255 scope global eth1
inet 192.168.33.20/32 scope global eth1 # ← VIPが残っている
inet6 fe80::a00:27ff:fe4e:29d9/64 scope link
valid_lft forever preferred_lft forever
node2側は、node1のkeepalivedのダウンを検知してMASTER STATEになり、VIPを持ち始めます。
$ ip addr show eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:75:a7:36 brd ff:ff:ff:ff:ff:ff
inet 192.168.33.12/24 brd 192.168.33.255 scope global eth1
inet 192.168.33.20/32 scope global eth1 # ← VIPが増えている
inet6 fe80::a00:27ff:fe75:a736/64 scope link
valid_lft forever preferred_lft forever
この時点で、VIPである 192.168.33.20
は競合しているので、アプリケーションは不具合を起こす可能性があります。
復旧するには、VIPを手動で削除します。
$ sudo ip addr del 192.168.33.20/32 dev eth1
keepalived異常終了後、復旧操作を行わないままkeepalivedを起動するとどうなるか
上記のように ip addr del
コマンドを実行せずに、またkeepalivedを起動するとどうなるかも確認しました。起動時にいい感じでBACKUP STATEに移行し、VIPを取り除いてくれるかを期待しつつ…
$ sudo service keepalived start
Aug 16 07:06:12 centos66-1 Keepalived[3476]: Starting Keepalived v1.2.13 (03/19,2015)
(snip)
Aug 16 07:06:12 centos66-1 Keepalived_vrrp[3480]: Netlink reflector reports IP 192.168.33.11 added
Aug 16 07:06:12 centos66-1 Keepalived_vrrp[3480]: Netlink reflector reports IP 192.168.33.20 added # ← VIPが登録されている
(snip)
Aug 16 07:06:12 centos66-1 Keepalived_vrrp[3480]: Registering Kernel netlink reflector
Aug 16 07:06:12 centos66-1 Keepalived_vrrp[3480]: Registering Kernel netlink command channel
(snip)
Aug 16 07:06:12 centos66-1 Keepalived_healthcheckers[3479]: Netlink reflector reports IP 192.168.33.11 added
Aug 16 07:06:12 centos66-1 Keepalived_healthcheckers[3479]: Netlink reflector reports IP 192.168.33.20 added # ← VIPが登録されている
(snip)
Aug 16 07:06:12 centos66-1 Keepalived_vrrp[3480]: Using LinkWatch kernel netlink reflector...
Aug 16 07:06:12 centos66-1 Keepalived_vrrp[3480]: VRRP_Instance(VI_1) Entering BACKUP STATE
Aug 16 07:06:12 centos66-1 Keepalived_vrrp[3480]: VRRP sockpool: [ifindex(3), proto(112), unicast(1), fd(10,11)]
Aug 16 07:06:12 centos66-1 Keepalived_healthcheckers[3479]: IPVS: Service already exists
Aug 16 07:06:12 centos66-1 Keepalived_healthcheckers[3479]: IPVS: Destination already exists
Aug 16 07:06:12 centos66-1 Keepalived_healthcheckers[3479]: IPVS: Destination already exists
Aug 16 07:06:12 centos66-1 Keepalived_healthcheckers[3479]: Using LinkWatch kernel netlink reflector...
Aug 16 07:06:12 centos66-1 Keepalived_healthcheckers[3479]: Activating healthchecker for service [192.168.33.11]:80
Aug 16 07:06:12 centos66-1 Keepalived_healthcheckers[3479]: Activating healthchecker for service [192.168.33.12]:80
いろいろと端折りましたが、正常終了時に出力されたような「removing protocol VIPs.
」のようなメッセージが出ません。むしろ、VIPである192.168.33.20
を登録したようなメッセージが出ています(Netlink reflector reports IP 192.168.33.20 added
)。
ということで、BACKUP STATEに移行したにも関わらず、VIPは解放されませんでした。
$ ip addr show eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:4e:29:d9 brd ff:ff:ff:ff:ff:ff
inet 192.168.33.11/24 brd 192.168.33.255 scope global eth1
inet 192.168.33.20/32 scope global eth1 # ← VIPが残っている
inet6 fe80::a00:27ff:fe4e:29d9/64 scope link
valid_lft forever preferred_lft forever
こうなってしまうと、次に正常終了しても一緒。
$ sudo service keepalived stop
Aug 16 07:13:53 centos66-1 Keepalived[3477]: Stopping Keepalived v1.2.13 (03/19,2015)
Aug 16 07:13:53 centos66-1 Keepalived_healthcheckers[3479]: Removing service [192.168.33.11]:80 from VS [192.168.33.20]:80
Aug 16 07:13:53 centos66-1 Keepalived_healthcheckers[3479]: Removing service [192.168.33.12]:80 from VS [192.168.33.20]:80
Aug 16 07:13:53 centos66-1 kernel: IPVS: __ip_vs_del_service: enter
もうVIPを解放してくれません…。
$ ip addr show eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:4e:29:d9 brd ff:ff:ff:ff:ff:ff
inet 192.168.33.11/24 brd 192.168.33.255 scope global eth1
inet 192.168.33.20/32 scope global eth1 # ← VIPが残っている
inet6 fe80::a00:27ff:fe4e:29d9/64 scope link
valid_lft forever preferred_lft forever
まとめ
最初の概要に書いたとおりですが、keepalived
が異常終了すると、VIPを自動で解放してくれないようです。対処としては、以下くらいかなと思います。
- 発覚したら速やかに
ip addr del
コマンドでIPを削除する - 自動化するには、
keepalived.conf
中のnotify_backup
中のスクリプトで、強引にVIPを解放する仕組みを仕込む - あるいは、一度MASTER STATEに戻してしまえば、次にはちゃんと解放してくれます。
keepalived
は結構歴史が古いソフトなので、本当にこんな対処しかないのかは不明です…。