Главная > Теория и практика > Построение отказоустойчивого балансировщика нагрузки на базе Perlbal/Heartbeat

Построение отказоустойчивого балансировщика нагрузки на базе Perlbal/Heartbeat

 В этой статье описывается процесс настройки отказоустойчивого двухузлового балансировщика нагрузки с активной/пассивной конфигурацией, поддержкой сессий и механизма Failover на базе Perlbal/Heartbeat под управлением Debian. Балансировщик работает между конечным пользователем и двумя backend-серверами, которые отдают некий контент. (В нашем примере это два сервера с установленным Apache). Балансировщик не только проксирует запросы к бэкэнду, он еще и проверяет состояние бэкэнда и, в случае отказа, перенаправляет запросы к другому серверу (failover). Вдобавок, ведется постоянный мониторинг бэкэнд-серверов при помощи Heartbeat и, если master-сервер “лежит”, то slave автоматически становится мастером. Ваши пользователи не заметят сбоев в работе сервиса. 

Наша конфигурация
Мы используем следующую конфигурацию:

  • Узел балансировки 1: lb1.example.com, IP адрес: 192.168.0.100
  • Узел балансировки 2: lb2.example.com, IP адрес: 192.168.0.101
  • Web-сервер 1: http1.example.com, IP адрес: 192.168.0.102
  • Web-сервер 2: http2.example.com, IP адрес: 192.168.0.103
  • Также нам понадобится виртуальный IP, который будет объединять узлы балансировки: 192.168.0.99

Cхематичное изображение нашего кусочка сети:

    shared IP=192.168.0.99
 192.168.0.100  192.168.0.101 192.168.0.102 192.168.0.103
 -------+------------+--------------+-----------+----------
        |            |              |           |
     +--+--+      +--+--+      +----+----+ +----+----+
     | lb1 |      | lb2 |      |  http1  | |  http2  |
     +-----+      +-----+      +---------+ +---------+
     Perlbal      Perlbal      2 web servers (Apache)
     heartbeat    heartbeat

Общий (виртуальный) IP-адрес не является проблемой, если вы сами являетесь администратором своей сети и можете самостоятельно выделять IP-адреса. Если же вы используете публичные адреса, то вам придется найти хостера, который даст вам два сервера (узлы балансировки) в одной подсети. Для общего IP вы можете использовать свободный адрес из той же подсети.

Подготовка бэкэнда

Мы сконфигурируем Perlbal как прозрачный прокси. Т.е. он будет транслировать запросы к бэкэнд-серверам, сохраняя оригинальный адрес клиента в заголовке X-Forwarded-For. 
Конечно же, мы хотим видеть в логах оригинальные адреса, а не IP наших балансировочных узлов. Поэтому немного поправим конфигурацию логов Apache. Отредактируем файл /etc/apache2/apache2.conf на http1/http2:

[...]
#LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
[...]

и незабываем о /etc/init.d/apache2 restart

На этом настройка бэкэндов закончена. Перейдем к балансировочным узлам.

Установка Perlbal

Сначала установим необходимые зависимости:

lb1/lb2:
apt-get install build-essential unzip lynx ncftp perl
Затем запустим оболочку Perl
perl -MCPAN -e shell
И выполним в ней три команды

force install HTTP::Date
install IO::AIO
force install Perlbal

Perlbal установлен.

Настройка узлов балансировки

Конфигурационный файл Perlbal находится в /etc/perlbal/perlbal.conf

CREATE POOL webfarm
  POOL webfarm ADD 192.168.0.102:80
  POOL webfarm ADD 192.168.0.103:80

CREATE SERVICE balancer
  SET listen          = 192.168.0.99:80
  SET role            = reverse_proxy
  SET pool            = webfarm
  SET persist_client  = on
  SET persist_backend = on
  SET verify_backend  = on
ENABLE balancer

Вероятно, вы захотите узнать больше об опциях конфигурации Perlbal. 
Лучший способ это сделать - скачать последнюю версию с http://code.google.com/p/perlbal/downloads/list

Настройка Heartbeat

Мы настроили Perlbal на прослушивание нашего виртуального IP 192.168.0.99,  но кто-то должен “сообщить” узлам балансировки, что они также должны слушать этот IP.  Это сделает Heartbeat.
Установим его на балансерах lb1 и lb2
apt-get install heartbeat
Для того, чтобы разрешить Perlbal слушать IP, мы должны добавить в /etc/sysctl.conf запись

[...]
net.ipv4.ip_nonlocal_bind=1

и выполнить команду sysctl -p

Теперь создадим три конфигурационных файла для Heartbeat:

/etc/ha.d/authkeys
/etc/ha.d/ha.cf
/etc/ha.d/haresources

/etc/ha.d/authkeys и /etc/ha.d/haresources должны быть одинаковыми на lb1 и lb2.
/etc/ha.d/ha.cf отличается всего одной строчкой.

nano /etc/ha.d/authkeys

auth 3
3 md5 somerandomstring

somerandomstring - это пароль, который используется heartbeat на lb1 и lb2 для взаимной аутентификации. Задайте ваш собственный пароль.

lb1:

vi /etc/ha.d/ha.cf

#
#       keepalive: how many seconds between heartbeats
#
keepalive 2
#
#       deadtime: seconds-to-declare-host-dead
#
deadtime 10
#
#       What UDP port to use for udp or ppp-udp communication?
#
udpport        694
bcast  eth0
mcast eth0 225.0.0.1 694 1 0
ucast eth0 192.168.0.101
#       What interfaces to heartbeat over?
udp     eth0
#
#       Facility to use for syslog()/logger (alternative to log/debugfile)
#
logfacility     local0
#
#       Tell what machines are in the cluster
#       node    nodename ...    -- must match uname -n
node    lb1.example.com
node    lb2.example.com

Опция ucast очень важна - в ней задается адрес второго узла балансировщика.
В нашем примере это 192.168.0.101 (lb2.example.com).

lb2:

nano /etc/ha.d/ha.cf

#
#       keepalive: how many seconds between heartbeats
#
keepalive 2
#
#       deadtime: seconds-to-declare-host-dead
#
deadtime 10
#
#       What UDP port to use for udp or ppp-udp communication?
#
udpport        694
bcast  eth0
mcast eth0 225.0.0.1 694 1 0
ucast eth0 192.168.0.100
#       What interfaces to heartbeat over?
udp     eth0
#
#       Facility to use for syslog()/logger (alternative to log/debugfile)
#
logfacility     local0
#
#       Tell what machines are in the cluster
#       node    nodename ...    -- must match uname -n
node    lb1.example.com
node    lb2.example.com

lb1/lb2:
vi /etc/ha.d/haresources

lb1.example.com 192.168.0.99

Теперь запустим Heartbeat на обоих узлах /etc/init.d/heartbeat start

Мы должны увидеть, что хост lb1 слушает наш виртуальный IP

lb1:~# ifconfig
eth0      Link encap:Ethernet  HWaddr 00:0C:29:A5:5B:93
          inet addr:192.168.0.100  Bcast:192.168.0.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fea5:5b93/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:63983 errors:0 dropped:0 overruns:0 frame:0
          TX packets:31480 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:92604963 (88.3 MiB)  TX bytes:2689903 (2.5 MiB)
          Interrupt:177 Base address:0x1400

eth0:0    Link encap:Ethernet  HWaddr 00:0C:29:A5:5B:93
          inet addr:192.168.0.99  Bcast:192.168.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          Interrupt:177 Base address:0x1400

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:56 errors:0 dropped:0 overruns:0 frame:0
          TX packets:56 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:3888 (3.7 KiB)  TX bytes:3888 (3.7 KiB)

lb1:~#

lb2 - это пассивный балансировочный узел. Он не должен слушать виртуальный IP, пока lb1 живет проверим это

lb2:~# ip addr sh eth0

Вывод должен быть примерно таким:

lb2:~# ip addr sh eth0
2: eth0:  mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 00:0c:29:e0:78:92 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.101/24 brd 192.168.0.255 scope global eth0
    inet6 fe80::20c:29ff:fee0:7892/64 scope link
       valid_lft forever preferred_lft forever
lb2:~#

 

lb2:~# ifconfig

eth0      Link encap:Ethernet  HWaddr 00:0C:29:E0:78:92
          inet addr:192.168.0.101  Bcast:192.168.0.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fee0:7892/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:75127 errors:0 dropped:0 overruns:0 frame:0
          TX packets:42144 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:109669197 (104.5 MiB)  TX bytes:3393369 (3.2 MiB)
          Interrupt:169 Base address:0x1400

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:56 errors:0 dropped:0 overruns:0 frame:0
          TX packets:56 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:3888 (3.7 KiB)  TX bytes:3888 (3.7 KiB)

lb2:~#

Запускаем Perlbal на lb1/lb2:

perlbal –daemon

Тестируем

Наш балансировочный узел настроен, запущен и готов к работе.
Вы можете выполнять HTTP-запросы к виртуальному IP 192.168.0.99 (или к тому адресу или доменному имени, с которым работаете вы) и в ответ будете получать контент с бэкэнд-серверов.

Для проверки отказоустойчивости и механизма failover остановите один из бэкэнд-серверов. Все запросы автоматически будут транслироваться к оставшемуся. Попробуйте остановить master-узел балансировщика (lb1), узел lb2 сразу возьмет на себя роль активного узла. вы можете проверить это, выполнив на lb2:

lb2:~# ip addr sh eth0

Теперь в этом выводе присутствует виртуальный адрес:

lb2:~# ip addr sh eth0
2: eth0:  mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 00:0c:29:e0:78:92 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.101/24 brd 192.168.0.255 scope global eth0
    inet 192.168.0.99/24 brd 192.168.0.255 scope global secondary eth0:0
    inet6 fe80::20c:29ff:fee0:7892/64 scope link
       valid_lft forever preferred_lft forever
lb2:~#

Как только узел lb1 будет вновь запущен, он опять будет выполнять функции master-узла.

Google Bookmarks Digg I.ua Ru-marks Ruspace Zakladok.net Reddit delicious Technorati Yahoo My Web News2.ru БобрДобр.ru Memori.ru rucity.com
  1. 29 Апрель 2009 в 13:09 | #1

    Даешь по статье в день!! =)
    Очень интересно вас читать, спасибо вам большое =)

  2. 17 Январь 2010 в 15:38 | #2

    не плохо, написать модет надо было вступление по больше?
    например, Perlbal Vs Nging?

    на соклько я знаю на FreeBSD большие плюсы использования Perlbal + механизма Kevent и AIO

  1. Пока что нет уведомлений.