I've been searching for a way to add and remove backend servers from HAProxy dinamically, is there a wrapper or even an API to handle it? I want to make an auto-scale system with HAProxy and DigitalOCean. Others load-balancers are welcome.
Add/remove backend servers from HAProxy with command line
autoscalinghaproxy
Related Solutions
The easiest solution would be just use DNS to map foo.cust.mydomain.example
to a specific server IP, as womble suggested. This would skip the entire proxy server. Perhaps this is not possible for you, for example if you do not have public IP addresses for the backend servers.
Directing all requests to one server (with a wildcard DNS) and then forwarding the requests dynamically according to the Host header is a bit more complicated, and it seems HAProxy cannot do this, because every backend server must be explicitly defined in HAProxy configuration.
Nginx, though, is different, with right configuration Nginx can use Host header to choose the backend. Nginx needs a DNS server that maps names to backend addresses, of course.
Here is a small example of the configuration:
server {
listen 80 default;
location / {
# You might need to send some headers to the backend server
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
resolver 192.0.2.1; # DNS server IP
# Forward all requests to the backend server using $http_host
# (this is the 'Host:' header value)
proxy_pass http://$http_host$request_uri;
}
}
This redirects http://myserver.cust.mydomain.example/foo/
to http://myserver.cust.mydomain.example/foo/
. Does not seem very helpful at first sight. But if you set up a private DNS server that maps those names to a backend server addresses, the request actually gets forwarded to a correct backend server on a private address.
But, this kind of DNS server setting might not be desired, and could cause problems in some cases. So, with some additions to the Nginx config, we can take another approach:
location / {
# headers...
resolver 192.0.2.1;
# A regex to get the first part (hostname) from the Host header
if ($http_host ~* "([a-z0-9-]+)(\.[a-z0-9-]+)*") {
# Save a captured part from the regex to a variable
set $redirect_hostname $1;
# Pass the request to a desired backend
proxy_pass http://$redirect_hostname.private.mydomain.example$request_uri;
}
}
Now redirect goes from http://myserver.cust.mydomain.example/foo/
to http://myserver.private.mydomain.example/foo/
. The DNS server can hold private addresses under different domain, and proxy_pass
directive can be modified to match the desired name server configuration.
I still think this kind of proxying might not be the easiest way to solve the whole picture, but it's one possibility after all. I'm happy if this was of any help.
References: Nginx Wiki, especially HttpProxyModule and HttpRewriteModule
First, your rule should also keep the HTTP version part.
Second, why don't you use the "force-persist" statement for this ? It's designed exactly for this role. Just find something in your request that makes it different from your visitors', set a cookie to access it, then you can use this server. This me chanism was made precisely for maintenance operations without having to make the server appear as up for other users.
Alternatively in your case you could also use the "redirect" method, as it supports the "set-cookie" option; In your frontend, you would then replace the use_backend rule with something like this :
redirect location / code 302 set-cookie SERVERID=live03 if acl_patch
Your browser would then learn this cookie and redirect to the /, where server 3 will handle the request. There's even a clear-cookie option that can be used to get rid of the stickiness if you want.
Best Answer
There is no API or anyway to do what you want. You need to add the backends into the config and do a graceful reload.
What that does is it spins off another haproxy process to handle the traffic and the other process waits till it finishes and quits. You should be able to reload haproxy with no connection refused or bad requests.