Reconfiguring haproxy backend dynamically

haproxyhttpreverse-proxy

My requirement is to have ~50 haproxy http backends, which will be added and removed dynamically (without my involvement) anywhere on the internal network. I can assume that each http backend knows its IP address and knows the IP address of haproxy. I can assume that I can add a little bit of code to each http backend, to allow it to register with haproxy whenever it spins up and deregister before it spins down.

I have haproxy listening on port 80:

frontend main *:80

Additionally I expose a stat socket:

stats socket 0.0.0.0:8080

My setup works & in particular I can connect to the stats socket using socat readline TCP4:<haproxyIP>:8080

Let us assume that we have two http backends serving on 10.0.0.1:4040 and 10.0.0.2:4040, and that haproxy can reach both addresses.

What stat socket command do I need to issue over the stat socket so that any request to <haproxyIP>:8080/backend1/status is routed to 10.0.0.1:4040/status and any request to <haproxyIP>:8080/backend2/version is routed to 10.0.0.2:4040/version?

In general: how do I dynamically proxy http requests from [GET|POST] <haproxyIP>:<haproxyPort>/<backendID>/<remainingPath> to [GET|POST] <backendIP>:<backendPort>/<remainingPath> given that I know a map from backendID -> backendIP, backendPort.

Best Answer

If all of your requests arriving to this frontend are in such form:

frontend main
    bind *:80 # Use separate bind directives as they are supported by new HAProxy versions
    use_backend %[path,fields(2,/)]

backend backend1
    reqrep ^([^\ :]*)\ /backend1/(.*)     \1\ /\2
    server foo ...

backend backend2
    reqrep ^([^\ :]*)\ /backend2/(.*)     \1\ /\2
    server bar ...

If you have some requests that are not in this format, you can add more use_backend-s or a default_backend. You can also have the orchestration tool that generates the config generate a flat file with all the backend names and you can then use it for even more logic

acl existing_backends path -f all_backends.txt -m beg

Where the all_backends.txt would look like:

/backend1/
/backend2/
...

Depending on the exact HAProxy version you are using, this could be somewhat optimzied (using quotes, variables, etc.), but this way it should work with 1.5+.

Related Topic