Perform http health check on backend servers with haproxy - haproxy

Is it possible to perform HTTP healthcheck on individual backend servers and load balance among active backend servers.
This works fine with single backend server when we mention host name in httpchk (option httpchk GET /info HTTP/1.1 Host:\ abc.mysrv1.com)
However i am unable to successfully configure it with multiple backend servers as i can't give individual host name on httpchk command and with below backend configuration getting http 400 error -
backend svc.op
balance roundrobin
mode http
http-send-name-header Host
option httpchk GET /info HTTP/1.1
http-check send-state
http-request set-uri /test/abcService
server abc.mysrv1.com abc.mysrv1.com:80 check
server abc.mysrv2.com abc.mysrv2.com:80 check
[WARNING] 115/162226 (4788) : Server svc.op/abc.mysrv1.com is DOWN, reason: Layer7 wrong status, code: 400, info: "Bad Request: missing required Host header", check duration: 1ms. 1 active and 0 backup servers left. 0 sessions active, 0 requeued, 0 remaining in queue.
[WARNING] 115/162227 (4788) : Server svc.op/abc.mysrv2.com is DOWN, reason: Layer7 wrong status, code: 400, info: "Bad Request: missing required Host header", check duration: 0ms. 0 active and 0 backup servers left. 0 sessions active, 0 requeued, 0 remaining in queue.
[ALERT] 115/162227 (4788) : backend ' svc.op' has no server available!
$ ./haproxy -version
HA-Proxy version 1.6.7 2016/07/13
UPDATE:
I didn't pursue this but someone suggested following -
backend h_a01
mode http
option httpchk GET /health HTTP/1.1\r\nHost:\ a01\r\n
http-check expect rstatus ^200
http-request set-uri /hello/world
http-request set-header Host a01
server a01 a01 check
backend h_a02
mode http
option httpchk GET /health HTTP/1.1\r\nHost:\ a02\r\n
http-check expect rstatus ^200
http-request set-uri /hello/world
http-request set-header Host a02
server a02 a02 check
backend a
mode http
option forwardfor
http-send-name-header Host
http-request set-uri /hello/world
server a1 a1 track h_a01/a01
server a2 a2 track h_a02/a02

Related

How to link frontend to backend when the path request are different?

I have an Haproxy set with https offloadin, and I'm trying to correctly point the requests made to frontend to it's corresponding backend, but bumped into some obstacles.
I have a backend server on http://:9000/abc (NOT in root of the webserver) and when I set a frontend with https:///abc the pointing works as expected and I see the login page.
But I also have another backend server, which is on http://:8888 (IN the root of webserver, it makes it's own redirect to http://:8888/def) and I want it to be accessible by https:///def. But in this case the pointing doesn't work.
How can I make https:///def point to http://:8888 ? Heres is my .cfg
Using HAproxy 1.7
# Automaticaly generated, dont edit manually.
# Generated on: 2019-01-28 13:59
global
maxconn 1000
stats socket /tmp/haproxy.socket level admin
uid 80
gid 80
nbproc 1
hard-stop-after 15m
chroot /tmp/haproxy_chroot
daemon
tune.ssl.default-dh-param 2048
server-state-file /tmp/haproxy_server_state
listen HAProxyLocalStats
bind 127.0.0.1:2200 name localstats
mode http
stats enable
stats refresh 10
stats admin if TRUE
stats show-legends
stats uri /haproxy/haproxy_stats.php?haproxystats=1
timeout client 5000
timeout connect 5000
timeout server 5000
frontend shared-frontend-merged
bind 200.129.168.14:443 name 200.129.168.14:443 no-sslv3 ssl crt-list /var/etc/haproxy/shared-frontend.crt_list
mode http
log global
option http-keep-alive
option forwardfor
acl https ssl_fc
http-request set-header X-Forwarded-Proto http if !https
http-request set-header X-Forwarded-Proto https if https
timeout client 30000
acl aclcrt_shared-frontend var(txn.txnhost) -m reg -i ^ifamcmc\.ddns\.net(:([0-9]){1,5})?$
acl ACL1 var(txn.txnpath) -m sub -i abc
acl ACL2 var(txn.txnpath) -m sub -i def
http-request set-var(txn.txnhost) hdr(host)
http-request set-var(txn.txnpath) path
use_backend glpi_ipvANY if ACL1
use_backend ciweb_ipvANY if ACL2
frontend http-to-https
bind 200.129.168.14:80 name 200.129.168.14:80
mode http
log global
option http-keep-alive
timeout client 30000
http-request redirect scheme https
backend abc_ipvANY
mode http
id 102
log global
timeout connect 30000
timeout server 30000
retries 3
option httpchk OPTIONS /
server abc 10.100.0.30:9000 id 103 check inter 1000
backend def_ipvANY
mode http
id 104
log global
timeout connect 30000
timeout server 30000
retries 3
option httpchk OPTIONS /
server def 10.100.0.40:8888 id 105 check inter 1000
I expect that access to https:///def correctly points to the backend at http://:8888
https://<my.address.com>/abc ------> http://<internal_ip>:9000/abc (OK)
https://<my.address.com>/def ------> http://<internal_ip_2>:8888 (NOT OK)
Have your HAProxy system do initially forwarding based on ports, and then wildcards on your directory.
Please see below:
frontend a-frontend-conf
# Declare an ACL using path_beg (Path Begins)
acl path_images path_beg /images
# Use backend server1 if acl condition path_images is fulfilled
use_backend server1 if path_images
backend server1
[...]
Source: https://serverfault.com/questions/659793/haproxy-how-to-balance-traffic-within-directory-reached

Why does HAProxy show that a server's check URL is a 404 when running curl on this URL is successful?

I'm setting up HAProxy to load-balance a resource between 3 back-ends. Here is the HAProxy config : (In the following snippets I replaced the actual domain name by example.net)
global
log 127.0.0.1 local2
log-send-hostname
maxconn 2000
pidfile /var/run/haproxy.pid
stats socket /var/run/haproxy.sock mode 600 level admin
stats timeout 30s
daemon
# SSL ciphers
...
defaults
mode http
option forwardfor
option contstats
option http-server-close
option log-health-checks
option redispatch
timeout connect 5000
timeout client 10000
timeout server 10000
...
frontend front
bind *:443 ssl crt /usr/local/etc/haproxy/front.pem
reqadd X-Forwarded-Proto:\ https if { ssl_fc }
stats uri /haproxy?stats
option httpclose
option forwardfor
default_backend back
balance source
backend back
balance roundrobin
option httpchk GET /healthcheck HTTP/1.0
server server1 xxx.xxx.xxx.xxx:80 check inter 5s fall 2 rise 1
server server2 yyy.yyy.yyy.yyy:8003 check backup
server mysite example.net:80 check backup
The issue is the following: even though the first 2 servers respond correctly, the domain-based one always shows as a 404:
What is counter-intuitive to me is that if I use curl to access this same healthcheck, I get an HTTP 200 (like I would expect to see in the HAProxy stats) :
curl -I http://example.net/healthcheck
HTTP/1.1 200 OK
When I ping my site, I get:
# ping example.net
PING example.net (217.160.0.195) 56(84) bytes of data.
64 bytes from 217-160-0-195.elastic-ssl.ui-r.com (217.160.0.195): icmp_seq=1 ttl=50 time=45.7 ms
Is it because the IP of my domain is shared with other domains (1&1 shared hosting) that HAProxy can't access it? Why is that and how to make HAProxy reach it correctly?

HAProxy Multiport backends

I may be using the wrong terms to search, but I'm having trouble finishing connections to my backend servers though HAProxy. I am able to initially login to the servers, but then the application communicates through two others ports as well. I can go directly to one of the servers and it logs in and lunches the application correctly. Through HAProxy however, I can authenticate, and then I get a communication error. I'm thinking that HAProxy is not passing through data on the other ports. How can this be achieved?
My setup:
2 HAProxy server connected to 2 identical VM servers. HAProxy seems to be working correctly as far as telling when the service on the mcahines are running. It is passing through authentication on port 8443. But that's as far as it will go. It will not launch the VM which uses ports 3000 and 5432. Any ideas on the HAProxy setup?
Here is my configuration file:
global
ssl-server-verify none
tune.ssl.default-dh-param 2048
maxconn 256
defaults
log global
mode http
option httplog
option dontlognull
retries 3
option redispatch
timeout connect 5000
timeout client 10000
timeout server 10000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
listen vm-port-3000
bind *:5432
server qvd4 10.0.0.1:3000
server qvdnode02 10.0.0.2:3000
listen vm-port-5432
bind *:5432
server qvd4 10.0.0.1:5432
server qvdnode02 10.0.0.2:5432
listen stats
bind :1936
stats enable
stats hide-version
stats realm Loadbalanced\ Servers
stats uri /haproxy?stats
stats auth haproxy:haproxy
frontend vm-initial-conn
bind *:8443 ssl crt /etc/ssl/certs/qvd/haproxy.pem
default_backend vmConn
backend vmConn
option forwardfor
option httpchk GET /qvd/ping HTTP/1.1
http-check expect status 200
balance roundrobin
http-request add-header X-Forwarded-Proto https if { ssl_fc }
http-request set-header X-Forwarded-Port %[dst_port]
server qvd4 10.0.0.1:8443 ssl verify none check
server qvdnode02 10.0.0.2:8443 ssl verify none check
In your vm-port-3000 you are actually binding to port 5432 instead of how it appears you intended to port 3000.
Thus, requests to port 5432 are randomly handled by either your vm-port-3000 or your vm-port-5432 listener while connections to port 3000 are not handled by HAProxy at all.

HaProxy (cannot bind socket, select test failed)

Hello everyone,
Im working about an high availbility project, I had to put in production an haproxy for some applications. Everything was ok after some basics tests but I had some errors and cant fix it. Does someone have some ideas ?
here is the test
# /usr/sbin/haproxy -d -f /etc/haproxy/haproxy.cfg
Available polling systems :
sepoll : pref=400, test result OK
epoll : pref=300, test result OK
poll : pref=200, test result OK
select : pref=150, test result FAILED
Total: 4 (3 usable), will use sepoll.
Using sepoll() as the polling mechanism.
[ALERT] 174/160258 (22038) : Starting proxy mysql: cannot bind socket
[ALERT] 174/160258 (22038) : Starting proxy http: cannot bind socket
There is my file haproxy.cfg
global
log 127.0.0.1 local0 notice
user haproxy
group haproxy
maxconn 32000
ulimit-n 65536
defaults
log global
option dontlognull
retries 2
timeout connect 3000
timeout server 5000
timeout client 5000
option redispatch
listen mysql
bind *:3306
mode tcp
option tcplog
balance roundrobin
option mysql-check user haproxy_check
server mysql1 10.83.83.167:3306 check
server mysql2 10.83.83.168:3306 check
server mysql3 10.83.83.169:3306 check
listen http
mode http
bind *:80
stats enable
stats uri /stats
stats auth admin:HaProxy2014
acl app1_cluster_acl hdr_beg(host) -i app1
acl app2_cluster_acl hdr_beg(host) -i app2
acl mysql_cluster_acl hdr_beg(host) -i mysql
use_backend app1_cluster if app1_cluster_acl
use_backend app2_cluster if app2_cluster_acl
use_backend mysql_cluster if mysql_cluster_acl
backend app1_cluster
mode http
cookie SERVERID insert indirect nocache
option forwardfor header X-Real-IP
option http-server-close
option httplog
balance roundrobin
server serv1 10.83.83.203:80 check cookie serv1
server serv2 10.83.83.204:80 check cookie serv2
backend app2_cluster
mode http
cookie SERVERID insert indirect nocache
option forwardfor header X-Real-IP
option http-server-close
option httplog
balance roundrobin
server serv1 10.83.83.187:80 check cookie serv1
server serv2 10.83.83.188:80 check cookie serv2
backend mysql_cluster
mode http
cookie SERVERID insert indirect nocache
option forwardfor header X-Real-IP
option http-server-close
option httplog
balance roundrobin
server mysql1 10.83.83.167:80 check cookie serv1
server mysql2 10.83.83.168:80 check cookie serv2
server mysql3 10.83.83.169:80 check cookie serv2
I get the same error if there is already a mysql or http service running on my load balancer in addition to ruuning on the back ends.
For example if nginx/apache is already running on my load balancer.
$ netstat -anp | grep ":80"
tcp 0 0 127.0.0.1:80 0.0.0.0:* LISTEN 3646/nginx
And i try to start my load balancer with bind *:80 i get a similar error.
$ haproxy -d -f /etc/haproxy/haproxy.cfg
Available polling systems :
epoll : pref=300, test result OK
poll : pref=200, test result OK
select : pref=150, test result FAILED
Total: 3 (2 usable), will use epoll.
Using epoll() as the polling mechanism.
[ALERT] 195/001456 (1903) : Starting frontend www: cannot bind socket [0.0.0.0:80]
If you need to have a mysql or http instance listening on 127.0.0.1 then you can specify the ip of another interface in the bind call.
bind: 10.0.0.20:80
With the latest version of haproxy you can now even use variables.
bind ${LB1}:80
And export these from the haproxy startup script or /etc/default/haproxy
export LB1="10.0.0.20"
Otherwise perhaps there is an issue with your haproxy startup scripts.

Haproxy 503 Service Unavailable . No server is available to handle this request

How does haproxy deal with static file , like .css, .js, .jpeg ? When I use my configure file , my brower says :
503 Service Unavailable
No server is available to handle this request.
This my config :
global
daemon
group root
maxconn 4000
pidfile /var/run/haproxy.pid
user root
defaults
log global
option redispatch
maxconn 65535
contimeout 5000
clitimeout 50000
srvtimeout 50000
retries 3
log 127.0.0.1 local3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout check 10s
listen dashboard_cluster :8888
mode http
stats refresh 5s
balance roundrobin
option httpclose
option tcplog
#stats realm Haproxy \ statistic
acl url_static path_beg -i /static
acl url_static path_end -i .css .jpg .jpeg .gif .png .js
use_backend static_server if url_static
backend static_server
mode http
balance roundrobin
option httpclose
option tcplog
stats realm Haproxy \ statistic
server controller1 10.0.3.139:80 cookie controller1 check inter 2000 rise 2 fall 5
server controller2 10.0.3.113:80 cookie controller2 check inter 2000 rise 2 fall 5
Does my file wrong ? What should I do to solve this problem ? ths !
What I think is the cause:
There was no default_backend defined. 503 will be sent by HAProxy---this will appear as NOSRV in the logs.
Another Possible Cause
Based on one of my experiences, the HTTP 503 error I receive was due to my 2 bindings I have for the same IP and port x.x.x.x:80.
frontend test_fe
bind x.x.x.x:80
bind x.x.x.x:443 ssl blah
# more config here
frontend conflicting_fe
bind x.x.x.x:80
# more config here
Haproxy configuration check does not warn you about it and netstat doesn't show you 2 LISTEN entries, that's why it took a while to realize what's going on.
This can also happen if you have 2 haproxy services running. Please check the running processes and terminate the older one.
Try making the timers bigger and check that the server is reachable.
From the HAproxy docs:
It can happen from many reasons:
The status code is always 3-digit. The first digit indicates a general status :
- 1xx = informational message to be skipped (eg: 100, 101)
- 2xx = OK, content is following (eg: 200, 206)
- 3xx = OK, no content following (eg: 302, 304)
- 4xx = error caused by the client (eg: 401, 403, 404)
- 5xx = error caused by the server (eg: 500, 502, 503)
503 when no server was available to handle the request, or in response to
monitoring requests which match the "monitor fail" condition
When a server's maxconn is reached, connections are left pending in a queue
which may be server-specific or global to the backend. In order not to wait
indefinitely, a timeout is applied to requests pending in the queue. If the
timeout is reached, it is considered that the request will almost never be
served, so it is dropped and a 503 error is returned to the client.
if you see SC in the logs:
SC The server or an equipment between it and haproxy explicitly refused
the TCP connection (the proxy received a TCP RST or an ICMP message
in return). Under some circumstances, it can also be the network
stack telling the proxy that the server is unreachable (eg: no route,
or no ARP response on local network). When this happens in HTTP mode,
the status code is likely a 502 or 503 here.
Check ACLs, check timeouts... and check the logs, that's the most important...