05/07/2016 - HAPROXY, VAGRANT
In this example, we're going to send a request to Load balancer (HAProxy) then get the response from load balanced two different web servers. Request will never go to web servers directly. Load balancer will decide which server to be hit with the request. Example uses vagrant machines and is a layer 4 (transport layer) load balancing. Visit here for full configuration manual for you HAProxy version.
Two web servers will have only apache running and the load balancer will have HAProxy running. Load balancer GUI will be accessible from the host machine to see the health and stats about the web servers.
This is a vagrant based example so if the Keepalived floating IP doesn't work as expected, it doesn't mean that it won't work as expected if you do everything manually on the servers so I suggest you to try installing packages manually on a fresh servers.
I'm assuming that you already have installed vagrant and Oracle VM software. I also assume that the ubuntu/trusty64
box is already added to your filesystem with vagrant box add ubuntu/trusty64
command. If you're not sure, you can confirm it with ls -l ~/.vagrant.d/boxes/
command.
mkdir lay4-hap1-web2
$ cd lay4-hap1-web2/
#!/usr/bin/env bash
# BEGIN ########################################################################
echo -e "-- ----------------- --\n"
echo -e "-- BEGIN ${HOSTNAME} --\n"
echo -e "-- ----------------- --\n"
# VARIABLES ####################################################################
echo -e "-- Setting global variables\n"
APACHE_CONFIG=/etc/apache2/apache2.conf
LOCALHOST=localhost
# BOX ##########################################################################
echo -e "-- Updating packages list\n"
apt-get update -y -qq
# APACHE #######################################################################
echo -e "-- Installing Apache web server\n"
apt-get install -y apache2 > /dev/null 2>&1
echo -e "-- Adding ServerName to Apache config\n"
grep -q "ServerName ${LOCALHOST}" "${APACHE_CONFIG}" || echo "ServerName ${LOCALHOST}" >> "${APACHE_CONFIG}"
echo -e "-- Restarting Apache web server\n"
service apache2 restart
# TEST #########################################################################
echo -e "-- Creating a dummy index.html file\n"
cat > /var/www/html/index.html <<EOD
<html>
<head>
<title>${HOSTNAME}</title>
</head>
<body>
<h1>${HOSTNAME}</h1>
<p>Hi sir, I am going to serve you today!</p>
</body>
</html>
EOD
# END ##########################################################################
echo -e "-- -------------- --"
echo -e "-- END ${HOSTNAME} --"
echo -e "-- -------------- --"
#!/usr/bin/env bash
# BEGIN ########################################################################
echo -e "-- ------------- --\n"
echo -e "-- BEGIN HAPROXY --\n"
echo -e "-- ------------- --\n"
# BOX ##########################################################################
echo -e "-- Updating packages list\n"
apt-get update -y -qq
# HAPROXY ######################################################################
echo -e "-- Installing HAProxy\n"
apt-get install -y haproxy > /dev/null 2>&1
echo -e "-- Enabling HAProxy as a start-up deamon\n"
cat > /etc/default/haproxy <<EOF
ENABLED=1
EOF
echo -e "-- Configuring HAProxy\n"
cat > /etc/haproxy/haproxy.cfg <<EOF
global
log /dev/log local0
log localhost local1 notice
user haproxy
group haproxy
maxconn 2000
daemon
defaults
log global
mode http
option httplog
option dontlognull
retries 3
timeout connect 5000
timeout client 50000
timeout server 50000
frontend http-in
bind *:80
default_backend webservers
backend webservers
balance roundrobin
stats enable
stats auth admin:admin
stats uri /haproxy?stats
option httpchk
option forwardfor
option http-server-close
server webserver1 192.168.50.10:80 check
server webserver2 192.168.50.20:80 check
EOF
echo -e "-- Validating HAProxy configuration\n"
haproxy -f /etc/haproxy/haproxy.cfg -c
echo -e "-- Starting HAProxy\n"
service haproxy start
# END ##########################################################################
echo -e "-- ----------- --"
echo -e "-- END HAPROXY --"
echo -e "-- ----------- --"
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/trusty64"
# Configs for web server 1
config.vm.define :webserver1 do |webserver1_config|
webserver1_config.vm.provider :virtualbox do |vb_config|
vb_config.name = "Web Server 1 - lay4-hap1-web2"
end
webserver1_config.vm.hostname = "webserver1"
webserver1_config.vm.network "private_network", ip: "192.168.50.10"
webserver1_config.vm.provision :shell, path: "webserver.sh"
end
# Configs for web server 2
config.vm.define :webserver2 do |webserver2_config|
webserver2_config.vm.provider :virtualbox do |vb_config|
vb_config.name = "Web Server 2 - lay4-hap1-web2"
end
webserver2_config.vm.hostname = "webserver2"
webserver2_config.vm.network "private_network", ip: "192.168.50.20"
webserver2_config.vm.provision :shell, path: "webserver.sh"
end
# Configs for haproxy
config.vm.define :haproxy do |haproxy_config|
haproxy_config.vm.provider :virtualbox do |vb_config|
vb_config.name = "HAProxy - lay4-hap1-web2"
end
haproxy_config.vm.hostname = "haproxy"
haproxy_config.vm.network :forwarded_port, guest: 80, host: 8080
haproxy_config.vm.network "private_network", ip: "192.168.50.30"
haproxy_config.vm.provision :shell, path: "haproxy.sh"
end
end
$ vagrant up --provision
Bringing machine 'webserver1' up with 'virtualbox' provider...
Bringing machine 'webserver2' up with 'virtualbox' provider...
Bringing machine 'haproxy' up with 'virtualbox' provider...
==> webserver1: ......
==> webserver1: ......
==> webserver1: ......
==> webserver1: -- Setting global variables
==> webserver1: -- Updating packages list
==> webserver1: -- Installing Apache web server
==> webserver1: -- Adding ServerName to Apache config
==> webserver1: -- Restarting Apache web server
==> webserver1: * Restarting web server apache2
==> webserver1: ...done.
==> webserver1: -- Creating a dummy index.html file
==> webserver2: ......
==> webserver2: ......
==> webserver2: ......
==> webserver2: -- Setting global variables
==> webserver2: -- Updating packages list
==> webserver2: -- Installing Apache web server
==> webserver2: -- Adding ServerName to Apache config
==> webserver2: -- Restarting Apache web server
==> webserver2: * Restarting web server apache2
==> webserver2: ...done.
==> webserver2: -- Creating a dummy index.html file
==> haproxy: ......
==> haproxy: ......
==> haproxy: ......
==> haproxy: -- Installing HAProxy
==> haproxy: -- Enabling HAProxy as a start-up daemon
==> haproxy: -- Configuring HAProxy
==> haproxy: -- Validating HAProxy configuration
==> haproxy: Configuration file is valid
==> haproxy: -- Starting HAProxy
==> haproxy: * Starting haproxy haproxy
==> haproxy: ...done.
# Server 1
$ vagrant ssh webserver1
vagrant@webserver1:~$
# Server 2
$ vagrant ssh webserver2
vagrant@webserver2:~$
# HAProxy
$ vagrant ssh haproxy
vagrant@haproxy:~$
In normal life web servers must not be directly accessible but I ignore it for now for testing purposes.
Response to request below will alway be the same.
# Request
http://192.168.50.10/
# Response
webserver1
Hi sir, I am going to serve you today!
Response to request below will alway be the same.
# Request
http://192.168.50.20/
# Response
webserver2
Hi sir, I am going to serve you today!
Response will always change because request is evenly shared between web servers. Load balancer does it!
# Request
http://192.168.50.30/
# Response
webserver1
Hi sir, I am going to serve you today!
# Request
http://192.168.50.30/
# Response
webserver2
Hi sir, I am going to serve you today!
# Request
http://192.168.50.30/
# Response
webserver1
Hi sir, I am going to serve you today!
Load balancer will direct all requests to web server 2 because it is available.
Load balancer will direct all requests to web server 1 because it is available.
There is web server for load balancer to direct requests to so error below will be generated. Default error message and template can be changed in HAProxy config file.
503 Service Unavailable
No server is available to handle this request.
Visit http://192.168.50.30/haproxy?stats
. Login with admin:admin
.