Part of collection: Hyper-converged Homelab with Proxmox
Keepalived is a Loadbalancer to add ‘high availability` to Linux systemen. See the Keepalived documentatie for more background information.
This is my implementation of two Pi-hole servers in a high availability configuration, with Keepalived for failover purposes and Orbital Sync for synchronizing the Pi-hole configuration.
For this to work and make sense, the two Pi-hole servers need to be in sync, I have Orbital Sync running as a Service inside my Docker Swarm. I only edit my Pi-hole configuration on the Master Node (192.168.1.155), from where the config synchronizes every 15 minutes to the Slave Node (192.168.1.166).
To use Oribital Sync; spin up a Docker Container based on the orbital-sync-yml configuration below.
Note: The Google SMTP Service I use, requires an App Passwords. To create it go to Google Account and 'Select Security / "Signing in to Google," / 2-Step Verification' At the bottom of that page, select App passwords and add one.
This setup is using a virtual ip address: 192.168.1.3, which is the only ip address that DNS clients need to have configured as their DNS server.
On Pi-hole01: 192.168.1.155
Execute these commands:
sudo apt-get install keepalived -y
sudo mkdir /etc/scripts
sudo sh -c "curl https://gist.githubusercontent.com/Drallas/e61e4ebc1eaa2e52f21597fc8f2f43b8/raw/eca7ce1061e7fc4b2c801fe693aa02c34f758963/script-chk_ftl -o /etc/scripts/chk_ftl"
sudo chmod +x /etc/scripts/chk_ftl
# Add the configuration to the server
sudo curl https://gist.githubusercontent.com/Drallas/e61e4ebc1eaa2e52f21597fc8f2f43b8/raw/08ad959f6db894b0402a3ce7178d4da86f4f2d21/script-keepalived-master.conf -o /etc/keepalived/keepalived.conf
# Start keepalived
systemctl enable --now keepalived.service
systemctl status keepalived.service
On Pi-hole02: 192.168.1.166
Execute these commands:
sudo apt-get install keepalived -y
sudo mkdir /etc/scripts
sudo sh -c "curl https://gist.githubusercontent.com/Drallas/e61e4ebc1eaa2e52f21597fc8f2f43b8/raw/eca7ce1061e7fc4b2c801fe693aa02c34f758963/script-chk_ftl | tr -d '\r' > /etc/scripts/chk_ftl"
sudo chmod +x /etc/scripts/chk_ftl
# Add the configuration to the server
sudo curl https://gist.githubusercontent.com/Drallas/e61e4ebc1eaa2e52f21597fc8f2f43b8/raw/08ad959f6db894b0402a3ce7178d4da86f4f2d21/script-keepalived-slave.conf -o /etc/keepalived/keepalived.conf
# Start keepalived
systemctl enable --now keepalived.service
systemctl status keepalived.service
Keepalived should now be active, time to test if it's working correctly.
Note: on Vm's
vrrp_track_process
can also be used as an alternative forvrrp_script
, but on RaspberryPI PC's and LXC containers this doens't work!
Open the Pi-hole interface on the virtual IP we configured previously (e.g. http://192.168.1.3/admin) it should show the hostname of the Master Pi-hole (pihole01).
Shut down the Master Pi-hole (or systemctl stop pihole-FTL
) and refresh the browser, it should now show the hostname of the Slave Pi-hole (pihole02).
From a workstation use this commandline script:
while true; do nslookup gist.github.com 192.168.1.3; sleep 1; done
To test if DNS lookups are not interrupted when the Master Pi-hole Node is taken offline, stop the Pi-hole service systemctl stop pihole-FTL
on the Pi-hole Master Node.
The nslookup command should keep on resolving uninterrupted.
Failover
To visualize the failover on Pi-hole Nodes; execute ip -br a
and check if the virtual-ip (192.168.1.3), moves from the Master to the Slave Node, a few seconds after stopping the pihole-FTL service.
# Master Node
ip -br a
lo UNKNOWN 127.0.0.1/8
eth0@if62 UP 192.168.1.155/24 192.168.1.3/24
ip -br a
lo UNKNOWN 127.0.0.1/8
eth0@if62 UP 192.168.1.155/24
# Slave Node
ip -br a
lo UNKNOWN 127.0.0.1/8
eth0@if26 UP 192.168.1.166/24
ip -br a
lo UNKNOWN 127.0.0.1/8
eth0@if26 UP 192.168.1.166/24 192.168.1.3/24
Make sure to start the pihole-FTL service again: systemctl start pihole-FTL
and that it's healthy systemctl status pihole-FTL
.