(Part 3 - Load Balancing With DNSdist)
Created: 2021-04-21 Wed 16:25
Welcome to part three of our BIND 9 webinar series
leastOutstanding
: use the server with the least outstanding
queries (possibly least load)chashed
: distribute based on hashes of the query name (sticky
queries)whashed
: distribute based on hashes of the query name (sticky
queries), but apply the configured weight for the back-end serverwrandom
: distribute random, but with a weight applied. Back-end
server receive the share of queries based on their configured
weightroundrobin
: distribute queries to all back-end server based on an
round-robin algorithm (send each query to the next server)counter=0
function luaroundrobin(servers, dq)
counter=counter+1
return servers[1+(counter % #servers)]
end
setServerPolicyLua("luaroundrobin", luaroundrobin)
> getPool(""):getCache():printStats() Entries: 122/10000 Hits: 9147 Misses: 10147 Deferred inserts: 1 Deferred lookups: 0 Lookup Collisions: 0 Insert Collisions: 0 TTL Too Shorts: 0
dnsdist.conf
(usually in /etc/dnsdist
)
dnsdist.conf
---- Listen addresses addLocal('192.0.2.1:53', { reusePort=true }) addLocal('127.0.0.1:53', { reusePort=true }) addLocal('[::1]:53', { reusePort=true }) addLocal('[2001:db8::1]:53', { reusePort=true }) ---- Back-end server newServer({address="192.0.2.100", qps=10000, order=1}) newServer({address="2001:db8:100::5353", qps=100, order=3}) newServer({address="2001:db8:200::6312", qps=100, order=2}) ---- Policy setServerPolicy(whashed) setACL({'192.0.2.0/24', '2001:db8::/64'}) ---- Cache pc = newPacketCache(10000, {maxTTL=86400, minTTL=0, temporaryFailureTTL=60, staleTTL=60, dontAge=false}) getPool(""):setCache(pc) ---- Web-server webserver("192.0.2.1:8083") setWebserverConfig({acl="192.0.2.10/32",password="dnsdist-is-great"}) --- Console controlSocket('127.0.0.1:5199') setKey("2ux3QDmpdDAzYjspexaspAdqnXF8jXFU5qhd/BqXV8ag=") ---- Filter Rules addAction(RegexRule(".*\\.facebook\\..*$"), RCodeAction(DNSRCode.REFUSED)) addAction(RegexRule(".*\\.doubleclick\\..*$"), RCodeAction(DNSRCode.REFUSED))
$ /bin/dnsdist -c > showServers() 198.51.100.12# Name Address State Qps Qlim Ord Wt Queries Drops Drate Lat Outstanding Pools 0 192.0.2.53:53 192.0.2.53:53 up 1.0 10000 1 1 10088 132 0.0 9.2 0 1 198.51.100.12:53 198.51.100.12:53 up 0.0 100 2 1 1391 2 0.0 44.5 0 2 203.0.113.11:53 203.0.113.11:53 up 0.0 100 3 1 318 0 0.0 65.3 0 All 0.0 11797 134 > newServer({address="1.1.1.1", qps=10000, order=1}) 1.1.1.1:53 > showServers() # Name Address State Qps Qlim Ord Wt Queries Drops Drate Lat Outstanding Pools 0 192.0.2.53:53 192.0.2.53:53 up 0.0 10000 1 1 10103 132 0.0 8.9 0 1 1.1.1.1:53 1.1.1.1:53 up 0.0 10000 1 1 3 0 0.0 0.3 0 2 198.51.100.12:53 198.51.100.12:53 up 0.0 100 2 1 1392 2 0.0 44.4 0 3 203.0.113.11:53 203.0.113.11:53 up 0.0 100 3 1 319 0 0.0 65.2 0 All 0.0 11817 134 >
---- Webserver webserver("192.0.2.1:8083") setWebserverConfig({acl="192.0.2.10/32",password="dnsdist-is-great"})
Example dnsdist configuration:
carbonServer('192.0.2.210', 'dnsdist.isp.example', 30, 'dnsdist', 'main')
/metrics
URL
endpoint of the Web-APIpc = newPacketCache(10000, --- create a new pool cache "pc" with 10.000 entries { maxTTL=86400, --- maximum TTL cache time minTTL=0, --- minimum TTL cache time temporaryFailureTTL=60, --- TTL used for server failures or "refused" staleTTL=60, --- TTL for stale cache entries dontAge=false --- cache entries "age", their TTL is decremented in cache }) getPool(""):setCache(pc) --- assign the cache to the default pool
a.root-servers.net
A-Record towards the downstream server
isc.org
:newServer({address="51.75.79.143", checkType="SOA", checkType=DNSClass.IN, checkName="isc.org"}) newServer({address="199.6.1.52", checkType="SOA", checkType=DNSClass.IN, checkName="isc.org"}) newServer({address="199.254.63.254", checkType="SOA", checkType=DNSClass.IN, checkName="isc.org"}) newServer({address="149.20.1.73", checkType="SOA", checkType=DNSClass.IN, checkName="isc.org"}) setServerPolicy(leastOutstanding) setLocal("192.0.2.123:53") [...]
primary
, which only contains one
primary authoritative servernewServer({ address="192.0.2.123", name="primary", pool={"primary", "otherpool"} }) addAction( OrRule({ QTypeRule(DNSQType.SOA), QTypeRule(DNSQType.AXFR), QTypeRule(DNSQType.IXFR)}), PoolAction("primary") )
source
parameter tells dnsdist which IP-address or
interface to use for outgoing queries:newServer({address="192.0.2.1", source="192.0.2.127"}) newServer({address="192.0.2.1", source="eth1"}) newServer({address="192.0.2.1", source="192.0.2.127@eth1"})
mname
fieldnsupdate
) to use a dedicated IP address:nsupdate > ttl 3600 > server 192.0.2.221 > add www.example.com. IN A 192.0.2.212 > send
notify
messages to
all secondaries configured in the NS records
notify
from trusted source addressesnotify
can be configured explicitly on the
authoritative servers. Example for BIND 9:
zone "example.com" { type primary; file "example.com"; notify explicit; also-notify { 192.0.2.53; 198.51.100.12; }; };
local dbr = dynBlockRulesGroup() dbr:setQueryRate(30, 10, "Exceeded query rate", 60) dbr:setRCodeRate(DNSRCode.NXDOMAIN, 20, 10, "Exceeded NXD rate", 60) dbr:setRCodeRate(DNSRCode.SERVFAIL, 20, 10, "Exceeded ServFail rate", 60) dbr:setQTypeRate(DNSQType.ANY, 5, 10, "Exceeded ANY rate", 60) dbr:setResponseByteRate(10000, 10, "Exceeded resp BW rate", 60) function maintenance() dbr:apply() end
firstAvailable
will
create a simple fail-over configuration
---- Back-end server newServer({address="192.0.2.100", qps=1000, order=1}) newServer({address="2001:db8:100::5353", qps=500, order=2}) newServer({address="2001:db8:200::6312", qps=500, order=3}) ---- Policy setServerPolicy(firstAvailable) setACL({'192.0.2.0/24', '2001:db8::/64'}) ---- Cache pc = newPacketCache(10000, {maxTTL=86400, minTTL=0, temporaryFailureTTL=60, staleTTL=60, dontAge=false}) getPool(""):setCache(pc) [...]
---- Back-end server newServer({address="192.0.2.100", order=1}) newServer({address="2001:db8:100::5353", order=3}) newServer({address="2001:db8:200::6312", order=2}) ---- Policy setServerPolicy(leastOutstanding) setACL({'192.0.2.0/24', '2001:db8::/64'}) ---- Cache pc = newPacketCache(10000, {maxTTL=86400, minTTL=0, temporaryFailureTTL=60, staleTTL=60, dontAge=false}) getPool(""):setCache(pc) [...]
-- Add a backend server with address 192.0.2.3 and assign it to the "abuse" pool newServer({address="192.0.2.3", pool="abuse"}) -- Send all queries for "bad-domain1.example." and "bad-domain2.example" to the "abuse" pool addAction({'bad-domain1.example', 'bad-domain2.example.'}, PoolAction("abuse"))