Setting up a pair of highly available load balanced website using Slicehost.
I embarked on setting this up as prototype or proof of concept.
My colleague/friend who runs his own business and has a website for which he was looking for some high availability and load balancing.
Below is the architecture..
I am making use of 4 virtual machines or servers.
dir0
dir1
web0
web1
The servers web0 and web1 will serve as a pool of web servers, which will be serving the website.
The 2 major components to make this happen are.
1. Load Balancing.
2. Failover
The load balancing software will be configured to run on either dir0 or dir1.
While the server dir0 is actively working as the load balancer, if disaster was to strike, we need to still carry on serving the web page. This is acheived by the failover component which will allow you to migrate the IP address to the standby server dir1 and start the load balancing software.
Some background information about working with Slicehost.
For the purpose of this exercise I am going to use the smallest slice "256 slice"
The distribution of choice was Debian 5.0 (lenny).
This article has got details regarding setting up iptables in debian lenny
http://articles.slicehost.com/2009/3/31/debian-lenny-setup-page-1
________|________
| |
######### #########
# dir-0 # # dir-1 #
######### #########
my configuration file
/etc/iptables.up.rules
Looks like this. I have enabled incoming SSH and HTTP
##############################################################################
# Generated by iptables-save v1.4.2 on Sat Oct 17 15:56:48 2009
*filter
:INPUT ACCEPT [140:10452]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [130:13960]
-A INPUT -i lo -j ACCEPT
-A INPUT -d 127.0.0.0/8 -i ! lo -j REJECT --reject-with icmp-port-unreachable
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-port-unreachable
-A OUTPUT -j ACCEPT
COMMIT
# Completed on Sat Oct 17 15:56:48 2009
##############################################################################
edit the lo interface to start iptables.
add the below line to "lo" interface
pre-up iptables-restore < /etc/iptables.up.rules
Restarting networking gives an error.
######################################
Reconfiguring network interfaces...if-up.d/mountnfs[eth0]: waiting for interface eth1 before doing NFS mounts (warning).
SIOCADDRT: File exists
Failed to bring up eth1.
done.
######################################
Haven't figured out what this means, But eth1 seems to be working fine..
######################################
Ok Round 1.
Installing Linux-ha or heartbeat
The linux-ha project is a great framework to provide IP and service failover feature.
http://www.linux-ha.org/doc/
Install heartbeat on both dir0 and dir1
apt-get update
apt-get upgrade
# Just wanted to make sure that we are up to date before proceeding with the install.
apt-get install less
# funny the less package was missing..
# I guess it makes sense, it is a minimal install
apt-get install heartbeat-2
The following NEW packages will be installed:
file gawk heartbeat heartbeat-2 libdb4.5 libglib2.0-0 libglib2.0-data
libltdl3 libmagic1 libnet1 libopenhpi2 libpcre3 libperl5.10 libsensors3
libsnmp-base libsnmp15 libsqlite3-0 libsysfs2 libxml2 libxml2-utils
mime-support openhpid perl perl-modules psmisc python python-central
python-minimal python2.5 python2.5-minimal sgml-base ucf xml-core
Obtain sample configuration files which will help in setting up heartbeat
The sample configuration files are in /usr/share/doc/heartbheat.
cd /etc/ha.d/
cp /usr/share/doc/heartbeat/ha.cf.gz .
cp /usr/share/doc/heartbeat/haresources.gz .
cp /usr/share/doc/heartbeat/authkeys .
gunzip ha.cf.gz
gunzip haresources.gz
Setting up the authkeys
cd /etc/ha.d/
echo "auth 3" >> authkeys
echo "3 md5 some_random_string_which_would_be_hard_to_guess" >> authkeys
chmod 400 authkeys
You have to edit you ha.cf configuration file
To hav ethe bare minimum of the below line.
dir0 (/etc/ha.d/ha.cf)
----------------------------
logfile /var/log/ha-log
logfacility local0
keepalive 2
udpport 694
ucast eth1 10.176.100.160
auto_failback off
node dir0
node dir1
----------------------------
dir1 (/etc/ha.d/ha.cf)
----------------------------
logfile /var/log/ha-log
logfacility local0
keepalive 2
udpport 694
ucast eth1 10.176.100.79
auto_failback off
node dir0
node dir1
----------------------------
I tend to use ucast as I do not plan on increasing the number of nodes.
----------------------------------
Obtain a failover IP address from Slicehost
I was allocated 174.143.237.200
echo "dir0 174.143.237.200/24" >> /etc/ha.d/haresources
This should allow us to do a basic heartbeat setup with a failover ip.
You can start heartbeat on both machines. The above IP should be running on one of them.
Infact running on dir0 if you have started dir0 first.
You can initiate a continuous ping from your local machine to the IP address 174.143.237.200.
While the ping is going on, you can stop heartbeat on dir0 and the ip should failover to dir1. and vise-verse.
I didn't loose any ping packets, while relocating the virtual IP address to and fro between dir0 and dir1.
-----------------------------------
Ok now moving on to a director setup or a load balancer setup.
I am planning on using ldirectord for the loadbalancing.
If it just simple port 80 loadbalancer, then you can have either nginx or a balance script do the job for you.
I will see if I have time to try out both approaches.
---------------------------------------------
LDirector Load balancing.
apt-get install ldirectord-2
update-rc.d -f ldirectord remove
/etc/haresources
dir0 \
IPaddr2::174.143.237.200/24/eth0/174.143.237.255 \
ldirectord::ldirectord.cf
on the web nodes did the following
apt-get update
aptitude safe-upgrade
aptitude install apache2
ifconfig tunl0 172.26.20.110 netmask 255.255.255.255 broadcast 172.26.20.110 up
route add -host 172.26.20.110 dev tunl0
Director load balancing didn't work due to several reason..
Some of it.. was due to the flast that mac addresses were being cloned etc..
--------------------------------------------
Load Balancing - Option 2 - Balance Script
aptitude install balance
Install balance on both dir0 and dir1
http://www.inlab.de/balance.html
Balance script is very straight forward, one liner which will setup some port forwarding and load balancing for you.
Man page is available here http://linux.die.net/man/1/balance
The virtual IP 174.143.237.200 is generally migrated from dir0 to dir1 and vice-versa by heartbeat.
When the IP address is migrated over, heartbeat scripts should be able to easily stop and start the balance script on it's own. Given the fact that there is no init script and configuration file for balance, I couldn't be bothered to write one up which is lsb compliant.
Under normal circumstances I would use below command to startup balance.
balance -b 174.143.237.200 80 10.176.109.174 10.176.109.192
Given that i don't have an init script.
As a work around, I am starting balance using the below command.
balance -b 0.0.0.0 80 10.176.109.174 10.176.109.192
The above balance command will listen on any IP address at port 80 and forward the connections to the 2 ips mentioned there. I would have the above balance command running on both dir0 and dir1.
What this allows me to do is migrate the virtual IP 174.143.237.200, between dir0 and dir1 without having to meddle with the balance script.
There are additional questions of monitoring etc.. but then again this is only setup as a proof of concept.
--------------------------------------------------
Load Balancing - Option 3 - HAProxy
http://www.haproxy.org/
aptitude install haproxy
update-rc.d -f haproxy remove
On both dir0 and dir1 install haproxy and remove it from starting up automatically.
enable haproxy in /etc/default/haproxy
All you need to do is set ENABLED=1
sed -i s/ENABLED=0/ENABLED=1/ /etc/default/haproxy
the haproxy configuration files needs to be setup.
The configuration file is located in /etc/haproxy/haproxy.cfg
The key section from the configuration file /etc/haproxy/haproxy.cfg is
listen ha.sushilsuresh.co.uk 174.143.237.200:80
balance roundrobin
stats enable
server web0 174.143.238.24:80 check inter 20 rise 2 fall 2
server web1 174.143.238.66:80 check inter 20 rise 2 fall 2
Finally I had to configure heartbeat to start and stop haproxy when heartbeat starts or stops.
The only configuration file that needs to be changed is
/etc/ha.d/haresources
dir0 \
IPaddr2::174.143.237.200/24/eth0/174.143.237.255 \
haproxy
Heartbeat is capable of calling the haproxy init script in /etc/init.d/
--------------------------------------------------
Testing
while true; do curl http://ha.sushilsuresh.co.uk; done
Web0 - It works!
Web1 - It works!
Web0 - It works!
Web1 - It works!
Web0 - It works!
Web1 - It works!
Web0 - It works!
Web1 - It works!
Web0 - It works!
Web1 - It works!
Web0 - It works!
Web1 - It works!
Web0 - It works!
While things are ticking along...
Trying stopping and starting apache on web1 and web2.
You should see corresponding changes in the output of the curl command.
Stopping apache web0 resulted in the below output from curl
Web0 - It works!
Web1 - It works!
Web0 - It works!
Web1 - It works!
Web0 - It works!
Web1 - It works!
Web1 - It works!
Web1 - It works!
Web1 - It works!
Web1 - It works!
Web1 - It works!
Web1 - It works!
Web1 - It works!
Web1 - It works!
Again while the above curl was running,
I tried to failover the IP from dir0 to dir1.
Either by stopping heartbeat on dir0 or rebooting dir0
Web0 - It works!
Web1 - It works!
Web0 - It works!
Web1 - It works!
curl: (7) couldn't connect to host
curl: (7) couldn't connect to host
curl: (7) couldn't connect to host
curl: (7) couldn't connect to host
curl: (7) couldn't connect to host
Web0 - It works!
Web1 - It works!
Web0 - It works!
Web1 - It works!
As you can see I missed about 5 consecutive curls and things were back to normal.
-----------------------------------
Load Balancing - Option 4 - Nginx Proxy Parse
Nginx has got the ability to load balance by making use of the httpd proxy module.
http://wiki.nginx.org/NginxHttpProxyModule
apt-get install nginx
update-rc.d -f nginx remove
The main configuration can fine needs to be edited.
/etc/nginx/nginx.conf
http {
default_type application/octet-stream;
upstream backend {
server 10.176.109.174 weight=10 max_fails=3 fail_timeout=10s;
server 10.176.109.192 weight=10 max_fails=3 fail_timeout=10s;
}
server {
location / {
proxy_pass http://backend;
}
}
include /etc/nginx/conf.d/*.conf;
}
nginx failover can also be achieved using the keepalived
The below url did interest me.. but just documenting it for now.
http://www.cyberciti.biz/faq/handling-nginx-failover-with-keepalived/
for now, I have just configured,, nginx to be started by heartbead within.
/etc/ha.d/haresource
----------------------------------------------------------------
balance
One liner very easy to setup... but lack a lot of features..
HAProxy
Very feature rich.
flexible and has got a nice admin interface to view statistics
nginx
very lightweight, and can hand a lot of user connections with ease.
Has a got reasonable features, but not as feature rich as HAProxy.