いまさらだけど keepalived を使ってみたメモ。LVS ではなく HAProxy の冗長化に使用するつもりなので LVS 関係の設定はありません。
CentOS 7 に yum で入れたバージョンで試しています。
- keepalived-1.2.13-7.el7.x86_64
vrrp_script と track_script
vrrp_script でチェックスクリプトを定義して、
vrrp_script chk_haproxy {
script "systemctl is-active haproxy"
interval 3 # スクリプトが実行されるインターバル
fall 3 # 非ゼロの終了コードが 3 回続いたら成功から失敗に遷移する
rise 2 # 非ゼロの終了コードが 2 回続いたら失敗から成功に遷移する
}
vrrp_script chk_http_port {
script "< /dev/tcp/127.0.0.1/80"
interval 3
fall 3
rise 2
}
vrrp_instance の track_script で VRRP インスタンスに設定する。
vrrp_instance VI_1 {
:
track_script {
chk_haproxy
chk_http_port # 複数指定できる
}
}
vrrp_script の weight
vrrp_sync_group を設定していてかつ weight も設定しているとチェック自体が実行されなくなる。
vrrp_sync_group を設定していなければ weight の値によって次のように動作する。
weightが未設定- スクリプトが失敗ると FAULT になる
weightが正数- スクリプトが成功するとプライオリティが指定値だけ上がる
weightが負数- スクリプトが失敗するとプライオリティが指定値だけ下がる
weight を指定している場合に、nopreempt も指定しているとスクリプトが失敗してもフェールオーバーしない(MASTER が FAULT にならないかぎりフェイルオーバーしないため)。
smtp_alert
global_defs で通知先やメールサーバを設定し、vrrp_sync_group や vrrp_instance で smtp_alert を指定すると、ステートの変化時にメールで通知できる。
global_defs {
notification_email {
ore@example.com
}
notification_email_from keepalived@example.com
smtp_server 127.0.0.1
smtp_connect_timeout 10
:
}
vrrp_sync_group VG_1 {
:
smtp_alert
}
vrrp_instance VI_1 {
:
smtp_alert
}
送信されるメールの内容は次のようなもの。
Sublect: [192.168.33.11] VRRP Group VG - Entering BACKUP state Body: => All VRRP group instances are now in BACKUP state <=
Sublect: [192.168.33.11] VRRP Instance VIP - Entering BACKUP state Body: => VRRP Instance is nolonger owning VRRP VIPs <=
MASTER や BACKUP になったときは通知されるけど FAULT になったときは通知されない。
- https://github.com/acassen/keepalived/blob/v1.2.13/keepalived/vrrp/vrrp_scheduler.c#L146-L158
- https://github.com/acassen/keepalived/blob/v1.2.13/keepalived/vrrp/vrrp_sync.c#L113-L125
notify
vrrp_sync_group や vrrp_instance でステートの変化時に実行するスクリプトを指定することができる。
vrrp_sync_group VG_1 { : notify "/vagrant/notify.sh" notify_master "/vagrant/notify.sh master" notify_backup "/vagrant/notify.sh backup" notify_fault "/vagrant/notify.sh fault" } vrrp_instance VI_1 { : notify "/vagrant/notify.sh" notify_master "/vagrant/notify.sh master" notify_backup "/vagrant/notify.sh backup" notify_fault "/vagrant/notify.sh fault" notify_stop "/vagrant/notify.sh stop" }
notify は指定した値がそのまま実行可能ファイル名だと認識されるので引数を指定することはできない。
notify "/vagrant/notify.sh" # OK notify "/vagrant/notify.sh arg" # NG
その他のスクリプトは引数を指定することができる。
notify_master "/vagrant/notify.sh master" notify_backup "/vagrant/notify.sh backup" notify_fault "/vagrant/notify.sh fault" notify_stop "/vagrant/notify.sh stop"
notify は次のように引数が付けられて実行される。
notify.sh GROUP VG_1 MASTER 0 notify.sh INSTANCE VI_1 MASTER 100 notify.sh GROUP VG_1 BACKUP 0 notify.sh INSTANCE VI_1 BACKUP 100 notify.sh GROUP VG_1 FAULT 0 notify.sh INSTANCE VI_1 FAULT 100
最後の数字は優先度で GROUP のときは優先度とか無いので常に 0 になる。
その他のスクリプトは引数はつかない(設定で指定した引数がそのまま渡される)。
notify_stop は vrrp_instance にのみ設定することができて、 VRRP インスタンスのシャットダウン時に実行される。
iptables や tcpdump で VRRP パケットを操作
iptables を有効にする。
sudo yum install -y iptables-services sudo systemctl start iptables.service sudo systemctl enable iptables.service sudo iptables -F sudo service iptables save
プロトコルには vrrp を指定する。
iptables -A INPUT -p vrrp -j DROP
tcpdump でも vrrp を指定できる。
tcpdump -nn -i any vrrp
vrrp のタイムアウト
vrrp のタイムアウト(MASTER が停止したと判断される時間)は advert_int の 3 倍で、変更できない。
unicast
自分自身に unicast しても届かないので、次のように2台で同じ値を設定しても多分大丈夫。
unicast_peer {
192.168.33.10
192.168.33.11
}
ログ
/etc/rsyslog.d/keepalived.conf 辺りで次のようにしておけば、ログを /var/log/keepalived.log に出力することができる(デフォだと /var/log/messages に出る)。
/etc/rsyslog.d/keepalived.conf
:programname, startswith, "Keepalived" /var/log/keepalived.log & stop :programname, startswith, "keepalived" /var/log/keepalived.log & stop
ログローテートも必要。
/etc/logrotate.d/keepalived
/var/log/keepalived.log {
daily
rotate 10
missingok
sharedscripts
postrotate
/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
endscript
}
これだと1回のローテートで rsyslogd に複数回 HUP される気がするので /etc/logrotate.d/syslog に追記するほうが良いかもしれない。
/etc/logrotate.d/syslog
/var/log/cron
/var/log/maillog
/var/log/messages
/var/log/secure
/var/log/spooler
/var/log/keepalived.log
{
missingok
sharedscripts
postrotate
/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
endscript
}