Keepalived and unicast over multiple interfaces
Vincent Bernat
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 is a Linux implementation of VRRP. 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.
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 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” 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. 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.