<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://kb.linux-vs.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=ZaphodB</id>
		<title>LVSKB - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="http://kb.linux-vs.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=ZaphodB"/>
		<link rel="alternate" type="text/html" href="http://kb.linux-vs.org/wiki/Special:Contributions/ZaphodB"/>
		<updated>2026-04-19T04:29:47Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.26.2</generator>

	<entry>
		<id>http://kb.linux-vs.org/wiki?title=Talk:IPv6_load_balancing&amp;diff=44407</id>
		<title>Talk:IPv6 load balancing</title>
		<link rel="alternate" type="text/html" href="http://kb.linux-vs.org/wiki?title=Talk:IPv6_load_balancing&amp;diff=44407"/>
				<updated>2017-09-20T17:34:33Z</updated>
		
		<summary type="html">&lt;p&gt;ZaphodB: Created page with &amp;quot;I found the service check and most likely your ICMPv6 issue as well to be caused by the way IPv6 source address selection works on linux. [http://www.davidc.net/networking/ipv...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I found the service check and most likely your ICMPv6 issue as well to be caused by the way IPv6 source address selection works on linux. [http://www.davidc.net/networking/ipv6-source-address-selection-linux] Basically whenever heartbeat adds a service IP you cannot check IPVS/DR realservers anymore because linux will use the one that was added latest unless you mark it as deprecated. -- [[ZaphodB]]&lt;/div&gt;</summary>
		<author><name>ZaphodB</name></author>	</entry>

	<entry>
		<id>http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=5783</id>
		<title>Building Scalable DNS Cluster using LVS</title>
		<link rel="alternate" type="text/html" href="http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=5783"/>
				<updated>2008-10-30T17:57:51Z</updated>
		
		<summary type="html">&lt;p&gt;ZaphodB: /* [http://doc.powerdns.com/built-in-recursor.html PowerDNS recursor] */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
DNS (Domain Name Service) is one of the primary Internet services, which is to map human-friendly domain names to machine-friendly IP address. If there are a lot of people using DNS service (for example, subscribers use ISP's DNS server), one DNS server might be becoming a bottleneck, and the server might fail.&lt;br /&gt;
&lt;br /&gt;
Scalable DNS cluster can help provide scalability and availability of DNS service.&lt;br /&gt;
&lt;br /&gt;
The Example below is about setting up a cluster for recursive DNS but you can just as well use the same method for authorative DNS as well. Just remember that clients who use your cluster as a secondary nameservice would need to also-notify{} each of your realservers, not just the service-IP.&lt;br /&gt;
&lt;br /&gt;
== Architecture ==&lt;br /&gt;
&lt;br /&gt;
DNS is a simple service, there is no affinity between requests from the same client. DNS usually listens for queries at UDP port 53 and TCP port 53.&lt;br /&gt;
&lt;br /&gt;
LVS can simply load balance UDP port 53 and TCP port 53 among a set of DNS servers, and there is no need to setup any persistence options.&lt;br /&gt;
&lt;br /&gt;
== Configuration Example ==&lt;br /&gt;
&lt;br /&gt;
keepalived.conf:&lt;br /&gt;
 ! Balancer-Set for udp/53&lt;br /&gt;
 virtual_server 194.97.173.124 53 {&lt;br /&gt;
    delay_loop 10&lt;br /&gt;
    lb_algo wrr&lt;br /&gt;
    lb_kind DR&lt;br /&gt;
    protocol UDP&lt;br /&gt;
    ! persistence_timeout 1&lt;br /&gt;
    ! persistence_granularity 255.255.255.255&lt;br /&gt;
    ! eth1.105 -&amp;gt; kai eth1.105&lt;br /&gt;
    real_server 10.1.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.1.53.1 a resolve.test.roka.net @10.1.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    ! eth1.109 -&amp;gt; kai eth1.109&lt;br /&gt;
    real_server 10.3.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.3.53.1 a resolve.test.roka.net @10.3.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As you can dig (;-) we are using an A record with a low TTL to test the service for this setup is a recursive DNS cluster. So far dig works fine with 44 real_servers configured on an idle Dual PIII 800.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
on real_server kai we use the following netfilter setup to be able to direct the traffic to different BIND processes on the same machine/mac:&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.1.53.2 eth1.105&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.3.53.2 eth1.109&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
&lt;br /&gt;
=== [http://www.isc.org/index.pl?/sw/bind/ BIND9] ===&lt;br /&gt;
&lt;br /&gt;
When i wrote this example we were using two BIND processes on the same machine for BIND9 currently just runs faster when it is not threading. Here is something JINMEI Tatuya told me on the bind9-workers Mailinglist which turned out to be very true:&lt;br /&gt;
 If you go with disabling threads, you may also want to enable&lt;br /&gt;
 &amp;quot;internal memory allocation&amp;quot;.  (I hear that) it should use memory more&lt;br /&gt;
 efficiently (and can make the server faster) but is disabled by&lt;br /&gt;
 default due to response-performance reasons in the threaded case.  You&lt;br /&gt;
 can enable this feature by adding the following line&lt;br /&gt;
&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 1&lt;br /&gt;
&lt;br /&gt;
 just before the following part of bind9/lib/isc/mem.c:&lt;br /&gt;
&lt;br /&gt;
 #ifndef ISC_MEM_USE_INTERNAL_MALLOC&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 0&lt;br /&gt;
 #endif&lt;br /&gt;
Try it and you will keep it. ;) &lt;br /&gt;
&lt;br /&gt;
BIND 9.4 line makes use of this new internal malloc library by default now, but disabling threading will probably free you from the hickups some BIND9 users are experiencing.&lt;br /&gt;
&lt;br /&gt;
=== [http://doc.powerdns.com/built-in-recursor.html PowerDNS recursor] === &lt;br /&gt;
&lt;br /&gt;
This one is a recursive-only Nameserver with very limited authorative DNS capabilities. The author of this Example uses [http://doc.powerdns.com/built-in-recursor.html PowerDNS recursor] exclusively for his caching-only DNS cluster by now and is glad that while giving roughly the same queries per second performance it generates less SERVFAIL answers and is generally several times more robust than BIND9.&lt;br /&gt;
&lt;br /&gt;
=== added redundancy via iBGP ===&lt;br /&gt;
&lt;br /&gt;
If you have more than one Loadbalancer at different locations and you can convince your local Networker to let you speak BGP4+ to his routers you can use quagga with something like the following configuration to failover the service IP to the second LB if the first one goes down:&lt;br /&gt;
 !&lt;br /&gt;
 router bgp 5430&lt;br /&gt;
  no synchronization&lt;br /&gt;
  bgp router-id a.b.c.d&lt;br /&gt;
  redistribute connected route-map benice&lt;br /&gt;
  neighbor c.d.e.f remote-as 5430&lt;br /&gt;
  neighbor c.d.e.f description ffm4-j2&lt;br /&gt;
  neighbor c.d.e.f send-community both&lt;br /&gt;
  neighbor c.d.e.f soft-reconfiguration inbound&lt;br /&gt;
  neighbor c.d.e.f route-map nixda in&lt;br /&gt;
  neighbor c.d.e.f route-map benice out&lt;br /&gt;
  neighbor d.c.f.e remote-as 5430&lt;br /&gt;
  neighbor d.c.f.e description ffm4-j&lt;br /&gt;
  neighbor d.c.f.e send-community both&lt;br /&gt;
  neighbor d.c.f.e soft-reconfiguration inbound&lt;br /&gt;
  neighbor d.c.f.e route-map nixda in&lt;br /&gt;
  neighbor d.c.f.e route-map benice out&lt;br /&gt;
  no auto-summary&lt;br /&gt;
 !&lt;br /&gt;
 access-list line permit 127.0.0.1/32 exact-match&lt;br /&gt;
 access-list line deny any&lt;br /&gt;
 !&lt;br /&gt;
 ip prefix-list cns-dus2 description dus2 high-metric eq low-perference&lt;br /&gt;
 ip prefix-list cns-dus2 seq 5 permit 194.97.173.125/32&lt;br /&gt;
 ip prefix-list cns-dus2 seq 10 deny any&lt;br /&gt;
 ip prefix-list cns-ffm4 description ffm4 low-metric eq high-preference&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 5 permit 194.97.173.124/32&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 10 deny any&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 10&lt;br /&gt;
  match ip address prefix-list cns-ffm4&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 0&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 20&lt;br /&gt;
  match ip address prefix-list cns-dus2&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 1&lt;br /&gt;
 !&lt;br /&gt;
 route-map nixda deny 10&lt;br /&gt;
 !&lt;br /&gt;
This is the LB at FFM4. Note that the metric at the DUS2 LB is just the other way around.&lt;br /&gt;
Here we fancy talking to two core-routers from each LB for extra redundancy.&lt;br /&gt;
You can also have an internal anycast ServiceIP if you use the same metric at both LBs and make sure they are attached to the same level of router network-topology-wise. This way traffic gets shared between the two loadbalancers according to your network-topology most interesting of course for large dialin ISPs.&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
dig does not return a non-zero error code when receiving a SERVFAIL but there are situations when some BIND9 versions return SERVFAIL for any query for example when they are out of memory. For a recursive DNS cluster situation we would want to take such BIND processes out of service.&lt;br /&gt;
&lt;br /&gt;
==== Workaround ====&lt;br /&gt;
&lt;br /&gt;
use the following perl script as a wrapper for dig which is quite ugly for perl is an interpretated language and forking it is not much fun so this consumes much user cpu when executed every 6 seconds.&lt;br /&gt;
 #!/usr/bin/perl&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
 # cmdline arguments: &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&lt;br /&gt;
 # /usr/bin/dig -b 10.5.53.1 IN A 2.0.0.127.my.test @10.5.53.2 +time=1 +tries=5 +fail&lt;br /&gt;
 if(&lt;br /&gt;
        ((defined $ARGV[0])&amp;amp;&amp;amp;($ARGV[0]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[1])&amp;amp;&amp;amp;($ARGV[1]=~/^(IN|CHAOS)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[2])&amp;amp;&amp;amp;($ARGV[2]=~/^(A|ANY|MX|PTR|SRV|TXT|AAAA|NS|CNAME|SOA)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[3])&amp;amp;&amp;amp;($ARGV[3]=~/^[A-Za-z0-9\-\.]+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[4])&amp;amp;&amp;amp;($ARGV[4]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[5])&amp;amp;&amp;amp;($ARGV[5]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[6])&amp;amp;&amp;amp;($ARGV[6]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[7])&amp;amp;&amp;amp;($ARGV[7]=~/^\S+$/))&lt;br /&gt;
        ) {&lt;br /&gt;
        my $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        if((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^tcp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;tcp&amp;quot;;&lt;br /&gt;
        } elsif ((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^udp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        my (@res)=`/usr/bin/dig -b $ARGV[0] $ARGV[1] $ARGV[2] $ARGV[3] \@$ARGV[4] +time=$ARGV[5] +tries=$ARGV[6] +fail +$transport 2&amp;gt;&amp;amp;1`;&lt;br /&gt;
        my $return=$?;&lt;br /&gt;
        if(my $error=(map {/status:\s*($ARGV[7])/ ? $1 : ()} @res)[0]) {&lt;br /&gt;
                die(&amp;quot;$error&amp;quot;);&lt;br /&gt;
        } elsif ($return!=0) {&lt;br /&gt;
                die(&amp;quot;dig returned: \&amp;quot;$return\&amp;quot;&amp;quot;);&lt;br /&gt;
        } elsif ($return==0) {&lt;br /&gt;
                exit 0;&lt;br /&gt;
        } else {&lt;br /&gt;
                die(&amp;quot;error: \&amp;quot;$return\&amp;quot; HAS BAD VALUE!&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
 } else {&lt;br /&gt;
        die(&amp;quot;dig-wrapper.pl &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
Ah yes, forgot to say: The Dual PIII 800 is not idleing around anymore - its busy running this script 44 times every 6 seconds, which accounts for roughly 12% user cpu and 5% system used at a query rate of ~3600q/s.&lt;br /&gt;
&lt;br /&gt;
==== Solution ====&lt;br /&gt;
&lt;br /&gt;
use a patched version of dig?&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
It still just works.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{lvs-example-stub}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:LVS Examples|DNS]]&lt;/div&gt;</summary>
		<author><name>ZaphodB</name></author>	</entry>

	<entry>
		<id>http://kb.linux-vs.org/wiki?title=Talk:Building_Scalable_DNS_Cluster_using_LVS&amp;diff=5756</id>
		<title>Talk:Building Scalable DNS Cluster using LVS</title>
		<link rel="alternate" type="text/html" href="http://kb.linux-vs.org/wiki?title=Talk:Building_Scalable_DNS_Cluster_using_LVS&amp;diff=5756"/>
				<updated>2008-01-31T16:27:02Z</updated>
		
		<summary type="html">&lt;p&gt;ZaphodB: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Hi!&lt;br /&gt;
What about the storage of zone files? Where were they located? Thanks&lt;br /&gt;
&lt;br /&gt;
: Each DNS server can keep a copy of zone files and the change can be synchronized through some tools, or Each DNS server access shared network file system for zone files. --[[User:Wensong|Wensong]] 23:15, 6 June 2007 (CST)&lt;br /&gt;
: Right, my example is from a recursive DNS (caching-only) setup. You can do just the same for authoritative DNS but you need to keep your realservers in sync then else you would end up with a VIP/ServiceIP telling you different things each time for the same request as we used lb_algo wrr (weighted round robin) here. --[[User:ZaphodB|ZaphodB]] 17:26, 31 January 2008 (CET)&lt;/div&gt;</summary>
		<author><name>ZaphodB</name></author>	</entry>

	<entry>
		<id>http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=4215</id>
		<title>Building Scalable DNS Cluster using LVS</title>
		<link rel="alternate" type="text/html" href="http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=4215"/>
				<updated>2007-07-04T12:48:45Z</updated>
		
		<summary type="html">&lt;p&gt;ZaphodB: /* PowerDNS recursor */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
DNS (Domain Name Service) is one of the primary Internet services, which is to map human-friendly domain names to machine-friendly IP address. If there are a lot of people using DNS service (for example, subscribers use ISP's DNS server), one DNS server might be becoming a bottleneck, and the server might fail.&lt;br /&gt;
&lt;br /&gt;
Scalable DNS cluster can help provide scalability and availability of DNS service.&lt;br /&gt;
&lt;br /&gt;
The Example below is about setting up a cluster for recursive DNS but you can just as well use the same method for authorative DNS as well. Just remember that clients who use your cluster as a secondary nameservice would need to also-notify{} each of your realservers, not just the service-IP.&lt;br /&gt;
&lt;br /&gt;
== Architecture ==&lt;br /&gt;
&lt;br /&gt;
DNS is a simple service, there is no affinity between requests from the same client. DNS usually listens for queries at UDP port 53 and TCP port 53.&lt;br /&gt;
&lt;br /&gt;
LVS can simply load balance UDP port 53 and TCP port 53 among a set of DNS servers, and there is no need to setup any persistence options.&lt;br /&gt;
&lt;br /&gt;
== Configuration Example ==&lt;br /&gt;
&lt;br /&gt;
keepalived.conf:&lt;br /&gt;
 ! Balancer-Set for udp/53&lt;br /&gt;
 virtual_server 194.97.173.124 53 {&lt;br /&gt;
    delay_loop 10&lt;br /&gt;
    lb_algo wrr&lt;br /&gt;
    lb_kind DR&lt;br /&gt;
    protocol UDP&lt;br /&gt;
    ! persistence_timeout 1&lt;br /&gt;
    ! persistence_granularity 255.255.255.255&lt;br /&gt;
    ! eth1.105 -&amp;gt; kai eth1.105&lt;br /&gt;
    real_server 10.1.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.1.53.1 a resolve.test.roka.net @10.1.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    ! eth1.109 -&amp;gt; kai eth1.109&lt;br /&gt;
    real_server 10.3.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.3.53.1 a resolve.test.roka.net @10.3.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As you can dig (;-) we are using an A record with a low TTL to test the service for this setup is a recursive DNS cluster. So far dig works fine with 44 real_servers configured on an idle Dual PIII 800.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
on real_server kai we use the following netfilter setup to be able to direct the traffic to different BIND processes on the same machine/mac:&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.1.53.2 eth1.105&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.3.53.2 eth1.109&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
&lt;br /&gt;
=== [http://www.isc.org/index.pl?/sw/bind/ BIND9] ===&lt;br /&gt;
&lt;br /&gt;
When i wrote this example we were using two BIND processes on the same machine for BIND9 currently just runs faster when it is not threading. Here is something JINMEI Tatuya told me on the bind9-workers Mailinglist which turned out to be very true:&lt;br /&gt;
 If you go with disabling threads, you may also want to enable&lt;br /&gt;
 &amp;quot;internal memory allocation&amp;quot;.  (I hear that) it should use memory more&lt;br /&gt;
 efficiently (and can make the server faster) but is disabled by&lt;br /&gt;
 default due to response-performance reasons in the threaded case.  You&lt;br /&gt;
 can enable this feature by adding the following line&lt;br /&gt;
&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 1&lt;br /&gt;
&lt;br /&gt;
 just before the following part of bind9/lib/isc/mem.c:&lt;br /&gt;
&lt;br /&gt;
 #ifndef ISC_MEM_USE_INTERNAL_MALLOC&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 0&lt;br /&gt;
 #endif&lt;br /&gt;
Try it and you will keep it. ;) &lt;br /&gt;
&lt;br /&gt;
BIND 9.4 line makes use of this new internal malloc library by default now, but disabling threading will probably free you from the hickups some BIND9 users are experiencing.&lt;br /&gt;
&lt;br /&gt;
=== [http://doc.powerdns.com/built-in-recursor.html PowerDNS recursor] === &lt;br /&gt;
&lt;br /&gt;
This one is a recursive-only Nameserver with very limited authorative DNS capabilities. The author of this Example uses PowerDNS recursor (v.3.1.4) exclusively for his caching-only DNS cluster by now and is glad that while giving roughly the same queries per second performance it generates less SERVFAIL answers and is generally several times more robust than BIND9.&lt;br /&gt;
&lt;br /&gt;
=== added redundancy via iBGP ===&lt;br /&gt;
&lt;br /&gt;
If you have more than one Loadbalancer at different locations and you can convince your local Networker to let you speak BGP4+ to his routers you can use quagga with something like the following configuration to failover the service IP to the second LB if the first one goes down:&lt;br /&gt;
 !&lt;br /&gt;
 router bgp 5430&lt;br /&gt;
  no synchronization&lt;br /&gt;
  bgp router-id a.b.c.d&lt;br /&gt;
  redistribute connected route-map benice&lt;br /&gt;
  neighbor c.d.e.f remote-as 5430&lt;br /&gt;
  neighbor c.d.e.f description ffm4-j2&lt;br /&gt;
  neighbor c.d.e.f send-community both&lt;br /&gt;
  neighbor c.d.e.f soft-reconfiguration inbound&lt;br /&gt;
  neighbor c.d.e.f route-map nixda in&lt;br /&gt;
  neighbor c.d.e.f route-map benice out&lt;br /&gt;
  neighbor d.c.f.e remote-as 5430&lt;br /&gt;
  neighbor d.c.f.e description ffm4-j&lt;br /&gt;
  neighbor d.c.f.e send-community both&lt;br /&gt;
  neighbor d.c.f.e soft-reconfiguration inbound&lt;br /&gt;
  neighbor d.c.f.e route-map nixda in&lt;br /&gt;
  neighbor d.c.f.e route-map benice out&lt;br /&gt;
  no auto-summary&lt;br /&gt;
 !&lt;br /&gt;
 access-list line permit 127.0.0.1/32 exact-match&lt;br /&gt;
 access-list line deny any&lt;br /&gt;
 !&lt;br /&gt;
 ip prefix-list cns-dus2 description dus2 high-metric eq low-perference&lt;br /&gt;
 ip prefix-list cns-dus2 seq 5 permit 194.97.173.125/32&lt;br /&gt;
 ip prefix-list cns-dus2 seq 10 deny any&lt;br /&gt;
 ip prefix-list cns-ffm4 description ffm4 low-metric eq high-preference&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 5 permit 194.97.173.124/32&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 10 deny any&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 10&lt;br /&gt;
  match ip address prefix-list cns-ffm4&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 0&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 20&lt;br /&gt;
  match ip address prefix-list cns-dus2&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 1&lt;br /&gt;
 !&lt;br /&gt;
 route-map nixda deny 10&lt;br /&gt;
 !&lt;br /&gt;
This is the LB at FFM4. Note that the metric at the DUS2 LB is just the other way around.&lt;br /&gt;
Here we fancy talking to two core-routers from each LB for extra redundancy.&lt;br /&gt;
You can also have an internal anycast ServiceIP if you use the same metric at both LBs and make sure they are attached to the same level of router network-topology-wise. This way traffic gets shared between the two loadbalancers according to your network-topology most interesting of course for large dialin ISPs.&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
dig does not return a non-zero error code when receiving a SERVFAIL but there are situations when some BIND9 versions return SERVFAIL for any query for example when they are out of memory. For a recursive DNS cluster situation we would want to take such BIND processes out of service.&lt;br /&gt;
&lt;br /&gt;
==== Workaround ====&lt;br /&gt;
&lt;br /&gt;
use the following perl script as a wrapper for dig which is quite ugly for perl is an interpretated language and forking it is not much fun so this consumes much user cpu when executed every 6 seconds.&lt;br /&gt;
 #!/usr/bin/perl&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
 # cmdline arguments: &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&lt;br /&gt;
 # /usr/bin/dig -b 10.5.53.1 IN A 2.0.0.127.my.test @10.5.53.2 +time=1 +tries=5 +fail&lt;br /&gt;
 if(&lt;br /&gt;
        ((defined $ARGV[0])&amp;amp;&amp;amp;($ARGV[0]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[1])&amp;amp;&amp;amp;($ARGV[1]=~/^(IN|CHAOS)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[2])&amp;amp;&amp;amp;($ARGV[2]=~/^(A|ANY|MX|PTR|SRV|TXT|AAAA|NS|CNAME|SOA)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[3])&amp;amp;&amp;amp;($ARGV[3]=~/^[A-Za-z0-9\-\.]+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[4])&amp;amp;&amp;amp;($ARGV[4]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[5])&amp;amp;&amp;amp;($ARGV[5]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[6])&amp;amp;&amp;amp;($ARGV[6]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[7])&amp;amp;&amp;amp;($ARGV[7]=~/^\S+$/))&lt;br /&gt;
        ) {&lt;br /&gt;
        my $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        if((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^tcp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;tcp&amp;quot;;&lt;br /&gt;
        } elsif ((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^udp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        my (@res)=`/usr/bin/dig -b $ARGV[0] $ARGV[1] $ARGV[2] $ARGV[3] \@$ARGV[4] +time=$ARGV[5] +tries=$ARGV[6] +fail +$transport 2&amp;gt;&amp;amp;1`;&lt;br /&gt;
        my $return=$?;&lt;br /&gt;
        if(my $error=(map {/status:\s*($ARGV[7])/ ? $1 : ()} @res)[0]) {&lt;br /&gt;
                die(&amp;quot;$error&amp;quot;);&lt;br /&gt;
        } elsif ($return!=0) {&lt;br /&gt;
                die(&amp;quot;dig returned: \&amp;quot;$return\&amp;quot;&amp;quot;);&lt;br /&gt;
        } elsif ($return==0) {&lt;br /&gt;
                exit 0;&lt;br /&gt;
        } else {&lt;br /&gt;
                die(&amp;quot;error: \&amp;quot;$return\&amp;quot; HAS BAD VALUE!&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
 } else {&lt;br /&gt;
        die(&amp;quot;dig-wrapper.pl &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
Ah yes, forgot to say: The Dual PIII 800 is not idleing around anymore - its busy running this script 44 times every 6 seconds, which accounts for roughly 12% user cpu and 5% system used at a query rate of ~3600q/s.&lt;br /&gt;
&lt;br /&gt;
==== Solution ====&lt;br /&gt;
&lt;br /&gt;
use a patched version of dig?&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
It still just works.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{lvs-example-stub}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:LVS Examples|DNS]]&lt;/div&gt;</summary>
		<author><name>ZaphodB</name></author>	</entry>

	<entry>
		<id>http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=4214</id>
		<title>Building Scalable DNS Cluster using LVS</title>
		<link rel="alternate" type="text/html" href="http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=4214"/>
				<updated>2007-07-04T12:48:09Z</updated>
		
		<summary type="html">&lt;p&gt;ZaphodB: /* BIND9 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
DNS (Domain Name Service) is one of the primary Internet services, which is to map human-friendly domain names to machine-friendly IP address. If there are a lot of people using DNS service (for example, subscribers use ISP's DNS server), one DNS server might be becoming a bottleneck, and the server might fail.&lt;br /&gt;
&lt;br /&gt;
Scalable DNS cluster can help provide scalability and availability of DNS service.&lt;br /&gt;
&lt;br /&gt;
The Example below is about setting up a cluster for recursive DNS but you can just as well use the same method for authorative DNS as well. Just remember that clients who use your cluster as a secondary nameservice would need to also-notify{} each of your realservers, not just the service-IP.&lt;br /&gt;
&lt;br /&gt;
== Architecture ==&lt;br /&gt;
&lt;br /&gt;
DNS is a simple service, there is no affinity between requests from the same client. DNS usually listens for queries at UDP port 53 and TCP port 53.&lt;br /&gt;
&lt;br /&gt;
LVS can simply load balance UDP port 53 and TCP port 53 among a set of DNS servers, and there is no need to setup any persistence options.&lt;br /&gt;
&lt;br /&gt;
== Configuration Example ==&lt;br /&gt;
&lt;br /&gt;
keepalived.conf:&lt;br /&gt;
 ! Balancer-Set for udp/53&lt;br /&gt;
 virtual_server 194.97.173.124 53 {&lt;br /&gt;
    delay_loop 10&lt;br /&gt;
    lb_algo wrr&lt;br /&gt;
    lb_kind DR&lt;br /&gt;
    protocol UDP&lt;br /&gt;
    ! persistence_timeout 1&lt;br /&gt;
    ! persistence_granularity 255.255.255.255&lt;br /&gt;
    ! eth1.105 -&amp;gt; kai eth1.105&lt;br /&gt;
    real_server 10.1.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.1.53.1 a resolve.test.roka.net @10.1.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    ! eth1.109 -&amp;gt; kai eth1.109&lt;br /&gt;
    real_server 10.3.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.3.53.1 a resolve.test.roka.net @10.3.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As you can dig (;-) we are using an A record with a low TTL to test the service for this setup is a recursive DNS cluster. So far dig works fine with 44 real_servers configured on an idle Dual PIII 800.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
on real_server kai we use the following netfilter setup to be able to direct the traffic to different BIND processes on the same machine/mac:&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.1.53.2 eth1.105&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.3.53.2 eth1.109&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
&lt;br /&gt;
=== [http://www.isc.org/index.pl?/sw/bind/ BIND9] ===&lt;br /&gt;
&lt;br /&gt;
When i wrote this example we were using two BIND processes on the same machine for BIND9 currently just runs faster when it is not threading. Here is something JINMEI Tatuya told me on the bind9-workers Mailinglist which turned out to be very true:&lt;br /&gt;
 If you go with disabling threads, you may also want to enable&lt;br /&gt;
 &amp;quot;internal memory allocation&amp;quot;.  (I hear that) it should use memory more&lt;br /&gt;
 efficiently (and can make the server faster) but is disabled by&lt;br /&gt;
 default due to response-performance reasons in the threaded case.  You&lt;br /&gt;
 can enable this feature by adding the following line&lt;br /&gt;
&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 1&lt;br /&gt;
&lt;br /&gt;
 just before the following part of bind9/lib/isc/mem.c:&lt;br /&gt;
&lt;br /&gt;
 #ifndef ISC_MEM_USE_INTERNAL_MALLOC&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 0&lt;br /&gt;
 #endif&lt;br /&gt;
Try it and you will keep it. ;) &lt;br /&gt;
&lt;br /&gt;
BIND 9.4 line makes use of this new internal malloc library by default now, but disabling threading will probably free you from the hickups some BIND9 users are experiencing.&lt;br /&gt;
&lt;br /&gt;
=== PowerDNS recursor === &lt;br /&gt;
&lt;br /&gt;
This one is a recursive-only Nameserver with very limited authorative DNS capabilities. The author of this Example uses PowerDNS recursor (v.3.1.4) exclusively for his caching-only DNS cluster by now and is glad that while giving roughly the same queries per second performance it generates less SERVFAIL answers and is generally several times more robust than BIND9.&lt;br /&gt;
&lt;br /&gt;
=== added redundancy via iBGP ===&lt;br /&gt;
&lt;br /&gt;
If you have more than one Loadbalancer at different locations and you can convince your local Networker to let you speak BGP4+ to his routers you can use quagga with something like the following configuration to failover the service IP to the second LB if the first one goes down:&lt;br /&gt;
 !&lt;br /&gt;
 router bgp 5430&lt;br /&gt;
  no synchronization&lt;br /&gt;
  bgp router-id a.b.c.d&lt;br /&gt;
  redistribute connected route-map benice&lt;br /&gt;
  neighbor c.d.e.f remote-as 5430&lt;br /&gt;
  neighbor c.d.e.f description ffm4-j2&lt;br /&gt;
  neighbor c.d.e.f send-community both&lt;br /&gt;
  neighbor c.d.e.f soft-reconfiguration inbound&lt;br /&gt;
  neighbor c.d.e.f route-map nixda in&lt;br /&gt;
  neighbor c.d.e.f route-map benice out&lt;br /&gt;
  neighbor d.c.f.e remote-as 5430&lt;br /&gt;
  neighbor d.c.f.e description ffm4-j&lt;br /&gt;
  neighbor d.c.f.e send-community both&lt;br /&gt;
  neighbor d.c.f.e soft-reconfiguration inbound&lt;br /&gt;
  neighbor d.c.f.e route-map nixda in&lt;br /&gt;
  neighbor d.c.f.e route-map benice out&lt;br /&gt;
  no auto-summary&lt;br /&gt;
 !&lt;br /&gt;
 access-list line permit 127.0.0.1/32 exact-match&lt;br /&gt;
 access-list line deny any&lt;br /&gt;
 !&lt;br /&gt;
 ip prefix-list cns-dus2 description dus2 high-metric eq low-perference&lt;br /&gt;
 ip prefix-list cns-dus2 seq 5 permit 194.97.173.125/32&lt;br /&gt;
 ip prefix-list cns-dus2 seq 10 deny any&lt;br /&gt;
 ip prefix-list cns-ffm4 description ffm4 low-metric eq high-preference&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 5 permit 194.97.173.124/32&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 10 deny any&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 10&lt;br /&gt;
  match ip address prefix-list cns-ffm4&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 0&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 20&lt;br /&gt;
  match ip address prefix-list cns-dus2&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 1&lt;br /&gt;
 !&lt;br /&gt;
 route-map nixda deny 10&lt;br /&gt;
 !&lt;br /&gt;
This is the LB at FFM4. Note that the metric at the DUS2 LB is just the other way around.&lt;br /&gt;
Here we fancy talking to two core-routers from each LB for extra redundancy.&lt;br /&gt;
You can also have an internal anycast ServiceIP if you use the same metric at both LBs and make sure they are attached to the same level of router network-topology-wise. This way traffic gets shared between the two loadbalancers according to your network-topology most interesting of course for large dialin ISPs.&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
dig does not return a non-zero error code when receiving a SERVFAIL but there are situations when some BIND9 versions return SERVFAIL for any query for example when they are out of memory. For a recursive DNS cluster situation we would want to take such BIND processes out of service.&lt;br /&gt;
&lt;br /&gt;
==== Workaround ====&lt;br /&gt;
&lt;br /&gt;
use the following perl script as a wrapper for dig which is quite ugly for perl is an interpretated language and forking it is not much fun so this consumes much user cpu when executed every 6 seconds.&lt;br /&gt;
 #!/usr/bin/perl&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
 # cmdline arguments: &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&lt;br /&gt;
 # /usr/bin/dig -b 10.5.53.1 IN A 2.0.0.127.my.test @10.5.53.2 +time=1 +tries=5 +fail&lt;br /&gt;
 if(&lt;br /&gt;
        ((defined $ARGV[0])&amp;amp;&amp;amp;($ARGV[0]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[1])&amp;amp;&amp;amp;($ARGV[1]=~/^(IN|CHAOS)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[2])&amp;amp;&amp;amp;($ARGV[2]=~/^(A|ANY|MX|PTR|SRV|TXT|AAAA|NS|CNAME|SOA)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[3])&amp;amp;&amp;amp;($ARGV[3]=~/^[A-Za-z0-9\-\.]+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[4])&amp;amp;&amp;amp;($ARGV[4]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[5])&amp;amp;&amp;amp;($ARGV[5]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[6])&amp;amp;&amp;amp;($ARGV[6]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[7])&amp;amp;&amp;amp;($ARGV[7]=~/^\S+$/))&lt;br /&gt;
        ) {&lt;br /&gt;
        my $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        if((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^tcp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;tcp&amp;quot;;&lt;br /&gt;
        } elsif ((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^udp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        my (@res)=`/usr/bin/dig -b $ARGV[0] $ARGV[1] $ARGV[2] $ARGV[3] \@$ARGV[4] +time=$ARGV[5] +tries=$ARGV[6] +fail +$transport 2&amp;gt;&amp;amp;1`;&lt;br /&gt;
        my $return=$?;&lt;br /&gt;
        if(my $error=(map {/status:\s*($ARGV[7])/ ? $1 : ()} @res)[0]) {&lt;br /&gt;
                die(&amp;quot;$error&amp;quot;);&lt;br /&gt;
        } elsif ($return!=0) {&lt;br /&gt;
                die(&amp;quot;dig returned: \&amp;quot;$return\&amp;quot;&amp;quot;);&lt;br /&gt;
        } elsif ($return==0) {&lt;br /&gt;
                exit 0;&lt;br /&gt;
        } else {&lt;br /&gt;
                die(&amp;quot;error: \&amp;quot;$return\&amp;quot; HAS BAD VALUE!&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
 } else {&lt;br /&gt;
        die(&amp;quot;dig-wrapper.pl &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
Ah yes, forgot to say: The Dual PIII 800 is not idleing around anymore - its busy running this script 44 times every 6 seconds, which accounts for roughly 12% user cpu and 5% system used at a query rate of ~3600q/s.&lt;br /&gt;
&lt;br /&gt;
==== Solution ====&lt;br /&gt;
&lt;br /&gt;
use a patched version of dig?&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
It still just works.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{lvs-example-stub}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:LVS Examples|DNS]]&lt;/div&gt;</summary>
		<author><name>ZaphodB</name></author>	</entry>

	<entry>
		<id>http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=4213</id>
		<title>Building Scalable DNS Cluster using LVS</title>
		<link rel="alternate" type="text/html" href="http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=4213"/>
				<updated>2007-07-04T12:47:38Z</updated>
		
		<summary type="html">&lt;p&gt;ZaphodB: /* BIND9 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
DNS (Domain Name Service) is one of the primary Internet services, which is to map human-friendly domain names to machine-friendly IP address. If there are a lot of people using DNS service (for example, subscribers use ISP's DNS server), one DNS server might be becoming a bottleneck, and the server might fail.&lt;br /&gt;
&lt;br /&gt;
Scalable DNS cluster can help provide scalability and availability of DNS service.&lt;br /&gt;
&lt;br /&gt;
The Example below is about setting up a cluster for recursive DNS but you can just as well use the same method for authorative DNS as well. Just remember that clients who use your cluster as a secondary nameservice would need to also-notify{} each of your realservers, not just the service-IP.&lt;br /&gt;
&lt;br /&gt;
== Architecture ==&lt;br /&gt;
&lt;br /&gt;
DNS is a simple service, there is no affinity between requests from the same client. DNS usually listens for queries at UDP port 53 and TCP port 53.&lt;br /&gt;
&lt;br /&gt;
LVS can simply load balance UDP port 53 and TCP port 53 among a set of DNS servers, and there is no need to setup any persistence options.&lt;br /&gt;
&lt;br /&gt;
== Configuration Example ==&lt;br /&gt;
&lt;br /&gt;
keepalived.conf:&lt;br /&gt;
 ! Balancer-Set for udp/53&lt;br /&gt;
 virtual_server 194.97.173.124 53 {&lt;br /&gt;
    delay_loop 10&lt;br /&gt;
    lb_algo wrr&lt;br /&gt;
    lb_kind DR&lt;br /&gt;
    protocol UDP&lt;br /&gt;
    ! persistence_timeout 1&lt;br /&gt;
    ! persistence_granularity 255.255.255.255&lt;br /&gt;
    ! eth1.105 -&amp;gt; kai eth1.105&lt;br /&gt;
    real_server 10.1.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.1.53.1 a resolve.test.roka.net @10.1.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    ! eth1.109 -&amp;gt; kai eth1.109&lt;br /&gt;
    real_server 10.3.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.3.53.1 a resolve.test.roka.net @10.3.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As you can dig (;-) we are using an A record with a low TTL to test the service for this setup is a recursive DNS cluster. So far dig works fine with 44 real_servers configured on an idle Dual PIII 800.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
on real_server kai we use the following netfilter setup to be able to direct the traffic to different BIND processes on the same machine/mac:&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.1.53.2 eth1.105&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.3.53.2 eth1.109&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
&lt;br /&gt;
=== BIND9 ===&lt;br /&gt;
&lt;br /&gt;
When i wrote this example we were using two &amp;lt;a href=&amp;quot;http://www.isc.org/index.pl?/sw/bind/&amp;quot;&amp;gt;BIND&amp;lt;/a&amp;gt; processes on the same machine for BIND9 currently just runs faster when it is not threading. Here is something JINMEI Tatuya told me on the bind9-workers Mailinglist which turned out to be very true:&lt;br /&gt;
 If you go with disabling threads, you may also want to enable&lt;br /&gt;
 &amp;quot;internal memory allocation&amp;quot;.  (I hear that) it should use memory more&lt;br /&gt;
 efficiently (and can make the server faster) but is disabled by&lt;br /&gt;
 default due to response-performance reasons in the threaded case.  You&lt;br /&gt;
 can enable this feature by adding the following line&lt;br /&gt;
&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 1&lt;br /&gt;
&lt;br /&gt;
 just before the following part of bind9/lib/isc/mem.c:&lt;br /&gt;
&lt;br /&gt;
 #ifndef ISC_MEM_USE_INTERNAL_MALLOC&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 0&lt;br /&gt;
 #endif&lt;br /&gt;
Try it and you will keep it. ;) &lt;br /&gt;
&lt;br /&gt;
BIND 9.4 line makes use of this new internal malloc library by default now, but disabling threading will probably free you from the hickups some BIND9 users are experiencing.&lt;br /&gt;
&lt;br /&gt;
=== PowerDNS recursor === &lt;br /&gt;
&lt;br /&gt;
This one is a recursive-only Nameserver with very limited authorative DNS capabilities. The author of this Example uses PowerDNS recursor (v.3.1.4) exclusively for his caching-only DNS cluster by now and is glad that while giving roughly the same queries per second performance it generates less SERVFAIL answers and is generally several times more robust than BIND9.&lt;br /&gt;
&lt;br /&gt;
=== added redundancy via iBGP ===&lt;br /&gt;
&lt;br /&gt;
If you have more than one Loadbalancer at different locations and you can convince your local Networker to let you speak BGP4+ to his routers you can use quagga with something like the following configuration to failover the service IP to the second LB if the first one goes down:&lt;br /&gt;
 !&lt;br /&gt;
 router bgp 5430&lt;br /&gt;
  no synchronization&lt;br /&gt;
  bgp router-id a.b.c.d&lt;br /&gt;
  redistribute connected route-map benice&lt;br /&gt;
  neighbor c.d.e.f remote-as 5430&lt;br /&gt;
  neighbor c.d.e.f description ffm4-j2&lt;br /&gt;
  neighbor c.d.e.f send-community both&lt;br /&gt;
  neighbor c.d.e.f soft-reconfiguration inbound&lt;br /&gt;
  neighbor c.d.e.f route-map nixda in&lt;br /&gt;
  neighbor c.d.e.f route-map benice out&lt;br /&gt;
  neighbor d.c.f.e remote-as 5430&lt;br /&gt;
  neighbor d.c.f.e description ffm4-j&lt;br /&gt;
  neighbor d.c.f.e send-community both&lt;br /&gt;
  neighbor d.c.f.e soft-reconfiguration inbound&lt;br /&gt;
  neighbor d.c.f.e route-map nixda in&lt;br /&gt;
  neighbor d.c.f.e route-map benice out&lt;br /&gt;
  no auto-summary&lt;br /&gt;
 !&lt;br /&gt;
 access-list line permit 127.0.0.1/32 exact-match&lt;br /&gt;
 access-list line deny any&lt;br /&gt;
 !&lt;br /&gt;
 ip prefix-list cns-dus2 description dus2 high-metric eq low-perference&lt;br /&gt;
 ip prefix-list cns-dus2 seq 5 permit 194.97.173.125/32&lt;br /&gt;
 ip prefix-list cns-dus2 seq 10 deny any&lt;br /&gt;
 ip prefix-list cns-ffm4 description ffm4 low-metric eq high-preference&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 5 permit 194.97.173.124/32&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 10 deny any&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 10&lt;br /&gt;
  match ip address prefix-list cns-ffm4&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 0&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 20&lt;br /&gt;
  match ip address prefix-list cns-dus2&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 1&lt;br /&gt;
 !&lt;br /&gt;
 route-map nixda deny 10&lt;br /&gt;
 !&lt;br /&gt;
This is the LB at FFM4. Note that the metric at the DUS2 LB is just the other way around.&lt;br /&gt;
Here we fancy talking to two core-routers from each LB for extra redundancy.&lt;br /&gt;
You can also have an internal anycast ServiceIP if you use the same metric at both LBs and make sure they are attached to the same level of router network-topology-wise. This way traffic gets shared between the two loadbalancers according to your network-topology most interesting of course for large dialin ISPs.&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
dig does not return a non-zero error code when receiving a SERVFAIL but there are situations when some BIND9 versions return SERVFAIL for any query for example when they are out of memory. For a recursive DNS cluster situation we would want to take such BIND processes out of service.&lt;br /&gt;
&lt;br /&gt;
==== Workaround ====&lt;br /&gt;
&lt;br /&gt;
use the following perl script as a wrapper for dig which is quite ugly for perl is an interpretated language and forking it is not much fun so this consumes much user cpu when executed every 6 seconds.&lt;br /&gt;
 #!/usr/bin/perl&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
 # cmdline arguments: &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&lt;br /&gt;
 # /usr/bin/dig -b 10.5.53.1 IN A 2.0.0.127.my.test @10.5.53.2 +time=1 +tries=5 +fail&lt;br /&gt;
 if(&lt;br /&gt;
        ((defined $ARGV[0])&amp;amp;&amp;amp;($ARGV[0]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[1])&amp;amp;&amp;amp;($ARGV[1]=~/^(IN|CHAOS)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[2])&amp;amp;&amp;amp;($ARGV[2]=~/^(A|ANY|MX|PTR|SRV|TXT|AAAA|NS|CNAME|SOA)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[3])&amp;amp;&amp;amp;($ARGV[3]=~/^[A-Za-z0-9\-\.]+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[4])&amp;amp;&amp;amp;($ARGV[4]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[5])&amp;amp;&amp;amp;($ARGV[5]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[6])&amp;amp;&amp;amp;($ARGV[6]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[7])&amp;amp;&amp;amp;($ARGV[7]=~/^\S+$/))&lt;br /&gt;
        ) {&lt;br /&gt;
        my $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        if((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^tcp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;tcp&amp;quot;;&lt;br /&gt;
        } elsif ((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^udp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        my (@res)=`/usr/bin/dig -b $ARGV[0] $ARGV[1] $ARGV[2] $ARGV[3] \@$ARGV[4] +time=$ARGV[5] +tries=$ARGV[6] +fail +$transport 2&amp;gt;&amp;amp;1`;&lt;br /&gt;
        my $return=$?;&lt;br /&gt;
        if(my $error=(map {/status:\s*($ARGV[7])/ ? $1 : ()} @res)[0]) {&lt;br /&gt;
                die(&amp;quot;$error&amp;quot;);&lt;br /&gt;
        } elsif ($return!=0) {&lt;br /&gt;
                die(&amp;quot;dig returned: \&amp;quot;$return\&amp;quot;&amp;quot;);&lt;br /&gt;
        } elsif ($return==0) {&lt;br /&gt;
                exit 0;&lt;br /&gt;
        } else {&lt;br /&gt;
                die(&amp;quot;error: \&amp;quot;$return\&amp;quot; HAS BAD VALUE!&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
 } else {&lt;br /&gt;
        die(&amp;quot;dig-wrapper.pl &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
Ah yes, forgot to say: The Dual PIII 800 is not idleing around anymore - its busy running this script 44 times every 6 seconds, which accounts for roughly 12% user cpu and 5% system used at a query rate of ~3600q/s.&lt;br /&gt;
&lt;br /&gt;
==== Solution ====&lt;br /&gt;
&lt;br /&gt;
use a patched version of dig?&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
It still just works.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{lvs-example-stub}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:LVS Examples|DNS]]&lt;/div&gt;</summary>
		<author><name>ZaphodB</name></author>	</entry>

	<entry>
		<id>http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=4212</id>
		<title>Building Scalable DNS Cluster using LVS</title>
		<link rel="alternate" type="text/html" href="http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=4212"/>
				<updated>2007-07-04T12:46:12Z</updated>
		
		<summary type="html">&lt;p&gt;ZaphodB: /* BIND9 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
DNS (Domain Name Service) is one of the primary Internet services, which is to map human-friendly domain names to machine-friendly IP address. If there are a lot of people using DNS service (for example, subscribers use ISP's DNS server), one DNS server might be becoming a bottleneck, and the server might fail.&lt;br /&gt;
&lt;br /&gt;
Scalable DNS cluster can help provide scalability and availability of DNS service.&lt;br /&gt;
&lt;br /&gt;
The Example below is about setting up a cluster for recursive DNS but you can just as well use the same method for authorative DNS as well. Just remember that clients who use your cluster as a secondary nameservice would need to also-notify{} each of your realservers, not just the service-IP.&lt;br /&gt;
&lt;br /&gt;
== Architecture ==&lt;br /&gt;
&lt;br /&gt;
DNS is a simple service, there is no affinity between requests from the same client. DNS usually listens for queries at UDP port 53 and TCP port 53.&lt;br /&gt;
&lt;br /&gt;
LVS can simply load balance UDP port 53 and TCP port 53 among a set of DNS servers, and there is no need to setup any persistence options.&lt;br /&gt;
&lt;br /&gt;
== Configuration Example ==&lt;br /&gt;
&lt;br /&gt;
keepalived.conf:&lt;br /&gt;
 ! Balancer-Set for udp/53&lt;br /&gt;
 virtual_server 194.97.173.124 53 {&lt;br /&gt;
    delay_loop 10&lt;br /&gt;
    lb_algo wrr&lt;br /&gt;
    lb_kind DR&lt;br /&gt;
    protocol UDP&lt;br /&gt;
    ! persistence_timeout 1&lt;br /&gt;
    ! persistence_granularity 255.255.255.255&lt;br /&gt;
    ! eth1.105 -&amp;gt; kai eth1.105&lt;br /&gt;
    real_server 10.1.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.1.53.1 a resolve.test.roka.net @10.1.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    ! eth1.109 -&amp;gt; kai eth1.109&lt;br /&gt;
    real_server 10.3.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.3.53.1 a resolve.test.roka.net @10.3.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As you can dig (;-) we are using an A record with a low TTL to test the service for this setup is a recursive DNS cluster. So far dig works fine with 44 real_servers configured on an idle Dual PIII 800.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
on real_server kai we use the following netfilter setup to be able to direct the traffic to different BIND processes on the same machine/mac:&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.1.53.2 eth1.105&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.3.53.2 eth1.109&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
&lt;br /&gt;
=== BIND9 ===&lt;br /&gt;
&lt;br /&gt;
When i wrote this example we were using two BIND processes on the same machine for BIND9 currently just runs faster when it is not threading. Here is something JINMEI Tatuya told me on the bind9-workers Mailinglist which turned out to be very true:&lt;br /&gt;
 If you go with disabling threads, you may also want to enable&lt;br /&gt;
 &amp;quot;internal memory allocation&amp;quot;.  (I hear that) it should use memory more&lt;br /&gt;
 efficiently (and can make the server faster) but is disabled by&lt;br /&gt;
 default due to response-performance reasons in the threaded case.  You&lt;br /&gt;
 can enable this feature by adding the following line&lt;br /&gt;
&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 1&lt;br /&gt;
&lt;br /&gt;
 just before the following part of bind9/lib/isc/mem.c:&lt;br /&gt;
&lt;br /&gt;
 #ifndef ISC_MEM_USE_INTERNAL_MALLOC&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 0&lt;br /&gt;
 #endif&lt;br /&gt;
Try it and you will keep it. ;) &lt;br /&gt;
&lt;br /&gt;
BIND 9.4 line makes use of this new internal malloc library by default now, but disabling threading will probably free you from the hickups some BIND9 users are experiencing.&lt;br /&gt;
&lt;br /&gt;
=== PowerDNS recursor === &lt;br /&gt;
&lt;br /&gt;
This one is a recursive-only Nameserver with very limited authorative DNS capabilities. The author of this Example uses PowerDNS recursor (v.3.1.4) exclusively for his caching-only DNS cluster by now and is glad that while giving roughly the same queries per second performance it generates less SERVFAIL answers and is generally several times more robust than BIND9.&lt;br /&gt;
&lt;br /&gt;
=== added redundancy via iBGP ===&lt;br /&gt;
&lt;br /&gt;
If you have more than one Loadbalancer at different locations and you can convince your local Networker to let you speak BGP4+ to his routers you can use quagga with something like the following configuration to failover the service IP to the second LB if the first one goes down:&lt;br /&gt;
 !&lt;br /&gt;
 router bgp 5430&lt;br /&gt;
  no synchronization&lt;br /&gt;
  bgp router-id a.b.c.d&lt;br /&gt;
  redistribute connected route-map benice&lt;br /&gt;
  neighbor c.d.e.f remote-as 5430&lt;br /&gt;
  neighbor c.d.e.f description ffm4-j2&lt;br /&gt;
  neighbor c.d.e.f send-community both&lt;br /&gt;
  neighbor c.d.e.f soft-reconfiguration inbound&lt;br /&gt;
  neighbor c.d.e.f route-map nixda in&lt;br /&gt;
  neighbor c.d.e.f route-map benice out&lt;br /&gt;
  neighbor d.c.f.e remote-as 5430&lt;br /&gt;
  neighbor d.c.f.e description ffm4-j&lt;br /&gt;
  neighbor d.c.f.e send-community both&lt;br /&gt;
  neighbor d.c.f.e soft-reconfiguration inbound&lt;br /&gt;
  neighbor d.c.f.e route-map nixda in&lt;br /&gt;
  neighbor d.c.f.e route-map benice out&lt;br /&gt;
  no auto-summary&lt;br /&gt;
 !&lt;br /&gt;
 access-list line permit 127.0.0.1/32 exact-match&lt;br /&gt;
 access-list line deny any&lt;br /&gt;
 !&lt;br /&gt;
 ip prefix-list cns-dus2 description dus2 high-metric eq low-perference&lt;br /&gt;
 ip prefix-list cns-dus2 seq 5 permit 194.97.173.125/32&lt;br /&gt;
 ip prefix-list cns-dus2 seq 10 deny any&lt;br /&gt;
 ip prefix-list cns-ffm4 description ffm4 low-metric eq high-preference&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 5 permit 194.97.173.124/32&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 10 deny any&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 10&lt;br /&gt;
  match ip address prefix-list cns-ffm4&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 0&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 20&lt;br /&gt;
  match ip address prefix-list cns-dus2&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 1&lt;br /&gt;
 !&lt;br /&gt;
 route-map nixda deny 10&lt;br /&gt;
 !&lt;br /&gt;
This is the LB at FFM4. Note that the metric at the DUS2 LB is just the other way around.&lt;br /&gt;
Here we fancy talking to two core-routers from each LB for extra redundancy.&lt;br /&gt;
You can also have an internal anycast ServiceIP if you use the same metric at both LBs and make sure they are attached to the same level of router network-topology-wise. This way traffic gets shared between the two loadbalancers according to your network-topology most interesting of course for large dialin ISPs.&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
dig does not return a non-zero error code when receiving a SERVFAIL but there are situations when some BIND9 versions return SERVFAIL for any query for example when they are out of memory. For a recursive DNS cluster situation we would want to take such BIND processes out of service.&lt;br /&gt;
&lt;br /&gt;
==== Workaround ====&lt;br /&gt;
&lt;br /&gt;
use the following perl script as a wrapper for dig which is quite ugly for perl is an interpretated language and forking it is not much fun so this consumes much user cpu when executed every 6 seconds.&lt;br /&gt;
 #!/usr/bin/perl&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
 # cmdline arguments: &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&lt;br /&gt;
 # /usr/bin/dig -b 10.5.53.1 IN A 2.0.0.127.my.test @10.5.53.2 +time=1 +tries=5 +fail&lt;br /&gt;
 if(&lt;br /&gt;
        ((defined $ARGV[0])&amp;amp;&amp;amp;($ARGV[0]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[1])&amp;amp;&amp;amp;($ARGV[1]=~/^(IN|CHAOS)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[2])&amp;amp;&amp;amp;($ARGV[2]=~/^(A|ANY|MX|PTR|SRV|TXT|AAAA|NS|CNAME|SOA)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[3])&amp;amp;&amp;amp;($ARGV[3]=~/^[A-Za-z0-9\-\.]+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[4])&amp;amp;&amp;amp;($ARGV[4]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[5])&amp;amp;&amp;amp;($ARGV[5]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[6])&amp;amp;&amp;amp;($ARGV[6]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[7])&amp;amp;&amp;amp;($ARGV[7]=~/^\S+$/))&lt;br /&gt;
        ) {&lt;br /&gt;
        my $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        if((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^tcp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;tcp&amp;quot;;&lt;br /&gt;
        } elsif ((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^udp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        my (@res)=`/usr/bin/dig -b $ARGV[0] $ARGV[1] $ARGV[2] $ARGV[3] \@$ARGV[4] +time=$ARGV[5] +tries=$ARGV[6] +fail +$transport 2&amp;gt;&amp;amp;1`;&lt;br /&gt;
        my $return=$?;&lt;br /&gt;
        if(my $error=(map {/status:\s*($ARGV[7])/ ? $1 : ()} @res)[0]) {&lt;br /&gt;
                die(&amp;quot;$error&amp;quot;);&lt;br /&gt;
        } elsif ($return!=0) {&lt;br /&gt;
                die(&amp;quot;dig returned: \&amp;quot;$return\&amp;quot;&amp;quot;);&lt;br /&gt;
        } elsif ($return==0) {&lt;br /&gt;
                exit 0;&lt;br /&gt;
        } else {&lt;br /&gt;
                die(&amp;quot;error: \&amp;quot;$return\&amp;quot; HAS BAD VALUE!&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
 } else {&lt;br /&gt;
        die(&amp;quot;dig-wrapper.pl &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
Ah yes, forgot to say: The Dual PIII 800 is not idleing around anymore - its busy running this script 44 times every 6 seconds, which accounts for roughly 12% user cpu and 5% system used at a query rate of ~3600q/s.&lt;br /&gt;
&lt;br /&gt;
==== Solution ====&lt;br /&gt;
&lt;br /&gt;
use a patched version of dig?&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
It still just works.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{lvs-example-stub}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:LVS Examples|DNS]]&lt;/div&gt;</summary>
		<author><name>ZaphodB</name></author>	</entry>

	<entry>
		<id>http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=4211</id>
		<title>Building Scalable DNS Cluster using LVS</title>
		<link rel="alternate" type="text/html" href="http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=4211"/>
				<updated>2007-07-04T12:44:29Z</updated>
		
		<summary type="html">&lt;p&gt;ZaphodB: /* BIND9 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
DNS (Domain Name Service) is one of the primary Internet services, which is to map human-friendly domain names to machine-friendly IP address. If there are a lot of people using DNS service (for example, subscribers use ISP's DNS server), one DNS server might be becoming a bottleneck, and the server might fail.&lt;br /&gt;
&lt;br /&gt;
Scalable DNS cluster can help provide scalability and availability of DNS service.&lt;br /&gt;
&lt;br /&gt;
The Example below is about setting up a cluster for recursive DNS but you can just as well use the same method for authorative DNS as well. Just remember that clients who use your cluster as a secondary nameservice would need to also-notify{} each of your realservers, not just the service-IP.&lt;br /&gt;
&lt;br /&gt;
== Architecture ==&lt;br /&gt;
&lt;br /&gt;
DNS is a simple service, there is no affinity between requests from the same client. DNS usually listens for queries at UDP port 53 and TCP port 53.&lt;br /&gt;
&lt;br /&gt;
LVS can simply load balance UDP port 53 and TCP port 53 among a set of DNS servers, and there is no need to setup any persistence options.&lt;br /&gt;
&lt;br /&gt;
== Configuration Example ==&lt;br /&gt;
&lt;br /&gt;
keepalived.conf:&lt;br /&gt;
 ! Balancer-Set for udp/53&lt;br /&gt;
 virtual_server 194.97.173.124 53 {&lt;br /&gt;
    delay_loop 10&lt;br /&gt;
    lb_algo wrr&lt;br /&gt;
    lb_kind DR&lt;br /&gt;
    protocol UDP&lt;br /&gt;
    ! persistence_timeout 1&lt;br /&gt;
    ! persistence_granularity 255.255.255.255&lt;br /&gt;
    ! eth1.105 -&amp;gt; kai eth1.105&lt;br /&gt;
    real_server 10.1.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.1.53.1 a resolve.test.roka.net @10.1.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    ! eth1.109 -&amp;gt; kai eth1.109&lt;br /&gt;
    real_server 10.3.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.3.53.1 a resolve.test.roka.net @10.3.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As you can dig (;-) we are using an A record with a low TTL to test the service for this setup is a recursive DNS cluster. So far dig works fine with 44 real_servers configured on an idle Dual PIII 800.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
on real_server kai we use the following netfilter setup to be able to direct the traffic to different BIND processes on the same machine/mac:&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.1.53.2 eth1.105&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.3.53.2 eth1.109&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
&lt;br /&gt;
=== BIND9 ===&lt;br /&gt;
&lt;br /&gt;
When i wrote this example we were using two BIND processes on the same machine for BIND9 currently just runs faster when it is not threading. Here is something JINMEI Tatuya told me on the bind9-workers Mailinglist which turned out to be very true:&lt;br /&gt;
 If you go with disabling threads, you may also want to enable&lt;br /&gt;
 &amp;quot;internal memory allocation&amp;quot;.  (I hear that) it should use memory more&lt;br /&gt;
 efficiently (and can make the server faster) but is disabled by&lt;br /&gt;
 default due to response-performance reasons in the threaded case.  You&lt;br /&gt;
 can enable this feature by adding the following line&lt;br /&gt;
&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 1&lt;br /&gt;
&lt;br /&gt;
 just before the following part of bind9/lib/isc/mem.c:&lt;br /&gt;
&lt;br /&gt;
 #ifndef ISC_MEM_USE_INTERNAL_MALLOC&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 0&lt;br /&gt;
 #endif&lt;br /&gt;
Try it and you will keep it. ;) Btw. IIRC the upcoming BIND 9.4 line makes use of this new internal malloc library by default.&lt;br /&gt;
&lt;br /&gt;
=== PowerDNS recursor === &lt;br /&gt;
&lt;br /&gt;
This one is a recursive-only Nameserver with very limited authorative DNS capabilities. The author of this Example uses PowerDNS recursor (v.3.1.4) exclusively for his caching-only DNS cluster by now and is glad that while giving roughly the same queries per second performance it generates less SERVFAIL answers and is generally several times more robust than BIND9.&lt;br /&gt;
&lt;br /&gt;
=== added redundancy via iBGP ===&lt;br /&gt;
&lt;br /&gt;
If you have more than one Loadbalancer at different locations and you can convince your local Networker to let you speak BGP4+ to his routers you can use quagga with something like the following configuration to failover the service IP to the second LB if the first one goes down:&lt;br /&gt;
 !&lt;br /&gt;
 router bgp 5430&lt;br /&gt;
  no synchronization&lt;br /&gt;
  bgp router-id a.b.c.d&lt;br /&gt;
  redistribute connected route-map benice&lt;br /&gt;
  neighbor c.d.e.f remote-as 5430&lt;br /&gt;
  neighbor c.d.e.f description ffm4-j2&lt;br /&gt;
  neighbor c.d.e.f send-community both&lt;br /&gt;
  neighbor c.d.e.f soft-reconfiguration inbound&lt;br /&gt;
  neighbor c.d.e.f route-map nixda in&lt;br /&gt;
  neighbor c.d.e.f route-map benice out&lt;br /&gt;
  neighbor d.c.f.e remote-as 5430&lt;br /&gt;
  neighbor d.c.f.e description ffm4-j&lt;br /&gt;
  neighbor d.c.f.e send-community both&lt;br /&gt;
  neighbor d.c.f.e soft-reconfiguration inbound&lt;br /&gt;
  neighbor d.c.f.e route-map nixda in&lt;br /&gt;
  neighbor d.c.f.e route-map benice out&lt;br /&gt;
  no auto-summary&lt;br /&gt;
 !&lt;br /&gt;
 access-list line permit 127.0.0.1/32 exact-match&lt;br /&gt;
 access-list line deny any&lt;br /&gt;
 !&lt;br /&gt;
 ip prefix-list cns-dus2 description dus2 high-metric eq low-perference&lt;br /&gt;
 ip prefix-list cns-dus2 seq 5 permit 194.97.173.125/32&lt;br /&gt;
 ip prefix-list cns-dus2 seq 10 deny any&lt;br /&gt;
 ip prefix-list cns-ffm4 description ffm4 low-metric eq high-preference&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 5 permit 194.97.173.124/32&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 10 deny any&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 10&lt;br /&gt;
  match ip address prefix-list cns-ffm4&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 0&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 20&lt;br /&gt;
  match ip address prefix-list cns-dus2&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 1&lt;br /&gt;
 !&lt;br /&gt;
 route-map nixda deny 10&lt;br /&gt;
 !&lt;br /&gt;
This is the LB at FFM4. Note that the metric at the DUS2 LB is just the other way around.&lt;br /&gt;
Here we fancy talking to two core-routers from each LB for extra redundancy.&lt;br /&gt;
You can also have an internal anycast ServiceIP if you use the same metric at both LBs and make sure they are attached to the same level of router network-topology-wise. This way traffic gets shared between the two loadbalancers according to your network-topology most interesting of course for large dialin ISPs.&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
dig does not return a non-zero error code when receiving a SERVFAIL but there are situations when some BIND9 versions return SERVFAIL for any query for example when they are out of memory. For a recursive DNS cluster situation we would want to take such BIND processes out of service.&lt;br /&gt;
&lt;br /&gt;
==== Workaround ====&lt;br /&gt;
&lt;br /&gt;
use the following perl script as a wrapper for dig which is quite ugly for perl is an interpretated language and forking it is not much fun so this consumes much user cpu when executed every 6 seconds.&lt;br /&gt;
 #!/usr/bin/perl&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
 # cmdline arguments: &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&lt;br /&gt;
 # /usr/bin/dig -b 10.5.53.1 IN A 2.0.0.127.my.test @10.5.53.2 +time=1 +tries=5 +fail&lt;br /&gt;
 if(&lt;br /&gt;
        ((defined $ARGV[0])&amp;amp;&amp;amp;($ARGV[0]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[1])&amp;amp;&amp;amp;($ARGV[1]=~/^(IN|CHAOS)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[2])&amp;amp;&amp;amp;($ARGV[2]=~/^(A|ANY|MX|PTR|SRV|TXT|AAAA|NS|CNAME|SOA)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[3])&amp;amp;&amp;amp;($ARGV[3]=~/^[A-Za-z0-9\-\.]+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[4])&amp;amp;&amp;amp;($ARGV[4]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[5])&amp;amp;&amp;amp;($ARGV[5]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[6])&amp;amp;&amp;amp;($ARGV[6]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[7])&amp;amp;&amp;amp;($ARGV[7]=~/^\S+$/))&lt;br /&gt;
        ) {&lt;br /&gt;
        my $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        if((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^tcp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;tcp&amp;quot;;&lt;br /&gt;
        } elsif ((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^udp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        my (@res)=`/usr/bin/dig -b $ARGV[0] $ARGV[1] $ARGV[2] $ARGV[3] \@$ARGV[4] +time=$ARGV[5] +tries=$ARGV[6] +fail +$transport 2&amp;gt;&amp;amp;1`;&lt;br /&gt;
        my $return=$?;&lt;br /&gt;
        if(my $error=(map {/status:\s*($ARGV[7])/ ? $1 : ()} @res)[0]) {&lt;br /&gt;
                die(&amp;quot;$error&amp;quot;);&lt;br /&gt;
        } elsif ($return!=0) {&lt;br /&gt;
                die(&amp;quot;dig returned: \&amp;quot;$return\&amp;quot;&amp;quot;);&lt;br /&gt;
        } elsif ($return==0) {&lt;br /&gt;
                exit 0;&lt;br /&gt;
        } else {&lt;br /&gt;
                die(&amp;quot;error: \&amp;quot;$return\&amp;quot; HAS BAD VALUE!&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
 } else {&lt;br /&gt;
        die(&amp;quot;dig-wrapper.pl &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
Ah yes, forgot to say: The Dual PIII 800 is not idleing around anymore - its busy running this script 44 times every 6 seconds, which accounts for roughly 12% user cpu and 5% system used at a query rate of ~3600q/s.&lt;br /&gt;
&lt;br /&gt;
==== Solution ====&lt;br /&gt;
&lt;br /&gt;
use a patched version of dig?&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
It still just works.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{lvs-example-stub}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:LVS Examples|DNS]]&lt;/div&gt;</summary>
		<author><name>ZaphodB</name></author>	</entry>

	<entry>
		<id>http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=4210</id>
		<title>Building Scalable DNS Cluster using LVS</title>
		<link rel="alternate" type="text/html" href="http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=4210"/>
				<updated>2007-07-04T12:41:11Z</updated>
		
		<summary type="html">&lt;p&gt;ZaphodB: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
DNS (Domain Name Service) is one of the primary Internet services, which is to map human-friendly domain names to machine-friendly IP address. If there are a lot of people using DNS service (for example, subscribers use ISP's DNS server), one DNS server might be becoming a bottleneck, and the server might fail.&lt;br /&gt;
&lt;br /&gt;
Scalable DNS cluster can help provide scalability and availability of DNS service.&lt;br /&gt;
&lt;br /&gt;
The Example below is about setting up a cluster for recursive DNS but you can just as well use the same method for authorative DNS as well. Just remember that clients who use your cluster as a secondary nameservice would need to also-notify{} each of your realservers, not just the service-IP.&lt;br /&gt;
&lt;br /&gt;
== Architecture ==&lt;br /&gt;
&lt;br /&gt;
DNS is a simple service, there is no affinity between requests from the same client. DNS usually listens for queries at UDP port 53 and TCP port 53.&lt;br /&gt;
&lt;br /&gt;
LVS can simply load balance UDP port 53 and TCP port 53 among a set of DNS servers, and there is no need to setup any persistence options.&lt;br /&gt;
&lt;br /&gt;
== Configuration Example ==&lt;br /&gt;
&lt;br /&gt;
keepalived.conf:&lt;br /&gt;
 ! Balancer-Set for udp/53&lt;br /&gt;
 virtual_server 194.97.173.124 53 {&lt;br /&gt;
    delay_loop 10&lt;br /&gt;
    lb_algo wrr&lt;br /&gt;
    lb_kind DR&lt;br /&gt;
    protocol UDP&lt;br /&gt;
    ! persistence_timeout 1&lt;br /&gt;
    ! persistence_granularity 255.255.255.255&lt;br /&gt;
    ! eth1.105 -&amp;gt; kai eth1.105&lt;br /&gt;
    real_server 10.1.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.1.53.1 a resolve.test.roka.net @10.1.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    ! eth1.109 -&amp;gt; kai eth1.109&lt;br /&gt;
    real_server 10.3.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.3.53.1 a resolve.test.roka.net @10.3.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As you can dig (;-) we are using an A record with a low TTL to test the service for this setup is a recursive DNS cluster. So far dig works fine with 44 real_servers configured on an idle Dual PIII 800.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
on real_server kai we use the following netfilter setup to be able to direct the traffic to different BIND processes on the same machine/mac:&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.1.53.2 eth1.105&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.3.53.2 eth1.109&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
&lt;br /&gt;
=== BIND9 ===&lt;br /&gt;
&lt;br /&gt;
When i wrote this example we were using two BIND processes on the same machine for BIND9 currently just runs faster when it is not threading. Here is something Jinmei Tatuya told me on the bind9-workers Mailinglist which turned out to be very true:&lt;br /&gt;
 If you go with disabling threads, you may also want to enable&lt;br /&gt;
 &amp;quot;internal memory allocation&amp;quot;.  (I hear that) it should use memory more&lt;br /&gt;
 efficiently (and can make the server faster) but is disabled by&lt;br /&gt;
 default due to response-performance reasons in the threaded case.  You&lt;br /&gt;
 can enable this feature by adding the following line&lt;br /&gt;
&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 1&lt;br /&gt;
&lt;br /&gt;
 just before the following part of bind9/lib/isc/mem.c:&lt;br /&gt;
&lt;br /&gt;
 #ifndef ISC_MEM_USE_INTERNAL_MALLOC&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 0&lt;br /&gt;
 #endif&lt;br /&gt;
Try it and you will keep it. ;) Btw. IIRC the upcoming BIND 9.4 line makes use of this new internal malloc library by default.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PowerDNS recursor === &lt;br /&gt;
&lt;br /&gt;
This one is a recursive-only Nameserver with very limited authorative DNS capabilities. The author of this Example uses PowerDNS recursor (v.3.1.4) exclusively for his caching-only DNS cluster by now and is glad that while giving roughly the same queries per second performance it generates less SERVFAIL answers and is generally several times more robust than BIND9.&lt;br /&gt;
&lt;br /&gt;
=== added redundancy via iBGP ===&lt;br /&gt;
&lt;br /&gt;
If you have more than one Loadbalancer at different locations and you can convince your local Networker to let you speak BGP4+ to his routers you can use quagga with something like the following configuration to failover the service IP to the second LB if the first one goes down:&lt;br /&gt;
 !&lt;br /&gt;
 router bgp 5430&lt;br /&gt;
  no synchronization&lt;br /&gt;
  bgp router-id a.b.c.d&lt;br /&gt;
  redistribute connected route-map benice&lt;br /&gt;
  neighbor c.d.e.f remote-as 5430&lt;br /&gt;
  neighbor c.d.e.f description ffm4-j2&lt;br /&gt;
  neighbor c.d.e.f send-community both&lt;br /&gt;
  neighbor c.d.e.f soft-reconfiguration inbound&lt;br /&gt;
  neighbor c.d.e.f route-map nixda in&lt;br /&gt;
  neighbor c.d.e.f route-map benice out&lt;br /&gt;
  neighbor d.c.f.e remote-as 5430&lt;br /&gt;
  neighbor d.c.f.e description ffm4-j&lt;br /&gt;
  neighbor d.c.f.e send-community both&lt;br /&gt;
  neighbor d.c.f.e soft-reconfiguration inbound&lt;br /&gt;
  neighbor d.c.f.e route-map nixda in&lt;br /&gt;
  neighbor d.c.f.e route-map benice out&lt;br /&gt;
  no auto-summary&lt;br /&gt;
 !&lt;br /&gt;
 access-list line permit 127.0.0.1/32 exact-match&lt;br /&gt;
 access-list line deny any&lt;br /&gt;
 !&lt;br /&gt;
 ip prefix-list cns-dus2 description dus2 high-metric eq low-perference&lt;br /&gt;
 ip prefix-list cns-dus2 seq 5 permit 194.97.173.125/32&lt;br /&gt;
 ip prefix-list cns-dus2 seq 10 deny any&lt;br /&gt;
 ip prefix-list cns-ffm4 description ffm4 low-metric eq high-preference&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 5 permit 194.97.173.124/32&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 10 deny any&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 10&lt;br /&gt;
  match ip address prefix-list cns-ffm4&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 0&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 20&lt;br /&gt;
  match ip address prefix-list cns-dus2&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 1&lt;br /&gt;
 !&lt;br /&gt;
 route-map nixda deny 10&lt;br /&gt;
 !&lt;br /&gt;
This is the LB at FFM4. Note that the metric at the DUS2 LB is just the other way around.&lt;br /&gt;
Here we fancy talking to two core-routers from each LB for extra redundancy.&lt;br /&gt;
You can also have an internal anycast ServiceIP if you use the same metric at both LBs and make sure they are attached to the same level of router network-topology-wise. This way traffic gets shared between the two loadbalancers according to your network-topology most interesting of course for large dialin ISPs.&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
dig does not return a non-zero error code when receiving a SERVFAIL but there are situations when some BIND9 versions return SERVFAIL for any query for example when they are out of memory. For a recursive DNS cluster situation we would want to take such BIND processes out of service.&lt;br /&gt;
&lt;br /&gt;
==== Workaround ====&lt;br /&gt;
&lt;br /&gt;
use the following perl script as a wrapper for dig which is quite ugly for perl is an interpretated language and forking it is not much fun so this consumes much user cpu when executed every 6 seconds.&lt;br /&gt;
 #!/usr/bin/perl&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
 # cmdline arguments: &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&lt;br /&gt;
 # /usr/bin/dig -b 10.5.53.1 IN A 2.0.0.127.my.test @10.5.53.2 +time=1 +tries=5 +fail&lt;br /&gt;
 if(&lt;br /&gt;
        ((defined $ARGV[0])&amp;amp;&amp;amp;($ARGV[0]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[1])&amp;amp;&amp;amp;($ARGV[1]=~/^(IN|CHAOS)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[2])&amp;amp;&amp;amp;($ARGV[2]=~/^(A|ANY|MX|PTR|SRV|TXT|AAAA|NS|CNAME|SOA)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[3])&amp;amp;&amp;amp;($ARGV[3]=~/^[A-Za-z0-9\-\.]+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[4])&amp;amp;&amp;amp;($ARGV[4]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[5])&amp;amp;&amp;amp;($ARGV[5]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[6])&amp;amp;&amp;amp;($ARGV[6]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[7])&amp;amp;&amp;amp;($ARGV[7]=~/^\S+$/))&lt;br /&gt;
        ) {&lt;br /&gt;
        my $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        if((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^tcp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;tcp&amp;quot;;&lt;br /&gt;
        } elsif ((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^udp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        my (@res)=`/usr/bin/dig -b $ARGV[0] $ARGV[1] $ARGV[2] $ARGV[3] \@$ARGV[4] +time=$ARGV[5] +tries=$ARGV[6] +fail +$transport 2&amp;gt;&amp;amp;1`;&lt;br /&gt;
        my $return=$?;&lt;br /&gt;
        if(my $error=(map {/status:\s*($ARGV[7])/ ? $1 : ()} @res)[0]) {&lt;br /&gt;
                die(&amp;quot;$error&amp;quot;);&lt;br /&gt;
        } elsif ($return!=0) {&lt;br /&gt;
                die(&amp;quot;dig returned: \&amp;quot;$return\&amp;quot;&amp;quot;);&lt;br /&gt;
        } elsif ($return==0) {&lt;br /&gt;
                exit 0;&lt;br /&gt;
        } else {&lt;br /&gt;
                die(&amp;quot;error: \&amp;quot;$return\&amp;quot; HAS BAD VALUE!&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
 } else {&lt;br /&gt;
        die(&amp;quot;dig-wrapper.pl &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
Ah yes, forgot to say: The Dual PIII 800 is not idleing around anymore - its busy running this script 44 times every 6 seconds, which accounts for roughly 12% user cpu and 5% system used at a query rate of ~3600q/s.&lt;br /&gt;
&lt;br /&gt;
==== Solution ====&lt;br /&gt;
&lt;br /&gt;
use a patched version of dig?&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
It still just works.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{lvs-example-stub}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:LVS Examples|DNS]]&lt;/div&gt;</summary>
		<author><name>ZaphodB</name></author>	</entry>

	<entry>
		<id>http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=4209</id>
		<title>Building Scalable DNS Cluster using LVS</title>
		<link rel="alternate" type="text/html" href="http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=4209"/>
				<updated>2007-07-04T12:37:45Z</updated>
		
		<summary type="html">&lt;p&gt;ZaphodB: /* Configuration Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
DNS (Domain Name Service) is one of the primary Internet services, which is to map human-friendly domain names to machine-friendly IP address. If there are a lot of people using DNS service (for example, subscribers use ISP's DNS server), one DNS server might be becoming a bottleneck, and the server might fail.&lt;br /&gt;
&lt;br /&gt;
Scalable DNS cluster can help provide scalability and availability of DNS service.&lt;br /&gt;
&lt;br /&gt;
== Architecture ==&lt;br /&gt;
&lt;br /&gt;
DNS is a simple service, there is no affinity between requests from the same client. DNS usually listens for queries at UDP port 53 and TCP port 53.&lt;br /&gt;
&lt;br /&gt;
LVS can simply load balance UDP port 53 and TCP port 53 among a set of DNS servers, and there is no need to setup any persistence options.&lt;br /&gt;
&lt;br /&gt;
== Configuration Example ==&lt;br /&gt;
&lt;br /&gt;
keepalived.conf:&lt;br /&gt;
 ! Balancer-Set for udp/53&lt;br /&gt;
 virtual_server 194.97.173.124 53 {&lt;br /&gt;
    delay_loop 10&lt;br /&gt;
    lb_algo wrr&lt;br /&gt;
    lb_kind DR&lt;br /&gt;
    protocol UDP&lt;br /&gt;
    ! persistence_timeout 1&lt;br /&gt;
    ! persistence_granularity 255.255.255.255&lt;br /&gt;
    ! eth1.105 -&amp;gt; kai eth1.105&lt;br /&gt;
    real_server 10.1.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.1.53.1 a resolve.test.roka.net @10.1.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    ! eth1.109 -&amp;gt; kai eth1.109&lt;br /&gt;
    real_server 10.3.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.3.53.1 a resolve.test.roka.net @10.3.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As you can dig (;-) we are using an A record with a low TTL to test the service for this setup is a recursive DNS cluster. So far dig works fine with 44 real_servers configured on an idle Dual PIII 800.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
on real_server kai we use the following netfilter setup to be able to direct the traffic to different BIND processes on the same machine/mac:&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.1.53.2 eth1.105&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.3.53.2 eth1.109&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
&lt;br /&gt;
=== BIND9 ===&lt;br /&gt;
&lt;br /&gt;
When i wrote this example we were using two BIND processes on the same machine for BIND9 currently just runs faster when it is not threading. Here is something Jinmei Tatuya told me on the bind9-workers Mailinglist which turned out to be very true:&lt;br /&gt;
 If you go with disabling threads, you may also want to enable&lt;br /&gt;
 &amp;quot;internal memory allocation&amp;quot;.  (I hear that) it should use memory more&lt;br /&gt;
 efficiently (and can make the server faster) but is disabled by&lt;br /&gt;
 default due to response-performance reasons in the threaded case.  You&lt;br /&gt;
 can enable this feature by adding the following line&lt;br /&gt;
&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 1&lt;br /&gt;
&lt;br /&gt;
 just before the following part of bind9/lib/isc/mem.c:&lt;br /&gt;
&lt;br /&gt;
 #ifndef ISC_MEM_USE_INTERNAL_MALLOC&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 0&lt;br /&gt;
 #endif&lt;br /&gt;
Try it and you will keep it. ;) Btw. IIRC the upcoming BIND 9.4 line makes use of this new internal malloc library by default.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PowerDNS recursor === &lt;br /&gt;
&lt;br /&gt;
This one is a recursive-only Nameserver with very limited authorative DNS capabilities. The author of this Example uses PowerDNS recursor (v.3.1.4) exclusively for his caching-only DNS cluster by now and is glad that while giving roughly the same queries per second performance it generates less SERVFAIL answers and is generally several times more robust than BIND9.&lt;br /&gt;
&lt;br /&gt;
=== added redundancy via iBGP ===&lt;br /&gt;
&lt;br /&gt;
If you have more than one Loadbalancer at different locations and you can convince your local Networker to let you speak BGP4+ to his routers you can use quagga with something like the following configuration to failover the service IP to the second LB if the first one goes down:&lt;br /&gt;
 !&lt;br /&gt;
 router bgp 5430&lt;br /&gt;
  no synchronization&lt;br /&gt;
  bgp router-id a.b.c.d&lt;br /&gt;
  redistribute connected route-map benice&lt;br /&gt;
  neighbor c.d.e.f remote-as 5430&lt;br /&gt;
  neighbor c.d.e.f description ffm4-j2&lt;br /&gt;
  neighbor c.d.e.f send-community both&lt;br /&gt;
  neighbor c.d.e.f soft-reconfiguration inbound&lt;br /&gt;
  neighbor c.d.e.f route-map nixda in&lt;br /&gt;
  neighbor c.d.e.f route-map benice out&lt;br /&gt;
  neighbor d.c.f.e remote-as 5430&lt;br /&gt;
  neighbor d.c.f.e description ffm4-j&lt;br /&gt;
  neighbor d.c.f.e send-community both&lt;br /&gt;
  neighbor d.c.f.e soft-reconfiguration inbound&lt;br /&gt;
  neighbor d.c.f.e route-map nixda in&lt;br /&gt;
  neighbor d.c.f.e route-map benice out&lt;br /&gt;
  no auto-summary&lt;br /&gt;
 !&lt;br /&gt;
 access-list line permit 127.0.0.1/32 exact-match&lt;br /&gt;
 access-list line deny any&lt;br /&gt;
 !&lt;br /&gt;
 ip prefix-list cns-dus2 description dus2 high-metric eq low-perference&lt;br /&gt;
 ip prefix-list cns-dus2 seq 5 permit 194.97.173.125/32&lt;br /&gt;
 ip prefix-list cns-dus2 seq 10 deny any&lt;br /&gt;
 ip prefix-list cns-ffm4 description ffm4 low-metric eq high-preference&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 5 permit 194.97.173.124/32&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 10 deny any&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 10&lt;br /&gt;
  match ip address prefix-list cns-ffm4&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 0&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 20&lt;br /&gt;
  match ip address prefix-list cns-dus2&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 1&lt;br /&gt;
 !&lt;br /&gt;
 route-map nixda deny 10&lt;br /&gt;
 !&lt;br /&gt;
This is the LB at FFM4. Note that the metric at the DUS2 LB is just the other way around.&lt;br /&gt;
Here we fancy talking to two core-routers from each LB for extra redundancy.&lt;br /&gt;
You can also have an internal anycast ServiceIP if you use the same metric at both LBs and make sure they are attached to the same level of router network-topology-wise. This way traffic gets shared between the two loadbalancers according to your network-topology most interesting of course for large dialin ISPs.&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
dig does not return a non-zero error code when receiving a SERVFAIL but there are situations when some BIND9 versions return SERVFAIL for any query for example when they are out of memory. For a recursive DNS cluster situation we would want to take such BIND processes out of service.&lt;br /&gt;
&lt;br /&gt;
==== Workaround ====&lt;br /&gt;
&lt;br /&gt;
use the following perl script as a wrapper for dig which is quite ugly for perl is an interpretated language and forking it is not much fun so this consumes much user cpu when executed every 6 seconds.&lt;br /&gt;
 #!/usr/bin/perl&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
 # cmdline arguments: &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&lt;br /&gt;
 # /usr/bin/dig -b 10.5.53.1 IN A 2.0.0.127.my.test @10.5.53.2 +time=1 +tries=5 +fail&lt;br /&gt;
 if(&lt;br /&gt;
        ((defined $ARGV[0])&amp;amp;&amp;amp;($ARGV[0]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[1])&amp;amp;&amp;amp;($ARGV[1]=~/^(IN|CHAOS)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[2])&amp;amp;&amp;amp;($ARGV[2]=~/^(A|ANY|MX|PTR|SRV|TXT|AAAA|NS|CNAME|SOA)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[3])&amp;amp;&amp;amp;($ARGV[3]=~/^[A-Za-z0-9\-\.]+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[4])&amp;amp;&amp;amp;($ARGV[4]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[5])&amp;amp;&amp;amp;($ARGV[5]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[6])&amp;amp;&amp;amp;($ARGV[6]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[7])&amp;amp;&amp;amp;($ARGV[7]=~/^\S+$/))&lt;br /&gt;
        ) {&lt;br /&gt;
        my $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        if((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^tcp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;tcp&amp;quot;;&lt;br /&gt;
        } elsif ((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^udp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        my (@res)=`/usr/bin/dig -b $ARGV[0] $ARGV[1] $ARGV[2] $ARGV[3] \@$ARGV[4] +time=$ARGV[5] +tries=$ARGV[6] +fail +$transport 2&amp;gt;&amp;amp;1`;&lt;br /&gt;
        my $return=$?;&lt;br /&gt;
        if(my $error=(map {/status:\s*($ARGV[7])/ ? $1 : ()} @res)[0]) {&lt;br /&gt;
                die(&amp;quot;$error&amp;quot;);&lt;br /&gt;
        } elsif ($return!=0) {&lt;br /&gt;
                die(&amp;quot;dig returned: \&amp;quot;$return\&amp;quot;&amp;quot;);&lt;br /&gt;
        } elsif ($return==0) {&lt;br /&gt;
                exit 0;&lt;br /&gt;
        } else {&lt;br /&gt;
                die(&amp;quot;error: \&amp;quot;$return\&amp;quot; HAS BAD VALUE!&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
 } else {&lt;br /&gt;
        die(&amp;quot;dig-wrapper.pl &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
Ah yes, forgot to say: The Dual PIII 800 is not idleing around anymore - its busy running this script 44 times every 6 seconds, which accounts for roughly 12% user cpu and 5% system used at a query rate of ~3600q/s.&lt;br /&gt;
&lt;br /&gt;
==== Solution ====&lt;br /&gt;
&lt;br /&gt;
use a patched version of dig?&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
It still just works.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{lvs-example-stub}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:LVS Examples|DNS]]&lt;/div&gt;</summary>
		<author><name>ZaphodB</name></author>	</entry>

	<entry>
		<id>http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=4208</id>
		<title>Building Scalable DNS Cluster using LVS</title>
		<link rel="alternate" type="text/html" href="http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=4208"/>
				<updated>2007-07-04T12:28:15Z</updated>
		
		<summary type="html">&lt;p&gt;ZaphodB: /* Architecture */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
DNS (Domain Name Service) is one of the primary Internet services, which is to map human-friendly domain names to machine-friendly IP address. If there are a lot of people using DNS service (for example, subscribers use ISP's DNS server), one DNS server might be becoming a bottleneck, and the server might fail.&lt;br /&gt;
&lt;br /&gt;
Scalable DNS cluster can help provide scalability and availability of DNS service.&lt;br /&gt;
&lt;br /&gt;
== Architecture ==&lt;br /&gt;
&lt;br /&gt;
DNS is a simple service, there is no affinity between requests from the same client. DNS usually listens for queries at UDP port 53 and TCP port 53.&lt;br /&gt;
&lt;br /&gt;
LVS can simply load balance UDP port 53 and TCP port 53 among a set of DNS servers, and there is no need to setup any persistence options.&lt;br /&gt;
&lt;br /&gt;
== Configuration Example ==&lt;br /&gt;
&lt;br /&gt;
keepalived.conf:&lt;br /&gt;
 ! Balancer-Set for udp/53&lt;br /&gt;
 virtual_server 194.97.173.124 53 {&lt;br /&gt;
    delay_loop 10&lt;br /&gt;
    lb_algo wrr&lt;br /&gt;
    lb_kind DR&lt;br /&gt;
    protocol UDP&lt;br /&gt;
    ! persistence_timeout 1&lt;br /&gt;
    ! persistence_granularity 255.255.255.255&lt;br /&gt;
    ! eth1.105 -&amp;gt; kai eth1.105&lt;br /&gt;
    real_server 10.1.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.1.53.1 a resolve.test.roka.net @10.1.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    ! eth1.109 -&amp;gt; kai eth1.109&lt;br /&gt;
    real_server 10.3.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.3.53.1 a resolve.test.roka.net @10.3.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As you can dig (;-) we are using an A record with a low TTL to test the service for this setup is a recursive DNS cluster. So far dig works fine with 44 real_servers configured on an idle Dual PIII 800.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
on real_server kai we use the following netfilter setup to be able to direct the traffic to different BIND processes on the same machine/mac:&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.1.53.2 eth1.105&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.3.53.2 eth1.109&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We are using two BIND processes on the same machine for BIND9 currently just runs faster when it is not threading. Here is something Jinmei Tatuya told me on the bind9-workers Mailinglist which turned out to be very true:&lt;br /&gt;
 If you go with disabling threads, you may also want to enable&lt;br /&gt;
 &amp;quot;internal memory allocation&amp;quot;.  (I hear that) it should use memory more&lt;br /&gt;
 efficiently (and can make the server faster) but is disabled by&lt;br /&gt;
 default due to response-performance reasons in the threaded case.  You&lt;br /&gt;
 can enable this feature by adding the following line&lt;br /&gt;
&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 1&lt;br /&gt;
&lt;br /&gt;
 just before the following part of bind9/lib/isc/mem.c:&lt;br /&gt;
&lt;br /&gt;
 #ifndef ISC_MEM_USE_INTERNAL_MALLOC&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 0&lt;br /&gt;
 #endif&lt;br /&gt;
Try it and you will keep it. ;) Btw. IIRC the upcoming BIND 9.4 line makes use of this new internal malloc library by default.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you have more than one Loadbalancer at different locations and you can convince your local Networker to let you speak BGP4+ to his routers you can use quagga with something like the following configuration to failover the service IP to the second LB if the first one goes down:&lt;br /&gt;
 !&lt;br /&gt;
 router bgp 5430&lt;br /&gt;
  no synchronization&lt;br /&gt;
  bgp router-id a.b.c.d&lt;br /&gt;
  redistribute connected route-map benice&lt;br /&gt;
  neighbor c.d.e.f remote-as 5430&lt;br /&gt;
  neighbor c.d.e.f description ffm4-j2&lt;br /&gt;
  neighbor c.d.e.f send-community both&lt;br /&gt;
  neighbor c.d.e.f soft-reconfiguration inbound&lt;br /&gt;
  neighbor c.d.e.f route-map nixda in&lt;br /&gt;
  neighbor c.d.e.f route-map benice out&lt;br /&gt;
  neighbor d.c.f.e remote-as 5430&lt;br /&gt;
  neighbor d.c.f.e description ffm4-j&lt;br /&gt;
  neighbor d.c.f.e send-community both&lt;br /&gt;
  neighbor d.c.f.e soft-reconfiguration inbound&lt;br /&gt;
  neighbor d.c.f.e route-map nixda in&lt;br /&gt;
  neighbor d.c.f.e route-map benice out&lt;br /&gt;
  no auto-summary&lt;br /&gt;
 !&lt;br /&gt;
 access-list line permit 127.0.0.1/32 exact-match&lt;br /&gt;
 access-list line deny any&lt;br /&gt;
 !&lt;br /&gt;
 ip prefix-list cns-dus2 description dus2 high-metric eq low-perference&lt;br /&gt;
 ip prefix-list cns-dus2 seq 5 permit 194.97.173.125/32&lt;br /&gt;
 ip prefix-list cns-dus2 seq 10 deny any&lt;br /&gt;
 ip prefix-list cns-ffm4 description ffm4 low-metric eq high-preference&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 5 permit 194.97.173.124/32&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 10 deny any&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 10&lt;br /&gt;
  match ip address prefix-list cns-ffm4&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 0&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 20&lt;br /&gt;
  match ip address prefix-list cns-dus2&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 1&lt;br /&gt;
 !&lt;br /&gt;
 route-map nixda deny 10&lt;br /&gt;
 !&lt;br /&gt;
This is the LB at FFM4. Note that the metric at the DUS2 LB is just the other way around.&lt;br /&gt;
Here we fancy talking to two core-routers from each LB for extra redundancy.&lt;br /&gt;
You can also have an internal anycast ServiceIP if you use the same metric at both LBs and make sure they are attached to the same level of router network-topology-wise. This way traffic gets shared between the two loadbalancers according to your network-topology most interesting of course for large dialin ISPs.&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
dig does not return a non-zero error code when receiving a SERVFAIL but there are situations when some BIND9 versions return SERVFAIL for any query for example when they are out of memory. For a recursive DNS cluster situation we would want to take such BIND processes out of service.&lt;br /&gt;
&lt;br /&gt;
==== Workaround ====&lt;br /&gt;
&lt;br /&gt;
use the following perl script as a wrapper for dig which is quite ugly for perl is an interpretated language and forking it is not much fun so this consumes much user cpu when executed every 6 seconds.&lt;br /&gt;
 #!/usr/bin/perl&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
 # cmdline arguments: &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&lt;br /&gt;
 # /usr/bin/dig -b 10.5.53.1 IN A 2.0.0.127.my.test @10.5.53.2 +time=1 +tries=5 +fail&lt;br /&gt;
 if(&lt;br /&gt;
        ((defined $ARGV[0])&amp;amp;&amp;amp;($ARGV[0]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[1])&amp;amp;&amp;amp;($ARGV[1]=~/^(IN|CHAOS)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[2])&amp;amp;&amp;amp;($ARGV[2]=~/^(A|ANY|MX|PTR|SRV|TXT|AAAA|NS|CNAME|SOA)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[3])&amp;amp;&amp;amp;($ARGV[3]=~/^[A-Za-z0-9\-\.]+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[4])&amp;amp;&amp;amp;($ARGV[4]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[5])&amp;amp;&amp;amp;($ARGV[5]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[6])&amp;amp;&amp;amp;($ARGV[6]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[7])&amp;amp;&amp;amp;($ARGV[7]=~/^\S+$/))&lt;br /&gt;
        ) {&lt;br /&gt;
        my $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        if((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^tcp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;tcp&amp;quot;;&lt;br /&gt;
        } elsif ((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^udp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        my (@res)=`/usr/bin/dig -b $ARGV[0] $ARGV[1] $ARGV[2] $ARGV[3] \@$ARGV[4] +time=$ARGV[5] +tries=$ARGV[6] +fail +$transport 2&amp;gt;&amp;amp;1`;&lt;br /&gt;
        my $return=$?;&lt;br /&gt;
        if(my $error=(map {/status:\s*($ARGV[7])/ ? $1 : ()} @res)[0]) {&lt;br /&gt;
                die(&amp;quot;$error&amp;quot;);&lt;br /&gt;
        } elsif ($return!=0) {&lt;br /&gt;
                die(&amp;quot;dig returned: \&amp;quot;$return\&amp;quot;&amp;quot;);&lt;br /&gt;
        } elsif ($return==0) {&lt;br /&gt;
                exit 0;&lt;br /&gt;
        } else {&lt;br /&gt;
                die(&amp;quot;error: \&amp;quot;$return\&amp;quot; HAS BAD VALUE!&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
 } else {&lt;br /&gt;
        die(&amp;quot;dig-wrapper.pl &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
Ah yes, forgot to say: The Dual PIII 800 is not idleing around anymore - its busy running this script 44 times every 6 seconds, which accounts for roughly 12% user cpu and 5% system used at a query rate of ~3600q/s.&lt;br /&gt;
&lt;br /&gt;
==== Solution ====&lt;br /&gt;
&lt;br /&gt;
use a patched version of dig?&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
It still just works.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{lvs-example-stub}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:LVS Examples|DNS]]&lt;/div&gt;</summary>
		<author><name>ZaphodB</name></author>	</entry>

	<entry>
		<id>http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=579</id>
		<title>Building Scalable DNS Cluster using LVS</title>
		<link rel="alternate" type="text/html" href="http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=579"/>
				<updated>2006-03-04T18:12:24Z</updated>
		
		<summary type="html">&lt;p&gt;ZaphodB: /* Configuration Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Architecture ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Configuration Example ==&lt;br /&gt;
&lt;br /&gt;
keepalived.conf:&lt;br /&gt;
 ! Balancer-Set for udp/53&lt;br /&gt;
 virtual_server 194.97.173.124 53 {&lt;br /&gt;
    delay_loop 10&lt;br /&gt;
    lb_algo wrr&lt;br /&gt;
    lb_kind DR&lt;br /&gt;
    protocol UDP&lt;br /&gt;
    ! persistence_timeout 1&lt;br /&gt;
    ! persistence_granularity 255.255.255.255&lt;br /&gt;
    ! eth1.105 -&amp;gt; kai eth1.105&lt;br /&gt;
    real_server 10.1.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.1.53.1 a resolve.test.roka.net @10.1.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    ! eth1.109 -&amp;gt; kai eth1.109&lt;br /&gt;
    real_server 10.3.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.3.53.1 a resolve.test.roka.net @10.3.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As you can dig (;-) we are using an A record with a low TTL to test the service for this setup is a recursive DNS cluster. So far dig works fine with 44 real_servers configured on an idle Dual PIII 800.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
on real_server kai we use the following netfilter setup to be able to direct the traffic to different BIND processes on the same machine/mac:&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.1.53.2 eth1.105&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.3.53.2 eth1.109&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We are using two BIND processes on the same machine for BIND9 currently just runs faster when it is not threading. Here is something Jinmei Tatuya told me on the bind9-workers Mailinglist which turned out to be very true:&lt;br /&gt;
 If you go with disabling threads, you may also want to enable&lt;br /&gt;
 &amp;quot;internal memory allocation&amp;quot;.  (I hear that) it should use memory more&lt;br /&gt;
 efficiently (and can make the server faster) but is disabled by&lt;br /&gt;
 default due to response-performance reasons in the threaded case.  You&lt;br /&gt;
 can enable this feature by adding the following line&lt;br /&gt;
&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 1&lt;br /&gt;
&lt;br /&gt;
 just before the following part of bind9/lib/isc/mem.c:&lt;br /&gt;
&lt;br /&gt;
 #ifndef ISC_MEM_USE_INTERNAL_MALLOC&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 0&lt;br /&gt;
 #endif&lt;br /&gt;
Try it and you will keep it. ;) Btw. IIRC the upcoming BIND 9.4 line makes use of this new internal malloc library by default.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you have more than one Loadbalancer at different locations and you can convince your local Networker to let you speak BGP4+ to his routers you can use quagga with something like the following configuration to failover the service IP to the second LB if the first one goes down:&lt;br /&gt;
 !&lt;br /&gt;
 router bgp 5430&lt;br /&gt;
  no synchronization&lt;br /&gt;
  bgp router-id a.b.c.d&lt;br /&gt;
  redistribute connected route-map benice&lt;br /&gt;
  neighbor c.d.e.f remote-as 5430&lt;br /&gt;
  neighbor c.d.e.f description ffm4-j2&lt;br /&gt;
  neighbor c.d.e.f send-community both&lt;br /&gt;
  neighbor c.d.e.f soft-reconfiguration inbound&lt;br /&gt;
  neighbor c.d.e.f route-map nixda in&lt;br /&gt;
  neighbor c.d.e.f route-map benice out&lt;br /&gt;
  neighbor d.c.f.e remote-as 5430&lt;br /&gt;
  neighbor d.c.f.e description ffm4-j&lt;br /&gt;
  neighbor d.c.f.e send-community both&lt;br /&gt;
  neighbor d.c.f.e soft-reconfiguration inbound&lt;br /&gt;
  neighbor d.c.f.e route-map nixda in&lt;br /&gt;
  neighbor d.c.f.e route-map benice out&lt;br /&gt;
  no auto-summary&lt;br /&gt;
 !&lt;br /&gt;
 access-list line permit 127.0.0.1/32 exact-match&lt;br /&gt;
 access-list line deny any&lt;br /&gt;
 !&lt;br /&gt;
 ip prefix-list cns-dus2 description dus2 high-metric eq low-perference&lt;br /&gt;
 ip prefix-list cns-dus2 seq 5 permit 194.97.173.125/32&lt;br /&gt;
 ip prefix-list cns-dus2 seq 10 deny any&lt;br /&gt;
 ip prefix-list cns-ffm4 description ffm4 low-metric eq high-preference&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 5 permit 194.97.173.124/32&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 10 deny any&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 10&lt;br /&gt;
  match ip address prefix-list cns-ffm4&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 0&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 20&lt;br /&gt;
  match ip address prefix-list cns-dus2&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 1&lt;br /&gt;
 !&lt;br /&gt;
 route-map nixda deny 10&lt;br /&gt;
 !&lt;br /&gt;
This is the LB at FFM4. Note that the metric at the DUS2 LB is just the other way around.&lt;br /&gt;
Here we fancy talking to two core-routers from each LB for extra redundancy.&lt;br /&gt;
You can also have an internal anycast ServiceIP if you use the same metric at both LBs and make sure they are attached to the same level of router network-topology-wise. This way traffic gets shared between the two loadbalancers according to your network-topology most interesting of course for large dialin ISPs.&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
dig does not return a non-zero error code when receiving a SERVFAIL but there are situations when some BIND9 versions return SERVFAIL for any query for example when they are out of memory. For a recursive DNS cluster situation we would want to take such BIND processes out of service.&lt;br /&gt;
&lt;br /&gt;
==== Workaround ====&lt;br /&gt;
&lt;br /&gt;
use the following perl script as a wrapper for dig which is quite ugly for perl is an interpretated language and forking it is not much fun so this consumes much user cpu when executed every 6 seconds.&lt;br /&gt;
 #!/usr/bin/perl&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
 # cmdline arguments: &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&lt;br /&gt;
 # /usr/bin/dig -b 10.5.53.1 IN A 2.0.0.127.my.test @10.5.53.2 +time=1 +tries=5 +fail&lt;br /&gt;
 if(&lt;br /&gt;
        ((defined $ARGV[0])&amp;amp;&amp;amp;($ARGV[0]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[1])&amp;amp;&amp;amp;($ARGV[1]=~/^(IN|CHAOS)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[2])&amp;amp;&amp;amp;($ARGV[2]=~/^(A|ANY|MX|PTR|SRV|TXT|AAAA|NS|CNAME|SOA)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[3])&amp;amp;&amp;amp;($ARGV[3]=~/^[A-Za-z0-9\-\.]+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[4])&amp;amp;&amp;amp;($ARGV[4]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[5])&amp;amp;&amp;amp;($ARGV[5]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[6])&amp;amp;&amp;amp;($ARGV[6]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[7])&amp;amp;&amp;amp;($ARGV[7]=~/^\S+$/))&lt;br /&gt;
        ) {&lt;br /&gt;
        my $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        if((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^tcp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;tcp&amp;quot;;&lt;br /&gt;
        } elsif ((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^udp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        my (@res)=`/usr/bin/dig -b $ARGV[0] $ARGV[1] $ARGV[2] $ARGV[3] \@$ARGV[4] +time=$ARGV[5] +tries=$ARGV[6] +fail +$transport 2&amp;gt;&amp;amp;1`;&lt;br /&gt;
        my $return=$?;&lt;br /&gt;
        if(my $error=(map {/status:\s*($ARGV[7])/ ? $1 : ()} @res)[0]) {&lt;br /&gt;
                die(&amp;quot;$error&amp;quot;);&lt;br /&gt;
        } elsif ($return!=0) {&lt;br /&gt;
                die(&amp;quot;dig returned: \&amp;quot;$return\&amp;quot;&amp;quot;);&lt;br /&gt;
        } elsif ($return==0) {&lt;br /&gt;
                exit 0;&lt;br /&gt;
        } else {&lt;br /&gt;
                die(&amp;quot;error: \&amp;quot;$return\&amp;quot; HAS BAD VALUE!&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
 } else {&lt;br /&gt;
        die(&amp;quot;dig-wrapper.pl &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
Ah yes, forgot to say: The Dual PIII 800 is not idleing around anymore - its busy running this script 44 times every 6 seconds, which accounts for roughly 12% user cpu and 5% system used at a query rate of ~3600q/s.&lt;br /&gt;
&lt;br /&gt;
==== Solution ====&lt;br /&gt;
&lt;br /&gt;
use a patched version of dig?&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
It still just works.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{lvs-example-stub}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:LVS Examples|DNS]]&lt;/div&gt;</summary>
		<author><name>ZaphodB</name></author>	</entry>

	<entry>
		<id>http://kb.linux-vs.org/wiki?title=FAQ&amp;diff=630</id>
		<title>FAQ</title>
		<link rel="alternate" type="text/html" href="http://kb.linux-vs.org/wiki?title=FAQ&amp;diff=630"/>
				<updated>2006-03-01T17:00:30Z</updated>
		
		<summary type="html">&lt;p&gt;ZaphodB: /* How do i get counters from ipvsadm in order to create graphs from? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== General ==&lt;br /&gt;
=== What's LVS? ===&lt;br /&gt;
&lt;br /&gt;
LVS stands for Linux Virtual Server, which is a highly scalable and highly available server built on a cluster of real servers, with the [[load balancer]] running on the Linux operating system. Users interact as if it were a single virtual server.&lt;br /&gt;
&lt;br /&gt;
=== Is LVS software free? ===&lt;br /&gt;
&lt;br /&gt;
Yes! All LVS software is released under the [http://www.gnu.org/copyleft/gpl.html GNU General Public License (GPL)].&lt;br /&gt;
&lt;br /&gt;
=== Is there a FreeBSD port of LVS software? ===&lt;br /&gt;
&lt;br /&gt;
Yes, there is a FreeBSD port of IPVS, which supports the [[LVS/DR]] and [[LVS/TUN]] methods now. See [http://dragon.linux-vs.org/~dragonfly/htm/lvs_freebsd.htm the LVS On FreeBSD page] for more information.&lt;br /&gt;
&lt;br /&gt;
=== Does LVS cluster support Linux servers only? ===&lt;br /&gt;
&lt;br /&gt;
No, real servers can almost run any operating systems in a LVS cluster, such as Linux, BSDs, Solaris, and Windows. [[LVS/NAT]] balance servers of the operating systems having TCP/IP support, [[LVS/TUN]] requires servers having IP Tunneling protocol, and [[LVS/DR]] requires servers having a non-arp device. Almost all the modern operating systems support non-arp device.&lt;br /&gt;
&lt;br /&gt;
== Performance ==&lt;br /&gt;
&lt;br /&gt;
=== How is the concurrent processing performance of current LVS software? ===&lt;br /&gt;
&lt;br /&gt;
The ultimate performance of LVS depends on hardware that LVS runs on. An ordinary box with a single Pentium III processor and 100Mbps NIC card running [[LVS/DR]] can handle about 10,000 connections per second for web service. We have heard that a powerful box with good hardware and kernel tuning achieved 50,000 connections per second.&lt;br /&gt;
&lt;br /&gt;
=== Can LVS handle more than 1 million simultaneous connections? ===&lt;br /&gt;
&lt;br /&gt;
Yes, LVS can handle much more than 1 million simultaneous connections. One connection just costs 128 bytes in the LVS box, so an LVS box with 1G memory can handle more than 8 million simultaneous connections.&lt;br /&gt;
&lt;br /&gt;
== Setup ==&lt;br /&gt;
&lt;br /&gt;
=== How do I check to see if my kernel has IPVS enabled? ===&lt;br /&gt;
&lt;br /&gt;
Try to run &amp;quot;modprobe ip_vs&amp;quot; and try to see if there is /proc/net/ip_vs. If so, your kernel has [[IPVS]] enabled. You can also run &amp;quot;cat /proc/net/ip_vs&amp;quot; or &amp;quot;ipvsadm -Ln&amp;quot; to see the version number of [[IPVS]].&lt;br /&gt;
&lt;br /&gt;
== Statistics ==&lt;br /&gt;
&lt;br /&gt;
=== How do i get counters from ipvsadm in order to create graphs from? ===&lt;br /&gt;
&lt;br /&gt;
The current kernel 2.6 version of ipvsadm (v1.24) supports&lt;br /&gt;
 ipvsadm --list --stats --numeric --exact&lt;br /&gt;
which gives you non-human-readable counters for Connections, Packets and Bytes for each Service Address and Realserver.&lt;/div&gt;</summary>
		<author><name>ZaphodB</name></author>	</entry>

	<entry>
		<id>http://kb.linux-vs.org/wiki?title=FAQ&amp;diff=572</id>
		<title>FAQ</title>
		<link rel="alternate" type="text/html" href="http://kb.linux-vs.org/wiki?title=FAQ&amp;diff=572"/>
				<updated>2006-03-01T16:28:05Z</updated>
		
		<summary type="html">&lt;p&gt;ZaphodB: typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== General ==&lt;br /&gt;
=== What's LVS? ===&lt;br /&gt;
&lt;br /&gt;
LVS stands for Linux Virtual Server, which is a highly scalable and highly available server built on a cluster of real servers, with the [[load balancer]] running on the Linux operating system. Users interact as if it were a single virtual server.&lt;br /&gt;
&lt;br /&gt;
=== Is LVS software free? ===&lt;br /&gt;
&lt;br /&gt;
Yes! All LVS software is released under the [http://www.gnu.org/copyleft/gpl.html GNU General Public License (GPL)].&lt;br /&gt;
&lt;br /&gt;
=== Is there a FreeBSD port of LVS software? ===&lt;br /&gt;
&lt;br /&gt;
Yes, there is a FreeBSD port of IPVS, which supports the [[LVS/DR]] and [[LVS/TUN]] methods now. See [http://dragon.linux-vs.org/~dragonfly/htm/lvs_freebsd.htm the LVS On FreeBSD page] for more information.&lt;br /&gt;
&lt;br /&gt;
=== Does LVS cluster support Linux servers only? ===&lt;br /&gt;
&lt;br /&gt;
No, real servers can almost run any operating systems in a LVS cluster, such as Linux, BSDs, Solaris, and Windows. [[LVS/NAT]] balance servers of the operating systems having TCP/IP support, [[LVS/TUN]] requires servers having IP Tunneling protocol, and [[LVS/DR]] requires servers having a non-arp device. Almost all the modern operating systems support non-arp device.&lt;br /&gt;
&lt;br /&gt;
== Performance ==&lt;br /&gt;
&lt;br /&gt;
=== How is the concurrent processing performance of current LVS software? ===&lt;br /&gt;
&lt;br /&gt;
The ultimate performance of LVS depends on hardware that LVS runs on. An ordinary box with a single Pentium III processor and 100Mbps NIC card running [[LVS/DR]] can handle about 10,000 connections per second for web service. We have heard that a powerful box with good hardware and kernel tuning achieved 50,000 connections per second.&lt;br /&gt;
&lt;br /&gt;
=== Can LVS handle more than 1 million simultaneous connections? ===&lt;br /&gt;
&lt;br /&gt;
Yes, LVS can handle much more than 1 million simultaneous connections. One connection just costs 128 bytes in the LVS box, so an LVS box with 1G memory can handle more than 8 million simultaneous connections.&lt;br /&gt;
&lt;br /&gt;
== Setup ==&lt;br /&gt;
&lt;br /&gt;
=== How do I check to see if my kernel has IPVS enabled? ===&lt;br /&gt;
&lt;br /&gt;
Try to run &amp;quot;modprobe ip_vs&amp;quot; and try to see if there is /proc/net/ip_vs. If so, your kernel has [[IPVS]] enabled. You can also run &amp;quot;cat /proc/net/ip_vs&amp;quot; or &amp;quot;ipvsadm -Ln&amp;quot; to see the version number of [[IPVS]].&lt;br /&gt;
&lt;br /&gt;
== Statistics ==&lt;br /&gt;
&lt;br /&gt;
=== How do i get counters from ipvsadm in order to create graphs from? ===&lt;br /&gt;
&lt;br /&gt;
 ipvsadm --list --stats --numeric --exact&lt;br /&gt;
gives you non-human-readable counters for Connections, Packets and Bytes for each Service Address and Realserver.&lt;/div&gt;</summary>
		<author><name>ZaphodB</name></author>	</entry>

	<entry>
		<id>http://kb.linux-vs.org/wiki?title=FAQ&amp;diff=571</id>
		<title>FAQ</title>
		<link rel="alternate" type="text/html" href="http://kb.linux-vs.org/wiki?title=FAQ&amp;diff=571"/>
				<updated>2006-03-01T16:27:39Z</updated>
		
		<summary type="html">&lt;p&gt;ZaphodB: get counter with ipvsadm --list --stats --numeric --exact&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== General ==&lt;br /&gt;
=== What's LVS? ===&lt;br /&gt;
&lt;br /&gt;
LVS stands for Linux Virtual Server, which is a highly scalable and highly available server built on a cluster of real servers, with the [[load balancer]] running on the Linux operating system. Users interact as if it were a single virtual server.&lt;br /&gt;
&lt;br /&gt;
=== Is LVS software free? ===&lt;br /&gt;
&lt;br /&gt;
Yes! All LVS software is released under the [http://www.gnu.org/copyleft/gpl.html GNU General Public License (GPL)].&lt;br /&gt;
&lt;br /&gt;
=== Is there a FreeBSD port of LVS software? ===&lt;br /&gt;
&lt;br /&gt;
Yes, there is a FreeBSD port of IPVS, which supports the [[LVS/DR]] and [[LVS/TUN]] methods now. See [http://dragon.linux-vs.org/~dragonfly/htm/lvs_freebsd.htm the LVS On FreeBSD page] for more information.&lt;br /&gt;
&lt;br /&gt;
=== Does LVS cluster support Linux servers only? ===&lt;br /&gt;
&lt;br /&gt;
No, real servers can almost run any operating systems in a LVS cluster, such as Linux, BSDs, Solaris, and Windows. [[LVS/NAT]] balance servers of the operating systems having TCP/IP support, [[LVS/TUN]] requires servers having IP Tunneling protocol, and [[LVS/DR]] requires servers having a non-arp device. Almost all the modern operating systems support non-arp device.&lt;br /&gt;
&lt;br /&gt;
== Performance ==&lt;br /&gt;
&lt;br /&gt;
=== How is the concurrent processing performance of current LVS software? ===&lt;br /&gt;
&lt;br /&gt;
The ultimate performance of LVS depends on hardware that LVS runs on. An ordinary box with a single Pentium III processor and 100Mbps NIC card running [[LVS/DR]] can handle about 10,000 connections per second for web service. We have heard that a powerful box with good hardware and kernel tuning achieved 50,000 connections per second.&lt;br /&gt;
&lt;br /&gt;
=== Can LVS handle more than 1 million simultaneous connections? ===&lt;br /&gt;
&lt;br /&gt;
Yes, LVS can handle much more than 1 million simultaneous connections. One connection just costs 128 bytes in the LVS box, so an LVS box with 1G memory can handle more than 8 million simultaneous connections.&lt;br /&gt;
&lt;br /&gt;
== Setup ==&lt;br /&gt;
&lt;br /&gt;
=== How do I check to see if my kernel has IPVS enabled? ===&lt;br /&gt;
&lt;br /&gt;
Try to run &amp;quot;modprobe ip_vs&amp;quot; and try to see if there is /proc/net/ip_vs. If so, your kernel has [[IPVS]] enabled. You can also run &amp;quot;cat /proc/net/ip_vs&amp;quot; or &amp;quot;ipvsadm -Ln&amp;quot; to see the version number of [[IPVS]].&lt;br /&gt;
&lt;br /&gt;
== Statistics ==&lt;br /&gt;
&lt;br /&gt;
=== How do i get counters from ipvsadm in to create graphs from? ===&lt;br /&gt;
&lt;br /&gt;
 ipvsadm --list --stats --numeric --exact&lt;br /&gt;
gives you non-human-readable counters for Connections, Packets and Bytes for each Service Address and Realserver.&lt;/div&gt;</summary>
		<author><name>ZaphodB</name></author>	</entry>

	<entry>
		<id>http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=575</id>
		<title>Building Scalable DNS Cluster using LVS</title>
		<link rel="alternate" type="text/html" href="http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=575"/>
				<updated>2006-03-01T16:16:42Z</updated>
		
		<summary type="html">&lt;p&gt;ZaphodB: /* Workaround */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Architecture ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Configuration Example ==&lt;br /&gt;
&lt;br /&gt;
keepalived.conf:&lt;br /&gt;
 ! Balancer-Set for udp/53&lt;br /&gt;
 virtual_server 194.97.173.124 53 {&lt;br /&gt;
    delay_loop 10&lt;br /&gt;
    lb_algo wrr&lt;br /&gt;
    lb_kind DR&lt;br /&gt;
    protocol UDP&lt;br /&gt;
    ! persistence_timeout 1&lt;br /&gt;
    ! persistence_granularity 255.255.255.255&lt;br /&gt;
    ! eth1.105 -&amp;gt; kai eth1.105&lt;br /&gt;
    real_server 10.1.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.1.53.1 a resolve.test.roka.net @10.1.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    ! eth1.109 -&amp;gt; kai eth1.109&lt;br /&gt;
    real_server 10.3.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.3.53.1 a resolve.test.roka.net @10.3.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As you can dig (;-) we are using an A record with a low TTL to test the service for this setup is a recursive DNS cluster. So far dig works fine with 44 real_servers configured on an idle Dual PIII 800.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
on real_server kai we use the following netfilter setup to be able to direct the traffic to different BIND processes on the same machine/mac:&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.1.53.2 eth1.105&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.3.53.2 eth1.109&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We are using two BIND processes on the same machine for BIND9 currently just runs faster when it is not threading. Here is something Jinmei Tatuya told me on the bind9-workers Mailinglist which turned out to be very true:&lt;br /&gt;
 If you go with disabling threads, you may also want to enable&lt;br /&gt;
 &amp;quot;internal memory allocation&amp;quot;.  (I hear that) it should use memory more&lt;br /&gt;
 efficiently (and can make the server faster) but is disabled by&lt;br /&gt;
 default due to response-performance reasons in the threaded case.  You&lt;br /&gt;
 can enable this feature by adding the following line&lt;br /&gt;
&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 1&lt;br /&gt;
&lt;br /&gt;
 just before the following part of bind9/lib/isc/mem.c:&lt;br /&gt;
&lt;br /&gt;
 #ifndef ISC_MEM_USE_INTERNAL_MALLOC&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 0&lt;br /&gt;
 #endif&lt;br /&gt;
Try it and you will keep it. ;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you have more than one Loadbalancer at different locations and you can convince your local Networker to let you speak BGP4+ to his routers you can use quagga with something like the following configuration to failover the service IP to the second LB if the first one goes down:&lt;br /&gt;
 !&lt;br /&gt;
 router bgp 5430&lt;br /&gt;
  no synchronization&lt;br /&gt;
  bgp router-id a.b.c.d&lt;br /&gt;
  redistribute connected route-map benice&lt;br /&gt;
  neighbor c.d.e.f remote-as 5430&lt;br /&gt;
  neighbor c.d.e.f description ffm4-j2&lt;br /&gt;
  neighbor c.d.e.f send-community both&lt;br /&gt;
  neighbor c.d.e.f soft-reconfiguration inbound&lt;br /&gt;
  neighbor c.d.e.f route-map nixda in&lt;br /&gt;
  neighbor c.d.e.f route-map benice out&lt;br /&gt;
  neighbor d.c.f.e remote-as 5430&lt;br /&gt;
  neighbor d.c.f.e description ffm4-j&lt;br /&gt;
  neighbor d.c.f.e send-community both&lt;br /&gt;
  neighbor d.c.f.e soft-reconfiguration inbound&lt;br /&gt;
  neighbor d.c.f.e route-map nixda in&lt;br /&gt;
  neighbor d.c.f.e route-map benice out&lt;br /&gt;
  no auto-summary&lt;br /&gt;
 !&lt;br /&gt;
 access-list line permit 127.0.0.1/32 exact-match&lt;br /&gt;
 access-list line deny any&lt;br /&gt;
 !&lt;br /&gt;
 ip prefix-list cns-dus2 description dus2 high-metric eq low-perference&lt;br /&gt;
 ip prefix-list cns-dus2 seq 5 permit 194.97.173.125/32&lt;br /&gt;
 ip prefix-list cns-dus2 seq 10 deny any&lt;br /&gt;
 ip prefix-list cns-ffm4 description ffm4 low-metric eq high-preference&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 5 permit 194.97.173.124/32&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 10 deny any&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 10&lt;br /&gt;
  match ip address prefix-list cns-ffm4&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 0&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 20&lt;br /&gt;
  match ip address prefix-list cns-dus2&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 1&lt;br /&gt;
 !&lt;br /&gt;
 route-map nixda deny 10&lt;br /&gt;
 !&lt;br /&gt;
This is the LB at FFM4. Note that the metric at the DUS2 LB is just the other way around.&lt;br /&gt;
Here we fancy talking to two core-routers from each LB for extra redundancy.&lt;br /&gt;
You can also have an internal anycast ServiceIP if you use the same metric at both LBs and make sure they are attached to the same level of router network-topology-wise. This way traffic gets shared between the two loadbalancers according to your network-topology most interesting of course for large dialin ISPs.&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
dig does not return a non-zero error code when receiving a SERVFAIL but there are situations when some BIND9 versions return SERVFAIL for any query for example when they are out of memory. For a recursive DNS cluster situation we would want to take such BIND processes out of service.&lt;br /&gt;
&lt;br /&gt;
==== Workaround ====&lt;br /&gt;
&lt;br /&gt;
use the following perl script as a wrapper for dig which is quite ugly for perl is an interpretated language and forking it is not much fun so this consumes much user cpu when executed every 6 seconds.&lt;br /&gt;
 #!/usr/bin/perl&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
 # cmdline arguments: &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&lt;br /&gt;
 # /usr/bin/dig -b 10.5.53.1 IN A 2.0.0.127.my.test @10.5.53.2 +time=1 +tries=5 +fail&lt;br /&gt;
 if(&lt;br /&gt;
        ((defined $ARGV[0])&amp;amp;&amp;amp;($ARGV[0]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[1])&amp;amp;&amp;amp;($ARGV[1]=~/^(IN|CHAOS)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[2])&amp;amp;&amp;amp;($ARGV[2]=~/^(A|ANY|MX|PTR|SRV|TXT|AAAA|NS|CNAME|SOA)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[3])&amp;amp;&amp;amp;($ARGV[3]=~/^[A-Za-z0-9\-\.]+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[4])&amp;amp;&amp;amp;($ARGV[4]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[5])&amp;amp;&amp;amp;($ARGV[5]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[6])&amp;amp;&amp;amp;($ARGV[6]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[7])&amp;amp;&amp;amp;($ARGV[7]=~/^\S+$/))&lt;br /&gt;
        ) {&lt;br /&gt;
        my $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        if((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^tcp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;tcp&amp;quot;;&lt;br /&gt;
        } elsif ((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^udp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        my (@res)=`/usr/bin/dig -b $ARGV[0] $ARGV[1] $ARGV[2] $ARGV[3] \@$ARGV[4] +time=$ARGV[5] +tries=$ARGV[6] +fail +$transport 2&amp;gt;&amp;amp;1`;&lt;br /&gt;
        my $return=$?;&lt;br /&gt;
        if(my $error=(map {/status:\s*($ARGV[7])/ ? $1 : ()} @res)[0]) {&lt;br /&gt;
                die(&amp;quot;$error&amp;quot;);&lt;br /&gt;
        } elsif ($return!=0) {&lt;br /&gt;
                die(&amp;quot;dig returned: \&amp;quot;$return\&amp;quot;&amp;quot;);&lt;br /&gt;
        } elsif ($return==0) {&lt;br /&gt;
                exit 0;&lt;br /&gt;
        } else {&lt;br /&gt;
                die(&amp;quot;error: \&amp;quot;$return\&amp;quot; HAS BAD VALUE!&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
 } else {&lt;br /&gt;
        die(&amp;quot;dig-wrapper.pl &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
Ah yes, forgot to say: The Dual PIII 800 is not idleing around anymore - its busy running this script 44 times every 6 seconds, which accounts for roughly 12% user cpu and 5% system used at a query rate of ~3600q/s.&lt;br /&gt;
&lt;br /&gt;
==== Solution ====&lt;br /&gt;
&lt;br /&gt;
use a patched version of dig?&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
It still just works.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{lvs-example-stub}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:LVS Examples|DNS]]&lt;/div&gt;</summary>
		<author><name>ZaphodB</name></author>	</entry>

	<entry>
		<id>http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=569</id>
		<title>Building Scalable DNS Cluster using LVS</title>
		<link rel="alternate" type="text/html" href="http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=569"/>
				<updated>2006-03-01T16:12:26Z</updated>
		
		<summary type="html">&lt;p&gt;ZaphodB: the SERVFAIL problem&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Architecture ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Configuration Example ==&lt;br /&gt;
&lt;br /&gt;
keepalived.conf:&lt;br /&gt;
 ! Balancer-Set for udp/53&lt;br /&gt;
 virtual_server 194.97.173.124 53 {&lt;br /&gt;
    delay_loop 10&lt;br /&gt;
    lb_algo wrr&lt;br /&gt;
    lb_kind DR&lt;br /&gt;
    protocol UDP&lt;br /&gt;
    ! persistence_timeout 1&lt;br /&gt;
    ! persistence_granularity 255.255.255.255&lt;br /&gt;
    ! eth1.105 -&amp;gt; kai eth1.105&lt;br /&gt;
    real_server 10.1.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.1.53.1 a resolve.test.roka.net @10.1.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    ! eth1.109 -&amp;gt; kai eth1.109&lt;br /&gt;
    real_server 10.3.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.3.53.1 a resolve.test.roka.net @10.3.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As you can dig (;-) we are using an A record with a low TTL to test the service for this setup is a recursive DNS cluster. So far dig works fine with 44 real_servers configured on an idle Dual PIII 800.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
on real_server kai we use the following netfilter setup to be able to direct the traffic to different BIND processes on the same machine/mac:&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.1.53.2 eth1.105&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.3.53.2 eth1.109&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
 iptables -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We are using two BIND processes on the same machine for BIND9 currently just runs faster when it is not threading. Here is something Jinmei Tatuya told me on the bind9-workers Mailinglist which turned out to be very true:&lt;br /&gt;
 If you go with disabling threads, you may also want to enable&lt;br /&gt;
 &amp;quot;internal memory allocation&amp;quot;.  (I hear that) it should use memory more&lt;br /&gt;
 efficiently (and can make the server faster) but is disabled by&lt;br /&gt;
 default due to response-performance reasons in the threaded case.  You&lt;br /&gt;
 can enable this feature by adding the following line&lt;br /&gt;
&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 1&lt;br /&gt;
&lt;br /&gt;
 just before the following part of bind9/lib/isc/mem.c:&lt;br /&gt;
&lt;br /&gt;
 #ifndef ISC_MEM_USE_INTERNAL_MALLOC&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 0&lt;br /&gt;
 #endif&lt;br /&gt;
Try it and you will keep it. ;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you have more than one Loadbalancer at different locations and you can convince your local Networker to let you speak BGP4+ to his routers you can use quagga with something like the following configuration to failover the service IP to the second LB if the first one goes down:&lt;br /&gt;
 !&lt;br /&gt;
 router bgp 5430&lt;br /&gt;
  no synchronization&lt;br /&gt;
  bgp router-id a.b.c.d&lt;br /&gt;
  redistribute connected route-map benice&lt;br /&gt;
  neighbor c.d.e.f remote-as 5430&lt;br /&gt;
  neighbor c.d.e.f description ffm4-j2&lt;br /&gt;
  neighbor c.d.e.f send-community both&lt;br /&gt;
  neighbor c.d.e.f soft-reconfiguration inbound&lt;br /&gt;
  neighbor c.d.e.f route-map nixda in&lt;br /&gt;
  neighbor c.d.e.f route-map benice out&lt;br /&gt;
  neighbor d.c.f.e remote-as 5430&lt;br /&gt;
  neighbor d.c.f.e description ffm4-j&lt;br /&gt;
  neighbor d.c.f.e send-community both&lt;br /&gt;
  neighbor d.c.f.e soft-reconfiguration inbound&lt;br /&gt;
  neighbor d.c.f.e route-map nixda in&lt;br /&gt;
  neighbor d.c.f.e route-map benice out&lt;br /&gt;
  no auto-summary&lt;br /&gt;
 !&lt;br /&gt;
 access-list line permit 127.0.0.1/32 exact-match&lt;br /&gt;
 access-list line deny any&lt;br /&gt;
 !&lt;br /&gt;
 ip prefix-list cns-dus2 description dus2 high-metric eq low-perference&lt;br /&gt;
 ip prefix-list cns-dus2 seq 5 permit 194.97.173.125/32&lt;br /&gt;
 ip prefix-list cns-dus2 seq 10 deny any&lt;br /&gt;
 ip prefix-list cns-ffm4 description ffm4 low-metric eq high-preference&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 5 permit 194.97.173.124/32&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 10 deny any&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 10&lt;br /&gt;
  match ip address prefix-list cns-ffm4&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 0&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 20&lt;br /&gt;
  match ip address prefix-list cns-dus2&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 1&lt;br /&gt;
 !&lt;br /&gt;
 route-map nixda deny 10&lt;br /&gt;
 !&lt;br /&gt;
This is the LB at FFM4. Note that the metric at the DUS2 LB is just the other way around.&lt;br /&gt;
Here we fancy talking to two core-routers from each LB for extra redundancy.&lt;br /&gt;
You can also have an internal anycast ServiceIP if you use the same metric at both LBs and make sure they are attached to the same level of router network-topology-wise. This way traffic gets shared between the two loadbalancers according to your network-topology most interesting of course for large dialin ISPs.&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
dig does not return a non-zero error code when receiving a SERVFAIL but there are situations when some BIND9 versions return SERVFAIL for any query for example when they are out of memory. For a recursive DNS cluster situation we would want to take such BIND processes out of service.&lt;br /&gt;
&lt;br /&gt;
==== Workaround ====&lt;br /&gt;
&lt;br /&gt;
use the following perl script as a wrapper for dig which is quite ugly for perl is an interpretated language and forking it is not much fun so this consumes much user cpu when executed every 6 seconds.&lt;br /&gt;
 #!/usr/bin/perl&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
 # cmdline arguments: &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&lt;br /&gt;
 # /usr/bin/dig -b 10.5.53.1 IN A 2.0.0.127.my.test @10.5.53.2 +time=1 +tries=5 +fail&lt;br /&gt;
 if(&lt;br /&gt;
        ((defined $ARGV[0])&amp;amp;&amp;amp;($ARGV[0]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[1])&amp;amp;&amp;amp;($ARGV[1]=~/^(IN|CHAOS)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[2])&amp;amp;&amp;amp;($ARGV[2]=~/^(A|ANY|MX|PTR|SRV|TXT|AAAA|NS|CNAME|SOA)$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[3])&amp;amp;&amp;amp;($ARGV[3]=~/^[A-Za-z0-9\-\.]+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[4])&amp;amp;&amp;amp;($ARGV[4]=~/^\d+\.\d+\.\d+\.\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[5])&amp;amp;&amp;amp;($ARGV[5]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[6])&amp;amp;&amp;amp;($ARGV[6]=~/^\d+$/))&lt;br /&gt;
        &amp;amp;&amp;amp;((defined $ARGV[7])&amp;amp;&amp;amp;($ARGV[7]=~/^\S+$/))&lt;br /&gt;
        ) {&lt;br /&gt;
        my $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        if((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^tcp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;tcp&amp;quot;;&lt;br /&gt;
        } elsif ((defined $ARGV[8])&amp;amp;&amp;amp;($ARGV[8]=~/^udp$/i)) {&lt;br /&gt;
                $transport=&amp;quot;notcp&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        my (@res)=`/usr/bin/dig -b $ARGV[0] $ARGV[1] $ARGV[2] $ARGV[3] \@$ARGV[4] +time=$ARGV[5] +tries=$ARGV[6] +fail +$transport 2&amp;gt;&amp;amp;1`;&lt;br /&gt;
        my $return=$?;&lt;br /&gt;
        if(my $error=(map {/status:\s*($ARGV[7])/ ? $1 : ()} @res)[0]) {&lt;br /&gt;
                die(&amp;quot;$error&amp;quot;);&lt;br /&gt;
        } elsif ($return!=0) {&lt;br /&gt;
                die(&amp;quot;dig returned: \&amp;quot;$return\&amp;quot;&amp;quot;);&lt;br /&gt;
        } elsif ($return==0) {&lt;br /&gt;
                exit 0;&lt;br /&gt;
        } else {&lt;br /&gt;
                die(&amp;quot;error: \&amp;quot;$return\&amp;quot; HAS BAD VALUE!&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
 } else {&lt;br /&gt;
        die(&amp;quot;dig-wrapper.pl &amp;lt;FromIP&amp;gt; &amp;lt;Class&amp;gt; &amp;lt;QTYPE&amp;gt; &amp;lt;QNAME&amp;gt; &amp;lt;ToIP&amp;gt; &amp;lt;Times&amp;gt; &amp;lt;Tries&amp;gt; &amp;lt;ErrrorMatch&amp;gt; &amp;lt;Transport&amp;gt;&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== Solution ====&lt;br /&gt;
&lt;br /&gt;
use a patched version of dig?&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
It still just works.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{lvs-example-stub}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:LVS Examples|DNS]]&lt;/div&gt;</summary>
		<author><name>ZaphodB</name></author>	</entry>

	<entry>
		<id>http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=517</id>
		<title>Building Scalable DNS Cluster using LVS</title>
		<link rel="alternate" type="text/html" href="http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=517"/>
				<updated>2006-01-21T12:31:58Z</updated>
		
		<summary type="html">&lt;p&gt;ZaphodB: /* Configuration Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Architecture ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Configuration Example ==&lt;br /&gt;
&lt;br /&gt;
keepalived.conf:&lt;br /&gt;
 ! Balancer-Set for udp/53&lt;br /&gt;
 virtual_server 194.97.173.124 53 {&lt;br /&gt;
    delay_loop 10&lt;br /&gt;
    lb_algo wrr&lt;br /&gt;
    lb_kind DR&lt;br /&gt;
    protocol UDP&lt;br /&gt;
    ! persistence_timeout 1&lt;br /&gt;
    ! persistence_granularity 255.255.255.255&lt;br /&gt;
    ! eth1.105 -&amp;gt; kai eth1.105&lt;br /&gt;
    real_server 10.1.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.1.53.1 a resolve.test.roka.net @10.1.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    ! eth1.109 -&amp;gt; kai eth1.109&lt;br /&gt;
    real_server 10.3.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.3.53.1 a resolve.test.roka.net @10.3.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As you can dig (;-) we are using an A record with a low TTL to test the service for this setup is a recursive DNS cluster. So far dig works fine with 44 real_servers configured on an idle Dual PIII 800.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
on real_server kai we use the following netfilter setup to be able to direct the traffic to different BIND processes on the same machine/mac:&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.1.53.2 eth1.105&lt;br /&gt;
 $ipt -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 $ipt -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.3.53.2 eth1.109&lt;br /&gt;
 $ipt -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
 $ipt -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We are using two BIND processes on the same machine for BIND9 currently just runs faster when it is not threading. Here is something Jinmei Tatuya told me on the bind9-workers Mailinglist which turned out to be very true:&lt;br /&gt;
 If you go with disabling threads, you may also want to enable&lt;br /&gt;
 &amp;quot;internal memory allocation&amp;quot;.  (I hear that) it should use memory more&lt;br /&gt;
 efficiently (and can make the server faster) but is disabled by&lt;br /&gt;
 default due to response-performance reasons in the threaded case.  You&lt;br /&gt;
 can enable this feature by adding the following line&lt;br /&gt;
&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 1&lt;br /&gt;
&lt;br /&gt;
 just before the following part of bind9/lib/isc/mem.c:&lt;br /&gt;
&lt;br /&gt;
 #ifndef ISC_MEM_USE_INTERNAL_MALLOC&lt;br /&gt;
 #define ISC_MEM_USE_INTERNAL_MALLOC 0&lt;br /&gt;
 #endif&lt;br /&gt;
Try it and you will keep it. ;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you have more than one Loadbalancer at different locations and you can convince your local Networker to let you speak BGP4+ to his routers you can use quagga with something like the following configuration to failover the service IP to the second LB if the first one goes down:&lt;br /&gt;
 !&lt;br /&gt;
 router bgp 5430&lt;br /&gt;
  no synchronization&lt;br /&gt;
  bgp router-id a.b.c.d&lt;br /&gt;
  redistribute connected route-map benice&lt;br /&gt;
  neighbor c.d.e.f remote-as 5430&lt;br /&gt;
  neighbor c.d.e.f description ffm4-j2&lt;br /&gt;
  neighbor c.d.e.f send-community both&lt;br /&gt;
  neighbor c.d.e.f soft-reconfiguration inbound&lt;br /&gt;
  neighbor c.d.e.f route-map nixda in&lt;br /&gt;
  neighbor c.d.e.f route-map benice out&lt;br /&gt;
  neighbor d.c.f.e remote-as 5430&lt;br /&gt;
  neighbor d.c.f.e description ffm4-j&lt;br /&gt;
  neighbor d.c.f.e send-community both&lt;br /&gt;
  neighbor d.c.f.e soft-reconfiguration inbound&lt;br /&gt;
  neighbor d.c.f.e route-map nixda in&lt;br /&gt;
  neighbor d.c.f.e route-map benice out&lt;br /&gt;
  no auto-summary&lt;br /&gt;
 !&lt;br /&gt;
 access-list line permit 127.0.0.1/32 exact-match&lt;br /&gt;
 access-list line deny any&lt;br /&gt;
 !&lt;br /&gt;
 ip prefix-list cns-dus2 description dus2 high-metric eq low-perference&lt;br /&gt;
 ip prefix-list cns-dus2 seq 5 permit 194.97.173.125/32&lt;br /&gt;
 ip prefix-list cns-dus2 seq 10 deny any&lt;br /&gt;
 ip prefix-list cns-ffm4 description ffm4 low-metric eq high-preference&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 5 permit 194.97.173.124/32&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 10 deny any&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 10&lt;br /&gt;
  match ip address prefix-list cns-ffm4&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 0&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 20&lt;br /&gt;
  match ip address prefix-list cns-dus2&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 1&lt;br /&gt;
 !&lt;br /&gt;
 route-map nixda deny 10&lt;br /&gt;
 !&lt;br /&gt;
This is the LB at FFM4. Note that the metric at the DUS2 LB is just the other way around.&lt;br /&gt;
Here we fancy talking to two core-routers from each LB for extra redundancy.&lt;br /&gt;
You can also have an internal anycast ServiceIP if you use the same metric at both LBs and make sure they are attached to the same level of router network-topology-wise. This way traffic gets shared between the two loadbalancers according to your network-topology most interesting of course for large dialin ISPs.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
It just works.&lt;br /&gt;
&lt;br /&gt;
[[Category:LVS Examples|DNS]]&lt;/div&gt;</summary>
		<author><name>ZaphodB</name></author>	</entry>

	<entry>
		<id>http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=507</id>
		<title>Building Scalable DNS Cluster using LVS</title>
		<link rel="alternate" type="text/html" href="http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=507"/>
				<updated>2006-01-20T09:36:48Z</updated>
		
		<summary type="html">&lt;p&gt;ZaphodB: /* Conclusion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Architecture ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Configuration Example ==&lt;br /&gt;
&lt;br /&gt;
keepalived.conf:&lt;br /&gt;
 ! Balancer-Set for udp/53&lt;br /&gt;
 virtual_server 194.97.173.124 53 {&lt;br /&gt;
    delay_loop 10&lt;br /&gt;
    lb_algo wrr&lt;br /&gt;
    lb_kind DR&lt;br /&gt;
    protocol UDP&lt;br /&gt;
    ! persistence_timeout 1&lt;br /&gt;
    ! persistence_granularity 255.255.255.255&lt;br /&gt;
    ! eth1.105 -&amp;gt; kai eth1.105&lt;br /&gt;
    real_server 10.1.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.1.53.1 a resolve.test.roka.net @10.1.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    ! eth1.109 -&amp;gt; kai eth1.109&lt;br /&gt;
    real_server 10.3.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.3.53.1 a resolve.test.roka.net @10.3.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As you can dig (;-) we are using an A record with a low TTL to test the service for this setup is a recursive DNS cluster. So far dig works fine with 44 real_servers configured on an idle Dual PIII 800.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
on real_server kai we use the following netfilter setup to be able to direct the traffic to different BIND processes on the same machine/mac:&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.1.53.2 eth1.105&lt;br /&gt;
 $ipt -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 $ipt -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.3.53.2 eth1.109&lt;br /&gt;
 $ipt -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
 $ipt -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you have more than one Loadbalancer at different locations and you can convince your local Networker to let you speak BGP4+ to his routers you can use quagga with something like the following configuration to failover the service IP to the second LB if the first one goes down:&lt;br /&gt;
 !&lt;br /&gt;
 router bgp 5430&lt;br /&gt;
  no synchronization&lt;br /&gt;
  bgp router-id a.b.c.d&lt;br /&gt;
  redistribute connected route-map benice&lt;br /&gt;
  neighbor c.d.e.f remote-as 5430&lt;br /&gt;
  neighbor c.d.e.f description ffm4-j2&lt;br /&gt;
  neighbor c.d.e.f send-community both&lt;br /&gt;
  neighbor c.d.e.f soft-reconfiguration inbound&lt;br /&gt;
  neighbor c.d.e.f route-map nixda in&lt;br /&gt;
  neighbor c.d.e.f route-map benice out&lt;br /&gt;
  neighbor d.c.f.e remote-as 5430&lt;br /&gt;
  neighbor d.c.f.e description ffm4-j&lt;br /&gt;
  neighbor d.c.f.e send-community both&lt;br /&gt;
  neighbor d.c.f.e soft-reconfiguration inbound&lt;br /&gt;
  neighbor d.c.f.e route-map nixda in&lt;br /&gt;
  neighbor d.c.f.e route-map benice out&lt;br /&gt;
  no auto-summary&lt;br /&gt;
 !&lt;br /&gt;
 access-list line permit 127.0.0.1/32 exact-match&lt;br /&gt;
 access-list line deny any&lt;br /&gt;
 !&lt;br /&gt;
 ip prefix-list cns-dus2 description dus2 high-metric eq low-perference&lt;br /&gt;
 ip prefix-list cns-dus2 seq 5 permit 194.97.173.125/32&lt;br /&gt;
 ip prefix-list cns-dus2 seq 10 deny any&lt;br /&gt;
 ip prefix-list cns-ffm4 description ffm4 low-metric eq high-preference&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 5 permit 194.97.173.124/32&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 10 deny any&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 10&lt;br /&gt;
  match ip address prefix-list cns-ffm4&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 0&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 20&lt;br /&gt;
  match ip address prefix-list cns-dus2&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 1&lt;br /&gt;
 !&lt;br /&gt;
 route-map nixda deny 10&lt;br /&gt;
 !&lt;br /&gt;
This is the LB at FFM4. Note that the metric at the DUS2 LB is just the other way around.&lt;br /&gt;
Here we fancy talking to two core-routers from each LB for extra redundancy.&lt;br /&gt;
You can also have an internal anycast ServiceIP if you use the same metric at both LBs and make sure they are attached to the same level of router network-topology-wise. This way traffic gets shared between the two loadbalancers according to your network-topology most interesting of course for large dialin ISPs.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
It just works.&lt;br /&gt;
&lt;br /&gt;
[[Category:LVS Examples|DNS]]&lt;/div&gt;</summary>
		<author><name>ZaphodB</name></author>	</entry>

	<entry>
		<id>http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=504</id>
		<title>Building Scalable DNS Cluster using LVS</title>
		<link rel="alternate" type="text/html" href="http://kb.linux-vs.org/wiki?title=Building_Scalable_DNS_Cluster_using_LVS&amp;diff=504"/>
				<updated>2006-01-20T09:34:46Z</updated>
		
		<summary type="html">&lt;p&gt;ZaphodB: /* Configuration Example */ now here is actually something written ;)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Architecture ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Configuration Example ==&lt;br /&gt;
&lt;br /&gt;
keepalived.conf:&lt;br /&gt;
 ! Balancer-Set for udp/53&lt;br /&gt;
 virtual_server 194.97.173.124 53 {&lt;br /&gt;
    delay_loop 10&lt;br /&gt;
    lb_algo wrr&lt;br /&gt;
    lb_kind DR&lt;br /&gt;
    protocol UDP&lt;br /&gt;
    ! persistence_timeout 1&lt;br /&gt;
    ! persistence_granularity 255.255.255.255&lt;br /&gt;
    ! eth1.105 -&amp;gt; kai eth1.105&lt;br /&gt;
    real_server 10.1.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.1.53.1 a resolve.test.roka.net @10.1.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    ! eth1.109 -&amp;gt; kai eth1.109&lt;br /&gt;
    real_server 10.3.53.2 53 {&lt;br /&gt;
        weight 1&lt;br /&gt;
        MISC_CHECK {&lt;br /&gt;
            misc_path &amp;quot;/usr/bin/dig -b 10.3.53.1 a resolve.test.roka.net @10.3.53.2 +time=1 +tries=5 +fail &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
            misc_timeout 6&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As you can dig (;-) we are using an A record with a low TTL to test the service for this setup is a recursive DNS cluster. So far dig works fine with 44 real_servers configured on an idle Dual PIII 800.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
on real_server kai we use the following netfilter setup to be able to direct the traffic to different BIND processes on the same machine/mac:&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.1.53.2 eth1.105&lt;br /&gt;
 $ipt -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 $ipt -t nat -A PREROUTING -i eth1.105 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.1.53.2:53&lt;br /&gt;
 #DNAT 194.97.173.124-&amp;gt;10.3.53.2 eth1.109&lt;br /&gt;
 $ipt -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p tcp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
 $ipt -t nat -A PREROUTING -i eth1.109 -s $net -d 194.97.173.124 -p udp --dport 53 -j DNAT --to-destination 10.3.53.2:53&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you have more than one Loadbalancer at different locations and you can convince your local Networker to let you speak BGP4+ to his routers you can use quagga with something like the following configuration to failover the service IP to the second LB if the first one goes down:&lt;br /&gt;
 !&lt;br /&gt;
 router bgp 5430&lt;br /&gt;
  no synchronization&lt;br /&gt;
  bgp router-id a.b.c.d&lt;br /&gt;
  redistribute connected route-map benice&lt;br /&gt;
  neighbor c.d.e.f remote-as 5430&lt;br /&gt;
  neighbor c.d.e.f description ffm4-j2&lt;br /&gt;
  neighbor c.d.e.f send-community both&lt;br /&gt;
  neighbor c.d.e.f soft-reconfiguration inbound&lt;br /&gt;
  neighbor c.d.e.f route-map nixda in&lt;br /&gt;
  neighbor c.d.e.f route-map benice out&lt;br /&gt;
  neighbor d.c.f.e remote-as 5430&lt;br /&gt;
  neighbor d.c.f.e description ffm4-j&lt;br /&gt;
  neighbor d.c.f.e send-community both&lt;br /&gt;
  neighbor d.c.f.e soft-reconfiguration inbound&lt;br /&gt;
  neighbor d.c.f.e route-map nixda in&lt;br /&gt;
  neighbor d.c.f.e route-map benice out&lt;br /&gt;
  no auto-summary&lt;br /&gt;
 !&lt;br /&gt;
 access-list line permit 127.0.0.1/32 exact-match&lt;br /&gt;
 access-list line deny any&lt;br /&gt;
 !&lt;br /&gt;
 ip prefix-list cns-dus2 description dus2 high-metric eq low-perference&lt;br /&gt;
 ip prefix-list cns-dus2 seq 5 permit 194.97.173.125/32&lt;br /&gt;
 ip prefix-list cns-dus2 seq 10 deny any&lt;br /&gt;
 ip prefix-list cns-ffm4 description ffm4 low-metric eq high-preference&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 5 permit 194.97.173.124/32&lt;br /&gt;
 ip prefix-list cns-ffm4 seq 10 deny any&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 10&lt;br /&gt;
  match ip address prefix-list cns-ffm4&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 0&lt;br /&gt;
 !&lt;br /&gt;
 route-map benice permit 20&lt;br /&gt;
  match ip address prefix-list cns-dus2&lt;br /&gt;
  set local-preference 100&lt;br /&gt;
  set metric 1&lt;br /&gt;
 !&lt;br /&gt;
 route-map nixda deny 10&lt;br /&gt;
 !&lt;br /&gt;
This is the LB at FFM4. Note that the metric at the DUS2 LB is just the other way around.&lt;br /&gt;
Here we fancy talking to two core-routers from each LB for extra redundancy.&lt;br /&gt;
You can also have an internal anycast ServiceIP if you use the same metric at both LBs and make sure they are attached to the same level of router network-topology-wise. This way traffic gets shared between the two loadbalancers according to your network-topology most interesting of course for large dialin ISPs.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:LVS Examples|DNS]]&lt;/div&gt;</summary>
		<author><name>ZaphodB</name></author>	</entry>

	</feed>