DNS-BALANCER
Давно искал решение балансировки нагрузки на DNS сервера.
Проблема заключается в том, что всего 2 IP выдается клиентам (менять их нет ни желания, ни сил (500 тысяч). На данный момент рекурсивные сервера отвечают на 2500 запросов ежесекундно, авторитотивные - чуть меньше. Изучения гор софта ни к чему хорошему не привели, то писан на ruby, то глючен как виндуза.
Пришло на ум простое решение, FreeBSD + pf + carp :)
Что нужно
1. На балансерах ядро с поддержкой pf и carp.
2. На DNS серверах просто с поддержкой ipfw хватит
Простая конфигурация, дальше сами допилите:
2 балансера LB1, LB2. 2 IP рекурсивных DNS (111.111.111.1, 111.111.222.1). 10,15,20 внутренних DNS серверов (192.168.1.20,192.168.1.21...) (192.168.2.20, 192.168.2.21...) Если балансите 2 внешних DNS - нужно 2 приватные сетки, 3 DNS - 3 сетки и пр.
LB1
/etc/rc.conf
cloned_interfaces="carp0 carp1 carp2 carp3" ifconfig_em0="inet 111.111.111.10 netmask 255.255.255.0" ifconfig_em0_alias0="inet 111.111.222.10 netmask 255.255.255.0" ifconfig_em0_alias1="inet 192.168.1.10 netmask 255.255.255.0" ifconfig_em0_alias1="inet 192.168.2.10 netmask 255.255.255.0" ifconfig_carp0="vhid 1 advskew 100 pass MEGAPASS 111.111.111.1/24" # NS1 ifconfig_carp1="vhid 1 advskew 100 pass MEGAPASS 192.168.1.1/24" # NS1 ifconfig_carp1="vhid 1 advskew 200 pass MEGAPASS 111.111.222.1/24" # NS2 ifconfig_carp1="vhid 1 advskew 200 pass MEGAPASS 192.168.2.1/24" # NS2
sysctl net.inet.carp.preempt=1
LB2
/etc/rc.conf
cloned_interfaces="carp0 carp1 carp2 carp3" ifconfig_em0="inet 111.111.111.11 netmask 255.255.255.0" ifconfig_em0_alias0="inet 111.111.222.11 netmask 255.255.255.0" ifconfig_em0_alias1="inet 192.168.1.11 netmask 255.255.255.0" ifconfig_em0_alias1="inet 192.168.2.11 netmask 255.255.255.0" ifconfig_carp0="vhid 1 advskew 200 pass MEGAPASS 111.111.111.1/24" # NS1 ifconfig_carp1="vhid 1 advskew 200 pass MEGAPASS 192.168.1.1/24" # NS1 ifconfig_carp1="vhid 1 advskew 100 pass MEGAPASS 111.111.222.1/24" # NS2 ifconfig_carp1="vhid 1 advskew 100 pass MEGAPASS 192.168.2.1/24" # NS2
sysctl net.inet.carp.preempt=1
Настройка фаера на узлах идентична
/etc/pf.conf (только важная часть)
ns1="111.111.111.1" ns2="111.111.222.1" set limit { frags 35000, states 500000 } table <dns_ns1> { 192.168.1.20, 192.168.1.21, 192.168.1.22 } table <dns_ns2> { 192.168.2.20, 192.168.2.21, 192.168.2.22 }
Разные IP нужны чтобы отвечать с нужного source!!!!
nat proto { tcp, udp } from <dns_ns1> port 53 -> $ns1 nat proto { tcp, udp } from <dns_ns2> port 53 -> $ns2 rdr proto { udp, tcp } from <ournets> to $ns1 port 53 -> <dns_ns1> round-robin rdr proto { udp, tcp } from <ournets> to $ns2 port 53 -> <dns_ns2> round-robin
Настройка на DNS бэкенде (192.168.1.20 он же 192.168.2.20 для примера)
fwd 192.168.1.1 udp from 192.168.1.20 53 to any fwd 192.168.1.1 tcp from 192.168.1.20 53 to any fwd 192.168.2.1 udp from 192.168.2.20 53 to any fwd 192.168.2.1 tcp from 192.168.2.20 53 to any
Итого получаем:
1. При выходе одного из балансеров из строя - ничего не теряем;
2. Равномерно размазали нагрузку на все backend DNS сервера.
На данный момент такая система обслуживает в пиках 10 тысяч запросов в секунду. Да, желательно врубить polling. Осталось наваять скрипт для динамического выноса из таблиц умерших backend'ов.
(c) 2008 Dmitry Rybin kirgudu@kirgudu.org