Jump to content
Калькуляторы

Балансировщик загрузки NAS средствами DNS

Хочу поделиться способом балансировки загрузки NAS серверов средствами DNS сервера. Идея не нова - для хоста vpn.somenet.ru делаем несколько A записей и DNS сервер примерно одинаково нагружает наши сервера. Однако часто, особенно у начинающих провайдеров, имеется "зоопарк" NAS серверов, разных по мощности. И желательно не превышать максимальную нагрузку на каждый сервер. И было бы неплохо автоматически удалять записи для серверов, которые не отвечают. Нижеприведенный скрипт делает все это, динамически обновляет зону для BIND, используя RNDC. На хосте где запускается скрипт должны присутствовать утилиты nsupdate, host, snmpget. На NAS серверах должна быть запущена служба SNMP.

 

#!/usr/bin/perl                 

$balance_host = "vpn.somenet.ru";

$snmp_get = "snmpget -v 2c -c public ";

@dns_get = `host $balance_host | cut -d " " -f 4`;

$nsupdate_cmd = qq~
server 127.0.0.1   
zone somenet.ru      
key rndc-key JhHyvY+7lUnJ1Ae1WSWcsQ==
~;                                   

%hosts = (
            # mikrotik              max sessions, snmp MIB
            "1.1.1.2"    =>      [ 70, "SNMPv2-SMI::enterprises.9.9.150.1.1.1.0" ],
            "1.1.1.3"    =>      [ 70, "SNMPv2-SMI::enterprises.9.9.150.1.1.1.0" ],
            # ucd-snmp            max sessions, snmp MIB
            "1.1.1.4"    =>      [ 500, "UCD-SNMP-MIB::prCount.1" ],               
        );                                                                                

# ---------------------------------------------------------------------------------------

chomp(@dns_get);
foreach (@dns_get){
    $actual_dns{$_} = $_;
}

print `date`;

foreach $host (sort keys %hosts){
    chomp($current = `$snmp_get $host $hosts{$host}[1] | cut -d " " -f 4`);
    if($current eq ""){ $current = -1; }

    if(($current >= $hosts{$host}[0] || $current == -1 ) && defined($actual_dns{$host})){
        # delete
        print "$host has $current connections with max $hosts{$host}[0] -> delete\n";
        $nsupdate_cmd .= "update delete $balance_host A $host\n";
        $need_update = 1;
    } elsif(($current < $hosts{$host}[0] && $current != -1) && !defined($actual_dns{$host})){
        # insert
        print "$host has $current connections with max $hosts{$host}[0] -> insert\n";
        $nsupdate_cmd .= "update add $balance_host 60 A $host\n";
        $need_update = 1;
    } else {
        # do nothing
        if(defined($actual_dns{$host})){ $mode = "enabled"; } else { $mode = "disabled"; }
        print "$host $mode and has $current connections with max $hosts{$host}[0]\n";
    }

    if(defined($actual_dns{$host})){ delete $actual_dns{$host}; }

}

foreach $host (sort keys %actual_dns){
    print "$host is old - delete\n";
    $nsupdate_cmd .= "update delete $balance_host A $host\n";
    $need_update = 1;
}

if($need_update){
    $nsupdate_cmd .= "send\n";
    print $nsupdate_cmd;
    open F, "| nsupdate";
    print F $nsupdate_cmd;
    close F;
}

 

Пример snmpd.conf для линуксового NAS:

 

rocommunity public
proc pppd

 

Далее на машине с BIND запускаем rndc-confgen и правим named.conf, пример:

 

...
key "rndc-key" {
       algorithm hmac-md5;
       secret "JhHyvY+7lUnJ1Ae1WSWcsQ==";
};

controls {
       inet 127.0.0.1 port 953
               allow { 127.0.0.1; } keys { "rndc-key"; };
};

zone "somenet.ru" in {
        type master;
        file "somenet.hosts";
        allow-update { key rndc-key; };
};
...

 

Не забываем добавить в cron вызов скрипта vpn_balancer.pl раз в минуту. Обратите внимание, что после данных манипуляций не рекомендуется вручную вносить изменения в файл somenet.hosts, для этого нужно использовать, например, такую команду:

 

cat << end-of-text | nsupdate
server 127.0.0.1
zone somenet.ru   
key rndc-key JhHyvY+7lUnJ1Ae1WSWcsQ==
update add somehost.somenet.ru 86400 A 1.1.1.1
update delete someanotherhost.somenet.ru
send
end-of-text

Edited by a0d75

Share this post


Link to post
Share on other sites

И было бы неплохо автоматически удалять записи для серверов, которые не отвечают.

Это совершенно ненужная операция.

Время жизни днс кеша на клиенте больше, чем время на подъем НАСа, который не отвечает.

Да и не будет клиент "ломится" на них, пока они лежат, если есть у него другие записи в кеше.

Share this post


Link to post
Share on other sites

Время жизни DNS кэша 60 секунд, если Вы внимательно посмотрели скрипт. Каждый неотвечающий NAS увеличивает время соединения клиента на 5-10 секунд, по крайней мере в нашей сети.

Share this post


Link to post
Share on other sites

Время жизни DNS кэша 60 секунд, если Вы внимательно посмотрели скрипт. Каждый неотвечающий NAS увеличивает время соединения клиента на 5-10 секунд, по крайней мере в нашей сети.

Где логика? Если значение (даже искуственно заниженное) ttl кеша в 6-10 раз больше, чем практический "затык" с неотвечающим НАСом, в вашей сети?

Share this post


Link to post
Share on other sites

Текущее время: 21:52:12,95
Введите новое время:

C:\>ping vpn.aaa.ru

Обмен пакетами с vpn.aaa.ru [192.168.20.47] по 32 байт:

Ответ от 192.168.20.47: число байт=32 время<1мс TTL=64
Ответ от 192.168.20.47: число байт=32 время<1мс TTL=64
Ответ от 192.168.20.47: число байт=32 время<1мс TTL=64
Ответ от 192.168.20.47: число байт=32 время<1мс TTL=64

Статистика Ping для 192.168.20.47:
    Пакетов: отправлено = 4, получено = 4, потеряно = 0 (0% потерь),
Приблизительное время приема-передачи в мс:
    Минимальное = 0мсек, Максимальное = 0 мсек, Среднее = 0 мсек

C:\>goto start

C:\>time
Текущее время: 21:52:17,15
Введите новое время:

C:\>ping vpn.aaa.ru

Обмен пакетами с vpn.aaa.ru [192.168.20.78] по 32 байт:

Ответ от 192.168.20.78: число байт=32 время<1мс TTL=64
Ответ от 192.168.20.78: число байт=32 время<1мс TTL=64
Ответ от 192.168.20.78: число байт=32 время<1мс TTL=64
Ответ от 192.168.20.78: число байт=32 время<1мс TTL=64

Статистика Ping для 192.168.20.78:
    Пакетов: отправлено = 4, получено = 4, потеряно = 0 (0% потерь),
Приблизительное время приема-передачи в мс:
    Минимальное = 0мсек, Максимальное = 0 мсек, Среднее = 0 мсек

C:\>goto start

C:\>time
Текущее время: 21:52:21,34
Введите новое время:

C:\>ping vpn.aaa.ru

Обмен пакетами с vpn.aaa.ru [192.168.20.78] по 32 байт:

Ответ от 192.168.20.78: число байт=32 время<1мс TTL=64
Ответ от 192.168.20.78: число байт=32 время<1мс TTL=64
Ответ от 192.168.20.78: число байт=32 время<1мс TTL=64
Ответ от 192.168.20.78: число байт=32 время<1мс TTL=64

Статистика Ping для 192.168.20.78:
    Пакетов: отправлено = 4, получено = 4, потеряно = 0 (0% потерь),
Приблизительное время приема-передачи в мс:
    Минимальное = 0мсек, Максимальное = 0 мсек, Среднее = 0 мсек

C:\>goto start

C:\>time
Текущее время: 21:52:24,70
Введите новое время:

C:\>ping vpn.aaa.ru

Обмен пакетами с vpn.aaa.ru [192.168.20.47] по 32 байт:

Ответ от 192.168.20.47: число байт=32 время<1мс TTL=64
Ответ от 192.168.20.47: число байт=32 время<1мс TTL=64
Ответ от 192.168.20.47: число байт=32 время<1мс TTL=64
Ответ от 192.168.20.47: число байт=32 время<1мс TTL=64

Статистика Ping для 192.168.20.47:
    Пакетов: отправлено = 4, получено = 4, потеряно = 0 (0% потерь),
Приблизительное время приема-передачи в мс:
    Минимальное = 0мсек, Максимальное = 0 мсек, Среднее = 0 мсек

Share this post


Link to post
Share on other sites

Реализация интересная, но для данной задачи бессмысленная. У нас прекрасно работали PPTP-сервера с выставленным TTL 0 vpn.ozerki.net. Как минимум винда, в рамках попытки установления TCP-соединения, посылает три пакета, каждый раз при этом разрешая имя в новый ip.

Edited by Dyr

Share this post


Link to post
Share on other sites

Проще пофиксить зоопарк, поставив то что будет держать 1300 соединений, по нагрузке + 1 запасной и под развитие

Share this post


Link to post
Share on other sites

Основная задача - защита NAS от перегруза. У нас зоопарк, одни могут нормально держать 500 соединений, другие - 300

Можно и это исправить, вставляя, скажем, две записи IN A x.x.x.1 и одну x.x.x.2 - тогда количество соединений по серверам поделится примерно как два к одному.

Share this post


Link to post
Share on other sites

Основная задача - защита NAS от перегруза. У нас зоопарк, одни могут нормально держать 500 соединений, другие - 300
Можно и это исправить, вставляя, скажем, две записи IN A x.x.x.1 и одну x.x.x.2 - тогда количество соединений по серверам поделится примерно как два к одному.

Вы уверены?

Share this post


Link to post
Share on other sites

Да, а что вас смущает? Именно так будут статистически распределяться в теории и именно это мы и наблюдали на практике.

Только надо не забывать выставлять в DNS тип выдачи случайный, а не цикличный (в терминах BIND "rrset-order {order random}")

Share this post


Link to post
Share on other sites

Да, а что вас смущает? Именно так будут статистически распределяться в теории и именно это мы и наблюдали на практике.
Очень странно ж)

Количество сессий на каждом NAS зависит не только от того сколько человек к нему ПОДКЛЮЧИЛИСЬ, но и от того сколько ОТКЛЮЧИЛИСЬ.

В эпоху анлима народ конечно редко отключаеться...

 

Share this post


Link to post
Share on other sites

Возможно, мы не настолько долго ставили асинхронное распределение, чтобы накопление разницы между увеличенным прибытием на NAS и примерно одинаковым убытием по всем NASaм оказывалось того порядка, чтобы нарушать нужное распределение.

Перечитал...нда...надеюсь, понятно обьяснил. :)

Share this post


Link to post
Share on other sites

Распределение будет равномерным. На каждый сервер упадет число коннектов примерно равное числу всех абонентов онлайн деленное на кол-во активных серверов.

 

Это подтверждается практикой. Рекомендуемый размер зоопарка чем больше - тем лучше, т.е. в случае выхода одного сервера нагрузка плавно распределится по другим машинам, а если их много, то не сильно вырастет на каждой отдельно взятой машине.

 

Лучше всего, если все машины в зоопарке будут примерно равны между собой по производительности, чтобы не создавать затык в нормальном режиме работы + не менее 30% должны иметь запас по производительности и те, которые работают под нагрузкой в часы пик.

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.