/ Linux

Setup HTTP Load Balancer with HAProxy


When it comes to ensuring that we need our website needs to be online at all times, we need to start looking at High Availability.

Today we will be demonstrating a basic setup of Layer 4 (transport layer) load balancing making use of HAProxy Server with 2 backend nodes using the round robin algorithm, which essentially means that the first backend node will respond on the first request, and the second backend node on the second request.

Our Setup:

We will have 1 haproxy server that will be listening on port 80 and also Python's SimpleHTTPServer running on port 8000, this will act as a lightweight web server to serve a maintenance page when both of our nodes are down.

Then for our back-end nodes, both servers will be listening on port 8080 and only allowing our haproxy to communicate with port 8080. Website configuration and content has been synchronized with each other so that we have the exact same content on both servers.

Resources:

haproxy: 192.168.1.2 (HAProxy)
node-web1: 192.168.10.4 (LAMP)
node-web2: 192.168.11.4 (LAMP)

Dependencies:

$ yum install haproxy screen python openssl openssl-devel -y

HAProxy Configuration:

$ vi /etc/haproxy/haproxy.cfg

global
    log         127.0.0.1 local2
    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon

    stats socket /var/lib/haproxy/stats mode 600 level admin

defaults
    log                     global
    option                  httplog
    option                  dontlognull
    option                  http-server-close
    option                  forwardfor
    option                  redispatch
    retries                 3
    timeout http-request    20s
    timeout queue           86400
    timeout connect         86400
    timeout client          86400
    timeout server          86400
    timeout http-keep-alive 30s
    timeout check           20s
    maxconn                 50000

listen stats   192.168.1.2:1936
    mode            http
    log             global
    maxconn 10
    timeout queue   100s
    stats enable
    stats hide-version
    stats refresh 30s
    stats show-node
    stats auth admin:sekret
    stats uri  /haproxy?stats

frontend http-in
    bind *:80
    mode http
    acl web hdr_end(host) -i domain.com
    acl www_web hdr_end(host) -i www.domain.com
    default_backend web-backend

backend web-backend
    mode http
    balance roundrobin
    option httpchk GET /status/healthcheck.html
    option httpclose
    option forwardfor
    server node-web1 192.168.10.4:8080 check 
    server node-web2 192.168.11.4:8080 check 
    server maintenance 127.0.0.1:8000 backup

Rsyslog Configuration:

$ vi /etc/rsyslog.conf

Uncomment the following:

$ModLoad imudp
$UDPServerRun 514

Backend Node Pages:

Set the following on your index.html for your backend nodes:

node-web1

<html>
Response From: node-web1 [192.168.10.4]
</html>

node-web2

<html>
Response From: node-web2 [192.168.11.4]
</html>

Maintenance Page:

Our maintenance page on Python Simple HTTP Server

$ mkdir -p /opt/python/simplehttpserver
$ cd /opt/python/simplehttpserver
$ vi index.html

<!doctype html>
<title>Site Maintenance</title>
<style>
  body { text-align: center; padding: 150px; }
  h1 { font-size: 50px; }
  body { font: 20px Helvetica, sans-serif; color: #333; }
  article { display: block; text-align: left; width: 650px; margin: 0 auto; }
  a { color: #dc8100; text-decoration: none; }
  a:hover { color: #333; text-decoration: none; }
</style>

<article>
    <h1>We&rsquo;ll be back soon!</h1>
    <div>
        <p>Sorry for the inconvenience but we&rsquo;re performing some maintenance at the moment. If you need to reach out to us, you can always <a href="mailto:support@bekkersolutions.com">contact us</a>, otherwise we&rsquo;ll be back online, shortly!</p>
        <p>&mdash; Your Orginization </p>
    </div>
</article>

Start the service in a screen session:

$ screen -S MaintenancePage -m -d sh -c "python –m SimpleHTTPServer"

Firewall Configuration:

For each node allow the HAProxy server address to communicate with port 8080/TCP:

$ iptables -A INPUT -p tcp -s [haproxy-source-address] --dport 8080 -j ACCEPT

Enable Services:

$ service rsyslog restart
$ service haproxy restart
$ chkconfig rsyslog on
$ chkconfig haproxy on

Testing:

$ curl http://192.168.1.2
Response From: node-web1 [192.168.10.4]

$ curl http://192.168.1.2
Response From: node-web2 [192.168.11.4]