There are times when you don't need the delivery options an ADC can provide, and even an SLB solution might not make sense. A tandem set of appliances for each local area network where servers reside is expensive to purchase and maintain vendor support. They also require power and use precious rack space. If a server load balancer is all you need to ensure service availability while dividing load, perhaps a different solution could do the job.
One Address To Rule Them All
Let's pick a service or two: named and httpd. Now, we'll assign an address to each service: 172.16.254.53 for DNS and 172.16.254.80 for web services. No matter what network the servers for these services lives on, the servicing address will be the same. With anycast, multiple servers can advertise their availability, inserting into the infrastructure's routing table a single address across multiple machines. Note, that this article will only deal with the httpd example.
More Than One Way To Get There
The OSPF protocol populates network destinations in a table based on the cost of the link. If there are multiple paths packets could take to reach a destination, the one with the lowest cost, or metric, gets its gateway updated in the routing table. If more than one of these share the lowest metric value, multiple gateways are placed in the routing table. For anycast, the destination is simply a host route and the multiple gateways are the addresses of the Ethernet interfaces of servers. Clients are directed to the system with the lowest metric, ensuring requests go to the closest systems, ones without WAN costs.
I assembled a small lab to test out this system.
Host: geary.streetsof.sf System: Juniper SRX Interfaces: lo.0 172.16.0.1/32 ospf area 0.0.0.0 vlan.10 172.16.1.1/30 ospf area 0.0.0.0 vlan.100 172.16.100.1/24 ospf area 172.16.100.0 Host: kearny.streetsof.sf System: Juniper SRX Interfaces: lo.0 172.16.0.2/32 ospf area 0.0.0.0 vlan.10 172.16.1.2/30 ospf area 0.0.0.0 vlan.200 172.16.200.1/24 ospf area 172.16.200.0 Host: polk.streetsof.sf System: CentOS Linux 6.0 Interfaces: ospf area 172.16.100.0 lo:0 172.16.0.3/32 lo:1 172.16.254.80/32 eth0 172.16.100.128/24 Host: union.streetsof.sf System: CentOS Linux 6.0 Interfaces: ospf area 172.16.100.0 lo:0 172.16.0.4/32 lo:1 172.16.254.80/32 eth0 172.16.100.129/24 Host: mission.streetsof.sf System: CentOS Linux 6.0 Interfaces: ospf area 172.16.200.0 lo:0 172.16.0.5/32 lo:1 172.16.254.80/32 eth0 172.16.200.128/24
The routing table on GEARY looks like:
Prefix Path Route NH Metric NextHop Nexthop Type Type Type Interface Address/LSP 172.16.0.2 Intra Router IP 1 vlan.10 172.16.1.2 172.16.0.3 Intra Router IP 1 vlan.100 172.16.100.128 172.16.0.4 Intra Router IP 1 vlan.100 172.16.100.129 172.16.0.5 Intra Router IP 1 vlan.10 172.16.1.2 172.16.0.1/32 Intra Network IP 0 lo0.0 172.16.0.3/32 Intra Network IP 11 vlan.100 172.16.100.128 172.16.0.4/32 Intra Network IP 11 vlan.100 172.16.100.129 172.16.254.80/32 Intra Network IP 11 vlan.100 172.16.100.128 vlan.100 172.16.100.129 172.16.100.0/24 Intra Network IP 1 vlan.100 172.16.200.0/24 Intra Network IP 19 vlan.10 172.16.1.2
When POLK and UNION become unavailable, the routing table on GEARY updates.
Prefix Path Route NH Metric NextHop Nexthop Type Type Type Interface Address/LSP 172.16.0.2 Intra Router IP 1 vlan.10 172.16.1.2 172.16.0.3 Intra Router IP 1 vlan.100 172.16.100.128 172.16.0.4 Intra Router IP 1 vlan.100 172.16.100.129 172.16.0.5 Intra Router IP 1 vlan.10 172.16.1.2 172.16.0.1/32 Intra Network IP 0 lo0.0 172.16.0.3/32 Intra Network IP 11 vlan.100 172.16.100.128 172.16.0.4/32 Intra Network IP 11 vlan.100 172.16.100.129 172.16.254.80/32 Intra Network IP 19 vlan.10 172.16.1.2 172.16.100.0/24 Intra Network IP 1 vlan.100 172.16.200.0/24 Intra Network IP 19 vlan.10 172.16.1.2
172.16.0.80 lives on as a valid destination, but since MISSION is now serving it, the route to a farther point (higher cost) is visible in the routing table.
On each web server was a file, host.txt, which simply contained the name of the server. Requests were made from FILLMORE, address 172.16.100.151.
[fillmore]$ curl -x "" http://172.16.254.80/host.txt POLK [fillmore]$
After the web server on POLK went offline...
[fillmore]$ curl -x "" http://172.16.254.80/host.txt UNION [fillmore]$
And, after the web server on UNION went offline...
[fillmore]$ curl -x "" http://172.16.254.80/host.txt MISSION [fillmore]$
So, it works as expected.
The Linux Configuration
For the OSPF networking, you might want to install Quagga routing software. On CentOS, this was simple.
[polk]# yum -y install quagga ... [polk]# chkconfig zebra on
You need to set up the loopback interfaces.
# /etc/sysconfig/network-scripts/ifcfg-lo:1 # Used as router-id, always available # DEVICE=lo:0 BOOTPROTO=none NM_CONTROLLED="no" IPADDR=172.16.0.3 NETMASK=255.255.255.255 ONBOOT=yes # /etc/sysconfig/network-scripts/ifcfg-lo:2 # To be brought up if Apache is working as expected # DEVICE=lo:1 BOOTPROTO=none NM_CONTROLLED="no" IPADDR=172.16.254.80 NETMASK=255.255.255.255 ONBOOT=no
A simple check would insert or remove the host's service loopback into the routing tables.
state="up" ifup lo:1 while : ; do /bin/sleep 10 # be sure to check an interface other than the anycast address # is Apache listening? /usr/bin/nc -z 172.16.0.3 80 if [ $? -eq 0 ]; then # if Apache is listening # Fire up ospfd and set state variable if [ "$state" != "up" ]; then /sbin/service zebra restart /sbin/service ospfd restart state="up" fi else # if Apache is not listening # Remove routing # Fire up Apache and give it a bit of time to load # Fire up routing /sbin/service ospfd stop /sbin/service zebra stop /sbin/service httpd restart /bin/sleep 10 fi done
! /etc/quagga/zebra.conf ! hostname polk password sfquagga enable password sfquagga ! interface lo:0 ip address 172.16.0.3/32 interface eth0 ip address 172.16.100.128/24 interface lo:1 ip address 172.16.0.80/32 ! line vty ! ! /etc/quagga/ospfd.conf ! hostname polk password sfquagga enable password sfquagga ! interface eth0 ip ospf priority 0 ip ospf cost 32768 ! router ospf log-adjacency-changes ospf router-id 172.16.0.3 network 172.16.100.0/24 area 172.16.100.0 network 172.16.0.3/32 area 172.16.100.0 network 172.16.0.80/32 area 172.16.100.0 ! line vty !
I would be interested in hearing how this works for you.