System administration
September 2010 21

Балансировка нагрузки с LVS

Итак, у вас есть нагруженный сервер и вам вдруг захотелось его разгрузить. Вы поставили и залили такой же (такие же), но пользователи упорно ходят на первый. В этом случае конечно же нужно задуматься о балансировке нагрузки.



DNS-RR


Первым делом напрашивается вариант с использованием Round-robin DNS. Если кто не знает, это метод позволяющий размазать запросы между n-ым количеством серверов просто отдавая на каждый DNS запрос новый IP.

Каковы минусы:
  • Сложно управлять: вы забили группу IP-адресов и все, никаких тебе управлений весами, состояние серверов не отслеживается и т.д.
  • Фактически вы размазываете запросы по диапазону IP, но не балансируете нагрузку на серверах
  • Кэширование DNS клиента может поломать всю малину


Хотя и не стоит добавлять между вводом и выводом «слишком много компьютера», хочется каких-либо методов контроля над ситуацией.

LVS


И тут на помощь к нам приходит Linux Virtual Server или LVS. Фактически, это модуль ядра (ipvs), существующий еще где-то с версии 2.0-2.2.

Что же он из себя представляет? Фактически это L4-роутер (я бы сказал что L3, но авторы настаивают на L4), позволяющий прозрачно и управляемо разруливать пакеты по заданным маршрутам.



Основная терминология следующая:
  • Director — собственно узел осуществляющий роутинг.
  • Realserver — рабочая лошадка, узел нашей фермы серверов.
  • VIP или Virtual IP — всего лишь IP нашего виртуального (собранного из кучи реальных) сервера.
  • Соответственно DIP и RIP — IP директора и реальных серверов.


На директоре включается этот самый модуль IPVS (IP Virtual Server), настраиваются правила проброса пакетов и поднимается VIP — обычно как алиас к внешнему интерфейсу. Пользователи будут ходить через VIP.

Пакеты, пришедшие на VIP пробрасываются выбранным методом до одного из Realserver'ов и там уже нормально отрабатываются. Клиенту кажется что он работает с одной машиной.

Правила


Правила проброса пакетов крайне просты: задаем виртуальный сервис, определяемый парой VIP:port. Сервис может быть TCP или UDP. Здесь же задаем метод ротации узлов (планировщик, scheduler). Далее задаем набор серверов из нашей фермы, также парой RIP:port, а также указываем метод проброса пакетов и вес, если того требует выбранный планировщик.

Выглядит это примерно следующим образом.

# ipvsadm -A -t 192.168.100.100:80 -s wlc
# ipvsadm -a -t 192.168.100.100:80 -r 192.168.100.2:80 -w 3
# ipvsadm -a -t 192.168.100.100:80 -r 192.168.100.3:80 -w 2
# ipvsadm -a -t 192.168.100.100:80 -r 127.0.0.1:80 -w 1


Да, не забудьте поставить пакет ipvsadmin, он должен быть в репозитории вашего дистрибутива. Во всяком случае в Debian и RedHat он есть.

В примере выше мы создаем виртуальный HTTP сервис 192.168.100.100 и включаем в него сервера 127.0.0.1, 192.168.100.2 и 192.168.100.3. Ключ "-w" задает вес сервера. Чем он выше, тем с бОльшей вероятностью он получит запрос. Если выставить вес в 0, то сервер будет исключен из всех операций. Очень удобно, если нужно вывести сервер из эксплуатации.

Пакеты по умолчанию пробрасываются методом DR. Вообще существуют следующие варианты роутинга:
  • Direct Routing (gatewaying) — пакет направляется напрямую на ферму, без изменений.
  • NAT (masquarading) — просто хитрый механизм NAT.
  • IPIP incapsulation (tunneling) — туннелирование.


DR является наиболее простым, но если вам, например, нужно поменять порт назначения, то придется рисовать правила в iptables. NAT же требует, чтобы маршрут по умолчанию у всей фермы был направлен на директора, что не всегда удобно, особенно если реальные сервера имеют и внешние адреса.

Планировщиков в комплекте поставки несколько, подробно можно почитать в инструкции. Рассмотрим лишь основные.
  • Round Robin — знакомая всем круговая порука.
  • Weighted Round Robin — тоже самое, но с использованием весов сервера.
  • Least Connection — отправляем пакет серверу с наименьшим количеством соединений.
  • Weighted Least Connection — тоже самое, но с учетом весов.


Ко всему прочему, можно сообщить, что сервис требует persistence, т.е. удерживание пользователя на одном из серверов в течении заданного промежутка времени — все новые запросы с одного и того же IP будут прокинуты на тот же сервер.

Подводные камни


Итак, согласно примеру выше, мы должны были получить виртуальный сервер на VIP 192.168.100.100, о чем нам ipvsadm и радостно сообщает:

ipvsadm -L -n
IP Virtual Server version 1.0.7 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.100.100:80 wlc
-> 192.168.100.2:80 Route 3 0 0
-> 192.168.100.3:80 Route 2 0 0
-> 127.0.0.1:80 Local 1 0 0


Однако, при попытке соединения ничего не произойдет! В чем же дело? Первым делом необходимо поднять алиас.
# ifconfig eth0:0 inet 192.168.100.100 netmask 255.255.255.255

Но и тут нас ждет неудача — пакет приходит на интерфейс реального сервера немодифицированным и следовательно тупо отпинывается ядром как не предназначающийся машине. Простейшим методом разрешения этого вопроса является поднятие VIP на loopback.

# ifconfig lo:0 inet 192.168.100.100 netmask 255.255.255.255

Ни в коем случае не поднимайте его на интерфейсе, который глядит в ту же подсеть, что и внешний интерфейс директора. В противном случае внешний роутер может закэшировать mac не той машины и весь трафик пойдет не туда.

Теперь пакетики должны побежать куда надо. Кстати, директор сам может быть реальным сервером, что мы и видим в нашем примере.

Единая точка отказа


В этом решении очевидной точкой отказа, вызывающей разрушение всего сервиса, будет сам директор.

Что ж, не беда, ipvsadm поддерживает запуск в режиме демона с возможностью синхронизации таблиц и текущих соединений между несколькими директорами. Один, очевидно, станет мастером, остальные будут слейвами.

Что остается нам? Переезжать VIP между директорами в случае отказа. Тут нам помогут HA решения вроде heartbeat.

Другой задачей будет мониторинг и своевременный вывод из эксплуатации серверов из нашей фермы. Проще всего это делать весами.

Для разруливания обоих вопросов написано множество решений, заточенных под разные типы сервисов. Мне лично больше всего понравилось решение Ultramonkey, от самих же авторов LVS.

У RedHat есть родная штука под названием Piranha, она имеет свой набор демонов для мониторинга фермы и директоров и даже некий топорненький веб-интерфейс, однако она не поддерживает более чем 2 директора в HA связке. Уж не знаю почему.

Ultramonkey


Итак, Ultramonkey состоит из 2-х основных пакетов — heartbeat и ldirectord. Первый занимается обеспечением HA для директоров, в том числе поднятие и переезд VIP (и вообще говоря может использоваться не только для директоров), а второй поддерживает конфиг ipvsadm и мониторит состояние фермы.

Для heartbeat необходимо нарисовать 3 конфига. Базовые версии снабжены подробными комментариями, поэтому просто приведу примеры.

authkeys
auth 2
#1 crc
2 sha1 mysecretpass
#3 md5 Hello!

Настраиваем авторизацию демонов на разных машинах.

haresources
Здесь у нас информация о том, для какого ресурса мы создаем HA и какие сервисы дергаем при переезде.
director1.foo.com IPaddr::192.168.100.100/24/eth0 ldirectord

Т.е. поднять на интерфейсе eth0 192.168.100.100/24 и запустить ldirectord.

ha.cf
keepalive 1
deadtime 20
udpport 694
udp eth0
node director1.foo.com # <-- должно совпадать с uname -n !
node director2.foo.com #

Говорим каким образом поддерживать HA кластер и кто собственно в него входит.

У ldirectord всего один конфиг и там в общем-то тоже все понятно.
checktimeout=10
checkinterval=2
autoreload=yes
logfile="/var/log/ldirectord.log"
# Virtual Service for HTTP
virtual=192.168.100.100:80
real=192.168.100.2:80 gate
real=192.168.100.3:80 gate
service=http
request="alive.html"
receive="I'm alive!"
scheduler=wlc
protocol=tcp
checktype=negotiate


Т.е. ldirectord будет каждые 2 секунды дергать через http файл alive.html и если в нем не будет строчки «I'm alive!» или, хуже того, сервер не ответит, демон тут же поставит ему вес 0 и он будет исключен из последующих пересылок.

Веса также можно расставлять самому, например пробегаясь кроном по полю и вычисляя их в зависимости от текущего loadavg и т.п. — прямой доступ к ipvsadm у вас никто не отнимает.

Применимость


Хотя везде по интернету в качестве сферы применения LVS в основном рассматривается балансировка веб-серверов, на самом деле им можно балансировать великое множество сервисов. Если протокол держится на одном порте и не имеет состояний, то его можно будет балансировать без особых проблем. Сложнее дело обстоит с мультипортовыми протоколами вроде samba и ftp, но и тут есть решения.

Кстати, в качестве реальных серверов не обязательно должен выступать Linux. Это можеть быть практически любая ОС со стеком TCP/IP.

Также существует еще и так называемый L7-роутер, который оперирует уже не портами, а знаниями о высокоуровневых протоколах. Товарищи японцы разрабатывают Ultramonkey-L7 для этого случая. Однако сейчас мы его касаться не будем.

Что еще почитать?




Какие решения для балансировки используете вы?
Буду рад любым замечаниям и комментариям.

+77
72.4k 392
Comments 50