In HAProxy, Can I switch backends on the basis of health checks? - haproxy

Consider we have two backends say backend_1 and backend_2.
I have a requirement to always move traffic to backend_1 and use backend_2 only if backend_1 servers health checks fail.
Is it possible in HAProxy?

In haproxy keyword backend is a group of servers. So solution depends on what you need.
If you mean backend in general sense, as servers then backup keyword is the answer:
frontend foo
bind *:80
default_backend bar
backend bar
option allbackups
server bar1 10.0.0.1:80 check
server bar2 10.0.0.2:80 check
server bar3 10.0.1.1:80 check backup
server bar4 10.0.1.2:80 check backup
I added 4 servers to backend and option allbackups to make it behave similar to the next example.
If you mean backend in haproxy sense as group of servers then nbsrv will be useful:
frontend front
bind *:80
acl is_foo_alive nbsrv(foo) -m int gt 0
use_backend foo if is_foo_alive
use_backend bar
backend foo
server foo1 10.0.0.1:80 check
server foo2 10.0.0.2:80 check
backend bar
server bar1 10.0.1.1:80 check
server bar2 10.0.1.2:80 check
nbsrc(foo) tells us how many servers are up in backend foo, so if we get more than 0, then we use backend foo. If not, we use next rule, which is use_backend bar.
Those solutions are similar, but may differ depending on how backends differ (e.g. manipulation of HTTP headers, HTTP authentication, etc.) and whether you use session stickiness.

Related

Append or Strip path to individual server in backend - HAProxy

First, a thank you for taking the time
I would like to add/remove a path /somepath in the backend for just one server where there are two servers LB. Let me give you an example. In the below one server 10.0.0.10 accepts traffic with /somepath but the other server 10.0.0.20 doesn’t require the /somepath. If I use a reqrep and strip /somepath it would strip it for both servers, however, I would want it to be stripped/add to only one server in the backend. I am using Haproxy version 1.5.
mode http
balance roundrobin
server webtest1 10.0.0.10:80 weight 90
server webtest2 10.0.0.20:80 weight 10

HAProxy redirect port and mask url

I have a couple of webservers that are reachable directly through the following URL:
https://abcd.example.com:8445/desktop/container/landing.jsp?locale=en_US
https://wxyz.example.com:8445/desktop/container/landing.jsp?locale=en_US
I need to use HAProxy to loadbalance between the two and use the following URLs instead when hitting the frontend:
http://1234.example.com/desktop/container/landing.jsp?locale=en_US
or
https://1234.example.com:8445/desktop/container/landing.jsp?locale=en_US
So other requirements beside the two above:
If initial traffic is port 80, convert to port 8445
Mask the URL so that on the browser while it redirected to https and port to 8445, the host remains intact, like so: https://1234.example.com:8445/desktop/container/landing.jsp?locale=en_US
Here's my config so far:
frontend WebApp_frontend
mode http
bind 10.4.34.11:80
acl is80 dst_port 80
http-request set-uri https://%[req.hdr(Host)]:8445%[path]?%[query] if is80
default_backend WebApp-backend
backend WebApp_backend
description WebApp
balance roundrobin
mode http
server webserver1 10.2.89.222:8445 check inter 5s fall 3 rise 5 downinter 1m ssl verify none
server webserver2 10.4.89.223:8445 check inter 5s fall 3 rise 5 downinter 1m ssl verify none
The problem I'm facing right now is that when you access the frontend, HAProxy will redirect you to any of the webservers and force your client to hit the webserver directly instead of through the HAProxy. I need the connection to remain through the HAProxy.
If all your application is doing is redirecting to HTTPs then you should probably just handle that directly within HAProxy. You might want to also explore whether your application supports X-Forwarded-Proto and X-Forwarded-Host.
Another option is you can have HAProxy rewrite the redirects from the backend application to the hostname you choose. Using HAProxy 2.1 you would do something like this:
http-response replace-header location https?://[^:/]*(:?[0-9]+/.*) https://1234.example.com\1 if { status 301:302 }

haproxy stick to group of backend servers

So I am struggling to find the correct config for my haproxy:
I have Ruby on Rails web application which is served by two physical hosts, each having 3 workers. The two hosts each have a database, and the two databases are synchronised in real time.
I am trying to have sessions stick to the same host, so requests are still load balanced across the 3 workers in each host.
The objective is to avoid two consecutive requests from the same client being sent to different hosts.
My config looks like this:
frontend web_front
bind *:4100
default_backend web_back
backend web_back
cookie SERVERID insert indirect nocache
balance roundrobin
server host_1_web_1 129.168.0.1:3000 maxconn 1 check cookie SRV_1
server host_1_web_2 129.168.0.1:3001 maxconn 1 check cookie SRV_1
server host_1_web_3 129.168.0.1:3002 maxconn 1 check cookie SRV_1
server host_2_web_1 129.168.0.2:3000 maxconn 1 check cookie SRV_2
server host_2_web_2 129.168.0.2:3001 maxconn 1 check cookie SRV_2
server host_2_web_3 129.168.0.2:3002 maxconn 1 check cookie SRV_2
As you can see, I have set the cookie of each host to the same value, hopping that requests would be still load balanced properly accross workers, but now only the first worker of each host seems to be getting requests.
Is there a way around this? Perhaps using sticky-tables?
If I am correctly understanding you requirements, you want two different levels of load balancing:
1. Server load balancing using session persistence
2. Worker load balancing without session persistence.
One solution would be to have a service in the server side listening for HAProxy connections and doing the load balance across the workers.
But you still can do this with HAProxy by using a dummy backend:
frontend web_front
bind *:4100
default_backend web_back
backend web_back
cookie SERVERID insert indirect nocache
balance roundrobin
server server1 127.0.0.1:3001 cookie SRV_1
server server2 127.0.0.1:3002 cookie SRV_2
listen lt_srv1
bind 127.0.0.1:3001
server host_1_web_1 129.168.0.1:3000 check
server host_1_web_2 129.168.0.1:3001 check
server host_1_web_3 129.168.0.1:3002 check
listen lt_srv2
bind 127.0.0.1:3002
server host_2_web_1 129.168.0.2:3000 check
server host_2_web_2 129.168.0.2:3001 check
server host_2_web_3 129.168.0.2:3002 check

haproxy: set timeout if <condition>

The question seems to be quite straight and easy, however I have not been able to find a proper answer.
In haproxy I have 1 backend, say:
backend-1
and 2 frontends, say:
frontend-1
frontend-2
In the backend stanza I want to set a "timeout server" parameter, but, only if the connection comes from frontend-1.
As I didn't find anything I tried to figure it out myself:
backend backend-1
bind *:80
option <blahblah_option>
timeout server 1d if frontend frontend-1
This syntax does not work, and I am mentioning it to let understand what I am trying to achieve.
This is not doable yet in HAProxy.
Later, you will be able to set timeouts using tcp-request and http-request rules.
What we usually do to workaround this for now, is that we setup 2 backends using the same parameters, but different timeout servers.
This is useful when a few urls only deserve a long server timeout.
Edit followup your comment about multiple health checks:
Well, that's why the server's 'track' directive exists:
backend my_app
server srv1 10.0.0.1:80 check
backend my_app_longtime
server srv1 10.0.0.1:80 track my_app/srv1
In the conf above, the server in my_app_longtime backend won't be checked. That said, it will follow up the same state than srv1 in the backend my_app.
Baptiste
Baptiste
I did it like this and it worked. It made it possible to extend timeout on specific app urls, which are more time consuming. Used that trace health check - thanks Babtiste.
frontend www-http
bind 10.0.0.1:80
default_backend app
acl long_url path_beg -i /long_url
use_backend app-extended if long_url
backend app
server web-1 10.0.0.2:80 check
backend app-extended
server web-1 10.0.0.2:80 trace app/web-1
timeout server 10m

Combine HAProxy stats?

I have two instances of HAProxy. Both instances have stats enabled and are working fine.
I am trying to combine the stats from both instances into one so that I can use a single HAProxy to view the front/backends stats. I've tried to have the stats listener on the same port for both haproxy instances but this isn't working. I've tried using the sockets interface but this only reports on one of the interfaces as well.
Any ideas?
My one haproxy config file looks like this:
global
daemon
maxconn 256
log 127.0.0.1 local0 debug
log-tag haproxy
stats socket /tmp/haproxy
defaults
log global
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend http-in
bind *:8000
default_backend servers
log global
option httplog clf
backend servers
balance roundrobin
server ws8001 localhost:8001
server ws8002 localhost:8002
log global
listen admin
bind *:7000
stats enable
stats uri /
The other haproxy config is the same except the front/backend server IPs are different.
While perhaps not an exact answer to this specific question, I've seen this kind of question enough that I think it deserves to be answered.
When running with nbproc greater than 1, the Stack Exchange guys have a unique solution. They have a listen section that receives SSL traffic and then uses send-proxy to 127.0.0.1:80. They then have a frontend that binds to 127.0.0.1:80 like this: bind 127.0.0.1:80 accept-proxy. Inside of that frontend they then bind that frontend, e.g. bind-process 1 and in the globals section the do the following:
global
stats socket /var/run/haproxy-t1.stat level admin
stats bind-process 1
The advantage of this is that they get multiple cores for SSL offloading and then a single core dedicated to load balancing traffic. All traffic ultimately flows through this frontend and therefore they can accurately measure stats from that frontend.
This can't work. Haproxy keeps stats separated in each process. It has no capabilities to combine stats of multiple processes.
That said, you are of course free to use external monitoring tools like (munin, graphite or even nagios) which can aggregate the CSV data from multiple stats sockets and display them in unified graphs. These tools are however out-of-scope of core haproxy.