Using vrrp_script, track_script, and notify Hooks in Keepalived for Priority Control and Service Failover
vrrp_script provides health/eligibility probes that can adjust a VRRP instance’s priority at runtime. By returning a non‑zero exit code, the script can penalize priority via weight, making the local node less likely to be elected master. track_script links these checks to a specific vrrp_instance. notify hooks run external actions when the role changes.
vrrp_script example (priority penalty when a flag file exists)
- Behavior: If /etc/keepalived/down exists, return 1 and reduce priority by 20; otherwise return 0.
- Purpose: Allow manual demotion of MASTER and role handoff.
Shell probe (install on each node):
# /usr/local/sbin/kv_down_check.sh
#!/usr/bin/env bash
set -euo pipefail
FLAG="/etc/keepalived/down"
if [ -e "$FLAG" ]; then
# Signal failure -> apply weight penalty
exit 1
fi
# Healthy
exit 0
Example VRRP script definition and attachment:
vrrp_script file_gate {
script "/usr/local/sbin/kv_down_check.sh"
interval 1
weight -20
}
vrrp_instance VIP_WEB {
# ... other instance options ...
track_script {
file_gate
}
}
notify callbacks
- notify_master: Runs when the local node transitions to MASTER (commonly used to start frontends like nginx/haproxy).
- notify_backup: Runs when the local node transitions to BACKUP (commonly used to stop or pause local services).
- notify_fault: Runs when the instance encounters a fault.
Example mapping to a service controller:
notify_master "/etc/keepalived/haproxy_ctl.sh start"
notify_backup "/etc/keepalived/haproxy_ctl.sh stop"
notify_fault "/etc/keepalived/haproxy_ctl.sh stop"
End‑to‑end configuration
Assumptions:
- VIP: 10.0.22.245 (same on both nodes)
- virtual_router_id: 51
- MASTER priortiy: 100
- BACKUP priority: 90
- A down file on MASTER reduces effective priority by 20 (to 80), triggreing failover.
MASTER node keepalived.conf:
global_defs {
router_id KEEPALIVED_MASTER
}
vrrp_script file_gate {
script "/usr/local/sbin/kv_down_check.sh"
interval 1
weight -20
}
vrrp_instance VIP_WEB {
state MASTER
interface eth1
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.0.22.245/24 dev eth1
}
track_script {
file_gate
}
notify_master "/etc/keepalived/haproxy_ctl.sh start"
notify_backup "/etc/keepalived/haproxy_ctl.sh stop"
notify_fault "/etc/keepalived/haproxy_ctl.sh stop"
}
BACKUP node keepalived.conf:
global_defs {
router_id KEEPALIVED_BACKUP
}
# Optional: include the same vrrp_script and track it on BACKUP for symmetry
vrrp_script file_gate {
script "/usr/local/sbin/kv_down_check.sh"
interval 1
weight -20
}
vrrp_instance VIP_WEB {
state BACKUP
interface eth1
virtual_router_id 51
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.0.22.245/24 dev eth1
}
track_script {
file_gate
}
notify_master "/etc/keepalived/haproxy_ctl.sh start"
notify_backup "/etc/keepalived/haproxy_ctl.sh stop"
notify_fault "/etc/keepalived/haproxy_ctl.sh stop"
}
Behavior walkthrough
- Normal state:
- MASTER has priority 100 and holds 10.0.22.245.
- BACKUP has priority 90 and remains passive.
- Simulated MASTER fault:
- Create the flag: touch /etc/keepalived/down on the MASTER node.
- file_gate returns 1 → weight -20 applies → effective priority becomes 80.
- BACKUP’s 90 surpasses 80, so BACKUP becomes MASTER and runs notify_master (start haproxy).
- Former MASTER demotes to BACKUP and runs notify_backup (stop haproxy).
- Recovery:
- Remove the flag: rm -f /etc/keepalived/down on the original MASTER.
- Its priority returns to 100. With preemption enabled by default, it regains MASTER and runs notify_master (start haproxy), while the other node transitions to BACKUP and runs notify_backup (stop haproxy).
Service control script for notify hooks
# /etc/keepalived/haproxy_ctl.sh
#!/usr/bin/env bash
set -euo pipefail
action="${1:-}" || true
case "$action" in
start)
if command -v systemctl >/dev/null 2>&1; then
systemctl start haproxy
else
/etc/init.d/haproxy start
fi
;;
stop)
if command -v systemctl >/dev/null 2>&1; then
systemctl stop haproxy
else
/etc/init.d/haproxy stop
fi
;;
restart)
if command -v systemctl >/dev/null 2>&1; then
systemctl restart haproxy
else
/etc/init.d/haproxy stop || true
/etc/init.d/haproxy start
fi
;;
*)
echo "usage: $0 {start|stop|restart}" >&2
exit 2
;;
esac