Keepalived and unicast over multiple interfaces
Vincent Bernat
3-minute read
Also available in
Attachment:
Update (2022-11)
Since Keepalived 2.1.0, the hack described here is not needed anymore: the
interface directive in vrrp_instance is not required anymore.
Keepalived[1] is a Linux implementation of VRRP[2]. The usual role of VRRP is to share a virtual IP across a set of routers. For each VRRP instance, a leader is elected and gets to serve the IP address, ensuring the high availability of the attached service. Keepalived can also be used for a generic leader election, thanks to its ability to use scripts for health checking and run commands on state change.
A simple configuration looks like this:
vrrp_instance gateway1 {
state BACKUP # ❶
interface eth0 # ❷
virtual_router_id 12 # ❸
priority 101 # ❹
virtual_ipaddress {
2001:db8:ff/64
}
}
The state keyword in ❶ instructs Keepalived to not take the leader
role when starting. Otherwise, incoming nodes create a temporary
disruption by taking over the IP address until the election settles.
The interface keyword in ❷ defines the interface for sending and
receiving VRRP packets. It is also the default interface to configure
the virtual IP address. The virtual_router_id directive in ❸ is
common to all nodes sharing the virtual IP. The priority keyword in
❹ helps to choose which router will be elected as leader. If you need
more information about Keepalived, be sure to check the
documentation[3].
VRRP design is tied to Ethernet networks and requires a multicast-enabled network for communication between nodes. In some environments, notably public clouds, multicast is unavailable. In this case, Keepalived can send VRRP packets using unicast:
vrrp_instance gateway1 {
state BACKUP
interface eth0
virtual_router_id 12
priority 101
unicast_peer {
2001:db8::11
2001:db8::12
}
virtual_ipaddress {
2001:db8:ff/64 dev lo
}
}
Another process, like a BGP daemon, should advertise the virtual IP
address to the “network.” If needed, Keepalived can trigger whatever
action is needed for this by using notify_* scripts.
Until version 2.1.0, the interface directive is mandatory and Keepalived
will transmit and receive VRRP packets on this interface only. If peers are
reachable through several interfaces, like on a BGP on the host[4] setup, you
need a workaround. A simple one is to use a VXLAN interface:
$ ip -6 link add keepalived6 type vxlan id 6 dstport 4789 local 2001:db8::10 nolearning
$ bridge fdb append 00:00:00:00:00:00 dev keepalived6 dst 2001:db8::11
$ bridge fdb append 00:00:00:00:00:00 dev keepalived6 dst 2001:db8::12
$ ip link set up dev keepalived6
Learning of MAC addresses is disabled and one generic entry for each peer is added in the forwarding database: transmitted packets are broadcasted to all peers, notably VRRP packets. Have a look at “VXLAN & Linux[5]” for additional details.
vrrp_instance gateway1 {
state BACKUP
interface keepalived6
mcast_src_ip 2001:db8::10
virtual_router_id 12
priority 101
virtual_ipaddress {
2001:db8:ff/64 dev lo
}
}
Starting from Keepalived 2.1.0, unicast_peer can be used without
the interface directive[6]. I think using VXLAN is still a
neat trick applicable to other situations where communication using
broadcast or multicast is needed, while the underlying network provides
no support for this.