Keepalived and unicast over multiple interfaces

Vincent Bernat

Up­date (2022-11)

Since Keepalived 2.1.0, the hack de­scribed here is not needed any­more: the interface di­rec­tive in vrrp_​instance is not re­quired anymore.

Keepalived is a Linux im­ple­men­ta­tion of VRRP. The usual role of VRRP is to share a vir­tual IP across a set of routers. For each VRRP in­stance, a leader is elected and gets to serve the IP ad­dress, en­sur­ing the high avail­abil­ity of the at­tached ser­vice. Keepalived can also be used for a generic leader elec­tion, thanks to its abil­ity to use scripts for health check­ing and run com­mands on state change.

A sim­ple con­fig­u­ra­tion looks like this:

vrrp_instance gateway1 {
  state BACKUP          # ❶
  interface eth0        # ❷
  virtual_router_id 12  # ❸
  priority 101          # ❹
  virtual_ipaddress {
    2001:db8:ff/64
  }
}

The state key­word in ❶ in­structs Keepalived to not take the leader role when start­ing. Oth­er­wise, in­com­ing nodes cre­ate a tem­po­rary dis­rup­tion by tak­ing over the IP ad­dress un­til the elec­tion set­tles. The interface key­word in ❷ de­fines the in­ter­face for send­ing and re­ceiv­ing VRRP pack­ets. It is also the de­fault in­ter­face to con­fig­ure the vir­tual IP ad­dress. The virtual_​router_id di­rec­tive in ❸ is com­mon to all nodes shar­ing the vir­tual IP. The priority key­word in ❹ helps to choose which router will be elected as leader. If you need more in­for­ma­tion about Keepalived, be sure to check the doc­u­mentation.

VRRP de­sign is tied to Eth­er­net net­works and re­quires a mul­ti­cast-en­abled net­work for com­mu­ni­ca­tion be­tween nodes. In some en­vi­ron­ments, no­tably pub­lic clouds, mul­ti­cast is un­avail­able. In this case, Keepalived can send VRRP pack­ets us­ing 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
  }
}

An­other process, like a BGP dae­mon, should ad­ver­tise the vir­tual IP ad­dress to the “net­work.” If needed, Keepalived can trig­ger what­ever ac­tion is needed for this by us­ing notify_* scripts.

Un­til ver­sion 2.1.0, the interface di­rec­tive is manda­tory and Keepalived will trans­mit and re­ceive VRRP pack­ets on this in­ter­face only. If peers are reach­able through sev­eral in­ter­faces, like on a BGP on the host setup, you need a work­around. A sim­ple one is to use a VXLAN in­terface:

$ 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

Learn­ing of MAC ad­dresses is dis­abled and one generic en­try for each peer is added in the for­ward­ing data­base: trans­mit­ted pack­ets are broad­casted to all peers, no­tably VRRP pack­ets. Have a look at “VXLAN & Linux” for ad­di­tional 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
  }
}

Start­ing from Keepalived 2.1.0, unicast_​peer can be used with­out the interface di­rec­tive. I think us­ing VXLAN is still a neat trick ap­pli­ca­ble to other sit­u­a­tions where com­mu­ni­ca­tion us­ing broad­cast or mul­ti­cast is needed, while the un­der­ly­ing net­work pro­vides no sup­port for this.