Keepalived using unicast, track and notify scripts

Keepalived works pretty well using multicast messages, unless the network infrastructure does not support multicasting, or when you need to run keepalived in a virtualized/containerized environment and need more than 256 instances of it.
The 256 instances of keepalived limitation stems from the virtual_router_id option in the keepalived.conf file, which accept values from 0-255.

So what happens if you have to run more than 256 keepalived pairs on the same network? There are two options:

- You need to segment the multicast /4 into smaller subnets and specify that in each keepalived.conf
- Get away with multicast completely and use unicast instead.

Starting with release 1.2.8 unicast is supported, and the config file looks like this:
vrrp_instance 23533267-f960-4bd9-9c72-2dd18e2eca8c {
interface eth0
track_interface {
eth0
eth1
}
state BACKUP # Can be the same on both instances, whichever starts first will be the master, or choose MASTER/BACKUP
virtual_router_id 50 # Needs to be the same on both instances, and needs to be unique if using multicast, does not matter with unicast
priority 100 # Can be the same on both instances, unless using MASTER/BACKUP then the bigger number is for the master
nopreempt # Don't fail back
unicast_src_ip 10.188.100.20 # Unicast specific option, this is the IP of the interface keepalived listens on
unicast_peer { # Unicast specific option, this is the IP of the peer instance
10.188.100.21
}
virtual_ipaddress { # The VIP that keepalived will monitor
10.188.96.53 dev eth0
}
}
view raw gistfile1.sh hosted with ❤ by GitHub

You can check that there's no multicast traffic by running tcpdump:
[root@host1 ~] tcpdump -i eth0 -s0 -vv net 224.0.0.0/4
view raw gistfile1.sh hosted with ❤ by GitHub

Two other useful features of keepalived that are not so well documented are the notify and script tracking options:
[root@host1 ~] cat /etc/keepalived/keepalived.conf
vrrp_script check_haproxy {
script "/usr/local/bin/check_haproxy.sh"
interval 2
fall 2
rise 2
}
vrrp_instance test_instance {
interface eth0
track_interface {
eth0
eth1
}
state BACKUP
virtual_router_id 50
priority 100
nopreempt
unicast_src_ip 10.188.100.20
unicast_peer {
10.188.100.21
}
virtual_ipaddress {
10.188.96.53 dev eth0
}
track_script {
check_haproxy
}
notify /usr/local/bin/keepalived.state.sh
}
[root@host1 ~] cat /usr/local/bin/check_haproxy.sh
#!/bin/bash
# Check if haproxy is running, return 1 if not.
# Used by keepalived to initiate a failover in case haproxy is down
HAPROXY_STATUS=$(/bin/ps ax | grep -w [h]aproxy)
if [ "$HAPROXY_STATUS" != "" ]
then
exit 0
else
logger "HAProxy is NOT running. Setting keepalived state to FAULT."
exit 1
fi
[root@host1 ~] cat /usr/local/bin/keepalived.state.sh
#!/bin/bash
TYPE=$1
NAME=$2
STATE=$3
echo $STATE > /var/run/keepalived.state
view raw gistfile1.sh hosted with ❤ by GitHub

The vrrp_script option on line 3 specifies what script to run and the following few lines at what duration. The script can be anything as long as it returns 0 on success and > 0 on failure.
When the script returns 1, keepalived will change its state to FAULT, and if it's the current MASTER will drop the VIP and stop sending multicast messages, if multicast is enabled (in this example it is not, as I am using unicast). The next time the script returns 0, the state will change to BACKUP if nopreempt is specified.

The final interesting bit is the notify stanza on line 36, which calls a script after a state change has occurred (e.g. transition from MASTER to BACKUP, or from MASTER to FAULT). As with the vrrp_script this can be any script. Keepalived passes the following 3 parameters to the notify script:

- $1 = “GROUP” or “INSTANCE”
- $2 = name of group or instance
- $3 = target state of transition (“MASTER”, “BACKUP”, “FAULT”)

The example keepalived.state.sh script on line 36 and 55 uses the STATE parameter to log the current state of keepalived.