Sometimes there are no duplicates, but usually there’s a couple of them.
I thought that there’s some sort of race condition here (when haproxy starts the DNS resolver responds with only some IPs), but the behavior is identical after reload:
$ docker compose exec haproxy kill -HUP 1
What am I doing wrong? How do I make haproxy connect to all the servers?
On a side note, set server http/s1 state ready always returns “No such server.” But the command works with http/s2, http/s3, http/s4. Anything wrong on my part here?
hello, if you have a resolvers section, try adding accepted_payload_size 8192 because the default of 512 bytes may be too small to fit more SRV records to populate your template.
In the OP I gave a link to a minimal reproducible example (GitHub gist). And yes, I don’t have the resolvers section. The reason I think it has nothing to do with accepted_payload_size is because it sometimes resolves to all 4 IPs. It’s just that usually it doesn’t. I tried it with 2 and 3 IPs, and it still doesn’t always resolve to all of them. And I don’t use SRV records. Can’t it be solved without a resolvers section? What resolvers section corresponds to the default settings? To be frank it potentially looks like a bug. At least I fail to understand what going on here.
The libc resolution is not designed for this. It will resolve the hostnames 4 times and use the first address in the answer. As such in this particular configuration you get completely random behaviour. You could have 4 times the same IP.
You need to switch to resolvers and disable libc resolution. It’s 2 lines after the global section like this:
I wrote my answer before I saw the @lukastribus reply so I guess I post it as is:
Okay, without the resolvers section haproxy calls getaddrinfo() 4 times, takes the first address and with luck obtains 4 different IPs. I’m not sure why it doesn’t call it once, because getaddrinfo() returns all the 4 IP addresses. There’s probably some reason, but it escapes me.
it starts to resolve the hostname continuously and in this case it succeeds. Unless allow-dup-ip is set. Which is by default not. It succeeds because it doesn’t let duplicates in this case.
I guess I’m starting to understand. init-addr is responsible for initial resolution that happens during initialization. And if I attach resolvers it starts to periodically reresolve the domain (at run time).
server-template s 4 app:80 check init-addr libc,none resolvers docker
Since at the moment I have only one listen section. But not that it matters much.
Don’t you know by any chance why libc resolution can’t resolve the domain once and use all the IPs? I think that’s more expected and can be useful. To me the libc method looks similar to what the default resolvers section does. I’m not sure if the latter uses getaddrinfo(), but at least they use the same DNS server.
libc resolution is was always supported, however it is a synchronous API so it cannot be used during runtime (because haproxy is a event-loop based application).
Usually people doing service discovery via DNS also need runtime updates, it’s not enough to just resolve the IPs once at startup.
Therefor to allow for service discovery via DNS a internal resolver was written that supports all this.
libc resolution itself was never really upgraded to support multiple answers, because we already have the resolver for this, and like I said it’s very rare that someone needing service discovery is ok with just resolving DNS records once.