Face the load

Foreword

One time or another, you’ll be facing the problem that your webserver isn’t powerfull enough as it can’t handle all the incoming traffic. You may at this moment consider using load balancing the charge between more than one server.

Here is what you’ll have to know about the Network topology overview related to this howto:

  • client ip address: 192.168.0.10
  • lb ip address: 192.168.0.107
  • server1 ip address: 192.168.0.108
  • server2 ip address: 192.168.0.109
  • ip address used for loadbalancing: 192.168.0.50

[!NOTE] Note: in this tutorial, I use the ifconfig command to configure interfaces, and I really don’t recommend you to do so. ifconfig is really deprecated and buggy on RedHat based systems, I strongly suggest you to use the ip command instead.

Installing necessary packages

iptables should already been installed on your system, but make sure of it. Next thing you’ll need is ipvsadm on the load balancer :

yum install ipvsadm
=>	Loaded plugins: fastestmirror
	Loading mirror speeds from cached hostfile
	 ...
	Setting up Install Process
	Resolving Dependencies
	--> Running transaction check
	---> Package ipvsadm.i386 0:1.24-10 set to be updated
	--> Finished Dependency Resolution
	...
	Complete!

Network configuration

Now you should add the ip dedicated for load balancing on servers.

As alias of eth0 on the load balancer :

ifconfig eth0:0 192.168.0.50 netmask 255.255.255.0
ifconfig eth0:0
=>	eth0:0    Link encap:Ethernet  HWaddr 00:0C:29:5A:78:22
	          inet addr:192.168.0.50  Bcast:192.168.0.255  Mask:255.255.255.0
	          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
	          Interrupt:75 Base address:0x2000

And as alias of lo:0 on server1 and server2 :

ifconfig lo:0 192.168.0.50 netmask 255.255.255.255
ifconfig lo:0
=>	lo:0      Link encap:Local Loopback
	          inet addr:192.168.0.50  Mask:255.255.255.255
	          UP LOOPBACK RUNNING  MTU:16436  Metric:1
ifconfig lo:0 192.168.0.50 netmask 255.255.255.255
ifconfig lo:0
=>	lo:0      Link encap:Local Loopback
	          inet addr:192.168.0.50  Mask:255.255.255.255
	          UP LOOPBACK RUNNING  MTU:16436  Metric:1

Yeah, this is not a permanent way to configure the interfaces, but that’s specific to your distribution, so, do it your way.

Prevent ARP problems

Well, as you configured ip addresses on all servers, every one of them will start to claim “i’ve got the 192.168.0.50 address !!!” via arp packets. This can result on an ARP tempest if you did this on many servers, and most certainly you’ll not be able to use the IP.

There’s a way of preventing this from happening, by telling servers to ignore arp and do not announce when they change something. Put this in /etc/sysctl.conf of each real server:

net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2

Then, apply changes you made in the sysctl.conf file :

sysctl -p

Let packets go through the load balancer

You need to let packets go through your load balancer, so add this in your /etc/sysctl.conf file on the load balancing server :

net.ipv4.ip_forward = 1

Then, apply changes you made in the sysctl.conf file :

sysctl -p

Marking packets that should be load-balanced

What we want is that packets directed to the port 80 of the load balancer ip address are being marked (like a stamp) so that ipvs can regognize them and handle them accordingly to ipvs rules.

iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark
iptables -t mangle -N myrule
iptables -t mangle -A PREROUTING -d 192.168.0.50 -p tcp --dport 80 -j myrule
iptables -t mangle -A myrule -j MARK --set-mark 0x1
iptables -t mangle -A myrule -j CONNMARK --save-mark

Setting up the ipvs rules

Now we just have to tell ipvsadm to route marked packets to server1 and server2 (which is meaned to be twice powerful as server1), using weight round robin load balancing. This means that servers with higher weight will receive more packets than servers with lighter weights. Concretely, telling that server2 has a weight of 2 and server1 a weight of 1, server2 will get 10 packets when server1 got 5.

ipvsadm -A -f 1 -s wrr
ipvsadm -a -f 1 -r 192.168.0.108:0 -w 1
ipvsadm -a -f 1 -r 192.168.0.109:0 -w 2

Putting some load on the load balancing ip

Here is the result of putting some load on the virtual ip :

IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
FWM  1 wrr
  -> 192.168.0.109:0              Route   2      0          1451
  -> 192.168.0.108:0              Route   1      0          721

We see that packets are transferred correctly to the servers, in accordance to their weight.