Saturday, 2 January 2016

Vagrant Lab for HAProxy

This article is about setting up a lab using Vagrant to play with the HAProxy load balancer.

If you want the TLDR version where you just copy/paste a few lines and the lab gets created then this will do the job, it's explained in more detail below. It's great with tools like Virtualbox and Vagrant that such a lab can be set up so easily, this would have taken days to build prior to virtualization!

#install software
sudo apt-get install virtualbox vagrant git

#configure host-only subnet address in virtualbox
VBoxManage hostonlyif create
VBoxManage hostonlyif ipconfig vboxnet0 --ip 172.28.128.1 --netmask 255.255.255.0
VBoxManage dhcpserver modify --ifname vboxnet0 --ip 172.28.128.1 --netmask 255.255.255.0 --lowerip 172.28.128.100 --upperip 172.28.128.250

#install the lab files, for some reason the box fails to auto-download so install it manually, should be fixed in future
git clone https://github.com/unixhead/haproxy-basic-lab && cd haproxy-basic-lab 
vagrant box add hashicorp/precise32 https://vagrantcloud.com/hashicorp/boxes/precise32/versions/1.0.0/providers/virtualbox.box


#run the lab
vagrant up


Now there is a slight caveat in that I use Linux Mint and the current versions of Vagrant & Virtualbox aren't quite right, so I had to manually install Vagrant from the website, but never let the truth get in the way of a good story.

My Virtualbox host-only network uses the range 172.28.128.0/24 and the network to be created is shown below, a simple load balancer infront of two web servers. The client is also the hypervisor hosting the VMs. It's very similar to the configuration of the Vagrant tutorial system. Virtualbox by default uses 192.168.0.0/24 for the host-only networks but that overlaps with a few places I work so had to change it.



The files needed are listed below, save them all to the same directory and run "vagrant up" in it. You can download them all in one go from github with the command:

git clone https://github.com/unixhead/haproxy-basic-lab

Vagrantfile - The configuration for Vagrant itself providing 3 VMs using the Ubuntu 32 bit image. One is the HAProxy load balancer and two web servers.

Vagrant.configure(2) do |config|
  config.vm.box = "hashicorp/precise32"

 config.vm.provider "virtualbox" do |v|
   v.memory = 1024
    v.cpus = 1
 end

 config.vm.define "lb" do |config|
  config.vm.hostname = "lb"
    config.vm.network "private_network", ip: "172.28.128.10"
   config.vm.provision :shell, path: "bootstrap-haproxy.sh"
 end

 config.vm.define "web1" do |config|
  config.vm.hostname = "web1"
    config.vm.network "private_network", ip: "172.28.128.11"
   config.vm.provision :shell, path: "bootstrap-apache.sh"
 end

 config.vm.define "web2" do |config|
  config.vm.hostname = "web2"
    config.vm.network "private_network", ip: "172.28.128.12"
   config.vm.provision :shell, path: "bootstrap-apache.sh"
 end

end


bootstrap-apache.sh - This script runs on the webservers after Vagrant has built them. It installs Apache with PHP, then sets the web root to the current Vagrant project directory.

#!/usr/bin/env bash

apt-get update
apt-get install -y apache2 php5
if ! [ -L /var/www ]; then
  rm -rf /var/www
  ln -fs /vagrant /var/www
fi


bootstrap-haproxy.sh - This runs on the load balancer after build, it installs HAProxy and copies the provided configuration file.

#!/usr/bin/env bash

apt-get update
apt-get install -y haproxy hatop
cp /vagrant/haproxy.cfg /etc/haproxy
echo "ENABLED=1" > /etc/default/haproxy
service haproxy start


haproxy.cfg - Basic HAProxy configuration for load balancing port 80 between two web servers.

frontend http
  bind *:80
  mode tcp
  option tcplog

  default_backend web-backend

backend web-backend
   balance roundrobin
   mode tcp
   server web1 172.28.128.11:80 check
   server web2 172.28.128.12:80 check


index.php - A basic web index to show which web server was accessed by printing the servers hostname. Both web-servers will load the same file.

<?php
echo gethostname() . "\n";
?>


To test it simply run Curl a few times against the IP address of the load balancer, the replies show that the web sessions are being balanced across both hosts:

matt@client haproxy-lab $ curl 172.28.128.10
web1
matt@client haproxy-lab $ curl 172.28.128.10
web2
matt@client haproxy-lab $ curl 172.28.128.10
web1
matt@client haproxy-lab $ curl 172.28.128.10
web2
matt@client haproxy-lab $ curl 172.28.128.10
web1
matt@client haproxy-lab $ curl 172.28.128.10
web2
matt@client haproxy-lab $ curl 172.28.128.10
web1
matt@client haproxy-lab $ curl 172.28.128.10
web2
matt@client haproxy-lab $ curl 172.28.128.10
web1
matt@client haproxy-lab $ curl 172.28.128.10
web2
matt@client haproxy-lab $ curl 172.28.128.10
web1