I've experimenting with a docker-swarm setup that runs, among other things, Traefik (on manager node) and Pi-Hole (on manager node and worker node). There are 3 working configurations, with drawbacks, and I'm hoping someone can illuminate me on potential solutions!
expose 53 over ingress network
Running pihole as-is, using port 53 published over the swarm ingress network, makes sure that DNS queries are load balanced by docker. However, Pi-Hole cannot differentiate client IP's anymore (pihole recommends running host-exposed ports to accomplish this), so each request is logged as originated from the docker-swarm manager node.
load balance 53 over traefik
Having traefik listen on tcp/udp 53 and then use the docker-swarm integration (add traefik labels on the pihole docker config for tcp, udp and http) works OK as well: traffic is load balanced. However, now all calls seems to originate from 'traefik.container.name'. Same problem, different layer.
expose ports on host
Expose 53 on the host port. This allows the proper resolve of each client IP, however, load balancing is not managed by docker anymore (as the ingress network is bypassed). I guess I could try load balancing through Traefik by manually setting the different host IP's, but that would not be taking into account newly created nodes, removed containers, ..., so it feels like a less desirable approach.
So, getting a fresh idea as to getting pihole to behave in a docker swarm, potentially combined with Traefik, would be great. This would mean 1) automatically load balancing to the various pihole containers 2) resolving client ip's properly.
You can load-balance pihole with traefik, but you will still have to expose the ports for traefik using host networking.
The remaining issue with this as the clients need the ip of the traefik node. By default a linux hosts resolv.conf allows a max of 3 resolvers. I'm not up to date with how resolvconf/systemd-resolved/windows/mac would handle an offline dns server, but I'm relatively confident they allow 3 (whether or not a given router /dhcp server does is another question).
So if you have 3 nodes(minimum viable swarm) where traefik will run just adding those ip's as the resolvers may work.
Beyond that another solution in front of, or in conjunction with traefik is needed. I'm thinking of foating ip with keepalived/corosync.
I am trying to solve this as well. Has there been any progress from anyone on this thread?
I suppose you could use macvlan and attach pihole with only port 53/tcp/udp published to assign an ip from the router's subnet. This would then be the DNS server IP instead of traefik. The only thing traefik would load balance are port 80 requests to pihole. You would lose out the full load balancing feature. I think the other issue would be to allocate IP's on the router for all the instances. Possibly ip conflict if there isn't a proper rule set to terminate an ip lease.