- Балансировка нагрузки с LVS
- DNS-RR
- LVS
- Правила
- Подводные камни
- Единая точка отказа
- Ultramonkey
- Применимость
- Что еще почитать?
- How To Setup LVS (Linux Virtual Server) Load Balancer on CentOS 8 / RHEL 8
- Step 1: Installing Linux Virtual Server on CentOS 8 / RHEL 8
- Step 2: Enabling IP forwarding and enable service
- Step 3: Configure LVS as Load Balancer
- Step 4: Adding a Virtual Service
Балансировка нагрузки с 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, то сервер будет исключен из всех операций. Очень удобно, если нужно вывести сервер из эксплуатации.
- 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 # 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 для этого случая. Однако сейчас мы его касаться не будем.
Что еще почитать?
Какие решения для балансировки используете вы?
Буду рад любым замечаниям и комментариям.
How To Setup LVS (Linux Virtual Server) Load Balancer on CentOS 8 / RHEL 8
Linux Virtual Server is a highly salable and highly available server built on a cluster of real servers with the load balance running on the Linux Operating System.
First of all we will install the Linux Virtual Server package on Our CentOS 8 / RHEL 8 machine. After Installing LVS on our Operating System we will configure it as a load balancer to the back end servers. This setup assumes you have installed a CentOS / RHEL 8 server or workstation edition.
Step 1: Installing Linux Virtual Server on CentOS 8 / RHEL 8
Run the following command on your server to Install Linux Virtual Server and Choose yes to proceed further.
[[email protected] ~]$ sudo yum install ipvsadm
[sudo] password for sabi:
Last metadata expiration check: 3:38:25 ago on Sun 22 Dec 2019 12:37:06 AM EST.
Dependencies resolved.
Package Arch Version Repository Size
Installing:
ipvsadm x86_64 1.29-8.el8 AppStream 57 k
Transaction Summary
Install 1 Package
Total download size: 57 k
Installed size: 83 k
Is this ok [y/N]: y
Step 2: Enabling IP forwarding and enable service
When you have finished installing package, enable the service and IP forwarding in your machine.
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Confirm it is turned to 1
[[email protected] ~]$ echo 'net.ipv4.ip forward = 1' | sudo tee -a /etc/sysctl.conf
[sudo] password for sabi:
net.ipv4.ip forward = 1
Start and enable ipvsadm services by running
sudo touch /etc/sysconfig/ipvsadm
sudo systemctl enable –now ipvsadm
Check out the service status, it will be look like as:
[[email protected] ~]$ systemctl status ipvsadm
● ipvsadm.service - Initialise the Linux Virtual Server
Loaded: loaded (/usr/lib/systemd/system/ipvsadm.service; enabled; vendor preset: di>
Active: active (exited) since Sun 2019-12-22 04:25:30 EST; 20s ago
Process: 5880 ExecStart=/bin/bash -c exec /sbin/ipvsadm-restore < /etc/sysconfig/ipv>
Main PID: 5880 (code=exited, status=0/SUCCESS)
Dec 22 04:25:29 localhost.localdomain systemd[1]: Starting Initialise the Linux Virtua>
Dec 22 04:25:30 localhost.localdomain systemd[1]: Started Initialise the Linux Virtual>
lines 1-8/8 (END)
Step 3: Configure LVS as Load Balancer
After setting up all, move forward to configure LVS as a load balancer to actual back-end applications.
Clean the IP tables rules by running
Step 4: Adding a Virtual Service
Add a virtual service by using the syntax
ipvsadm -A -t (ServiceIP:Port) -s (Distribution method)
Following Distribution methods supported:
- rr (Round Robin) = Equal load distribution among back-end servers
- wrr (Weighted Round Robin) = The Round Robin based on real Servers weight
- lc (Least Connection) = Servers having few active processes are selected for new load assignment on priority basis.
- wlc ( Weighted Least Connection) = Assigns tasks to servers with fewer jobs and relative to the real server’s weight (Ci/Wi) . By default, this method is used.
We will do configuration based on below diagram.
In this case, I’m setting LVS server to listen on 192.168.233.129 with port 80.
sudo ipvsadm -A -t 192.168.233.129:80 -s wlc
Now, add the back-end servers by typing
sudo ipvsadm -a -t (ServiceIP:Port) -r (BackendServerIP:Port) -m
The configuration will look like
sudo ipvsadm -a -t 192.168.233.129:80 -r 192.168.233.209:80 -m
sudo ipvsadm -a -t 192.168.233.129:80 -r 192.168.233.4:80 -m
Type the following command to list current rules:
[[email protected] ~]$ sudo ipvsadm -l
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP cent01:http wlc
-> cent03:http Masq 1 0 0
-> cent02:http Masq 1 0 0
Allow Firewall
sudo firewall-cmd --add-service=http --permanent
sudo firewall-cmd --reload
Now, when you load the LVS server IP / domain name from the browser, you will see the page on one of the back-end server.
Hi this is the LVS server page on back-end server 1
Upon reloading, the back-end server 2 page should show
Hi this is the LVS server page on back-end server 2
This is how you can set up your LVS server on CentOS 8 / RHEL 8.