いまさらだけど 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 }