Keepalived and libvirt MACVTAP network interfaces
Keepalived is a routing software written in C that can be used to setup load balancing and high availiability for Linux machines.
NOTE 1: For the sake of simplicity, in this exampe we will consider a cluster of two CentOS Stream virtual machines with firewalld and iptables disabled.
NOTE 2: virtualization host is Fedora 33 server with libvirt
and qemu/kvm
.
CentOS Stream
Install keepalived
:
$ dnf install keepalived
Add nginx repo to the system: repo.
It will be use to check that keepalived is actually working:
$ dnf install nginx
$ systemctl enable --now nginx
Configure keepalived
:
$ vi /etc/keepalived/keepalived.conf
---
vrrp_script chk_nginx {
script "/etc/keepalived/scripts/nginx-check.sh"
interval 2 # run script every 2 seconds
weight 2 # add 2 points if OK
}
vrrp_instance VI_1 {
interface enp2s0 # interface to monitor
state MASTER # MASTER on host1, BACKUP on host2
virtual_router_id 51
priority 101 # MASTER 101, BACKUP 100
advert_int 1
#nopreempt # decomment to not have the VIP go back to master when it goes back online
authentication {
auth_type PASS
auth_pass myPass # maximum 8 chars
}
virtual_ipaddress {
10.10.0.12/24 # virtual ip address
}
track_script {
chk_nginx
}
}
Also add a script to check if nginx
is alive and well:
$ mkdir /etc/keepalived/scripts
$ vi /etc/keepalived/scripts/nginx-check.sh
---
#!/bin/sh
if [ -z "`pidof nginx`" ]; then
exit 1
fi
---
$ chmod 755 /etc/keepalived/scripts/nginx-check.sh
libvirt and qemu/KVM caveats
In my case I have two virtual machine each configured with one MACVTAP virtual
network adapter.
Apparently libvirt MACVTAP network interfaces doesn’t actually pass all
traffic going from host to guests and vice versa.
This unfortunate behavior makes it impossible for keepalived to receive
packets, meaning that both machines will try to elavate themselves to MASTER
status.
To avoid this conflict, add trustGuestRxFilters='yes'
parameter to the
virtual network adapter config:
$ virsh edit <vm_name>
---
...
<interface type='direct' trustGuestRxFilters='yes'>
...
</interface>
...