
Pihole in HA mode
Pihole is the central point of resolving internal and external domains in my homelab. Running this on only one device is a classical SPOF so I run two separate instances on two physical devices in HA mode.
In my homelab I decided to use two spare Raspberry Pis doing all DNS resolving. Even my Fritzbox uses the Pihole devices as custom DNS server. The problem is, that the Fritzbox can only take one IP as DNS server server. There is no builtin logic running Pihole in a typical high availability (HA) setup like one Pihole goes down and the other one kicks in.
So even having two devices running Pihole, Fritzbox would only use one for resolving names, which is a single point of failure (SPOF).
Floating IP
The solution would be having a floating IP that jumps to the device, which can handle the current request. If both are up, there is a primary instance, and one or multiple secondary instances.
Fortunately there is keepalived which brings load balancing and high availability to Linux.
[…] keepalived runs a set of health checkers that watch each server pool and decide, in real time, whether a real server stays in the topology or drops out according to its health.
keepalived ships in most Linux distributions. I use Raspberry Pi OS Lite, the headless version without any desktop environment.
My current Pihole setup is:
- Pihole 1: x.x.x.18
- Pihole 2: x.x.x.19
- Floating IP: x.x.x.53
On the Raspberry Pis I rolled out this configuration, with a different
priority value, to define the primary and seconday instance.
1global_defs {
2 enable_script_security
3 script_user root
4}
5
6vrrp_script chk_pihole {
7 // Replace with your actual IP
8 script "/usr/bin/dig +short +time=1 +tries=1 pi.hole @x.x.x.19"
9 // Check each 2 seconds
10 interval 2
11 // Require 2 consecutive failures mark node as down
12 fall 2
13 // Require 2 consecutive successes to mark as healthy again
14 rise 2
15}
16
17vrrp_instance pihole {
18 state BACKUP
19 interface eth0
20 virtual_router_id 53
21 priority 100
22 advert_int 1
23
24 virtual_ipaddress {
25 x.x.x.53/24 // Replace with your actual IP
26 }
27
28 track_script {
29 chk_pihole
30 }
31}In the healthcheck script you define how often a check can fail or should
succeed to trigger failed or healthy states. In the example above, a check
each 2 seconds with fall 2 means a failover after 4 seconds
Result
The only IP address that Fritzbox hands out to all my devices is x.x.x.53
which is a floating, load balanced IP what either one of my Raspberry Pis answers.
I can update one Pi while the other one automatically serves all DNS requests.