Что такое Keepalived
Опубликовано: 24.01.2023
Keepalived —
легкое приложение для обеспечения отказоустойчивости сервисов и балансировки нагрузки.
Keepalived реализует набор средств проверки работоспособности, позволяя определять рабочие ноды кластера и менять состояние участников. Также keepalived позволяет выполнять набор хуков для автоматизации процесса при смене данного состояния. Высокая доступность достигается протоколом маршрутизации с виртуальным резервированием (VRRP).
Подробная документация представлена на сайте keepalived.readthedocs.io, но на английском языке. На русском инструкции ограничиваются примерами по настройке приложения.
Keepalived может быть установлен на все популярные дистрибутивы Linux. По умолчанию, он есть во многих официальных репозиториях и может быть установлен одной из двух команд:
apt install k eepalived
yum install k eepalived
* первая команда для deb (Debian / Ubuntu / Astra Linux), вторая для rpm (Rocky Linux / РЕД ОС).
Среди аналогов можно выделить:
Также в качестве аналога k eepalived часто приводят HAProxy. Тут важно сделать оговорку, что последний выполняет балансировку, пропуская трафик через себя, в то время как k eepalived позволяет определить рабочую ноду для прямого обращения. Кстати, k eepalived и HAProxy, иногда, используют вместе.
Встречается в статьях
Мини-инструкции:
- Шпаргалка по настройке SELinux для различных программ
- Установка, настройка и создание кластера с помощью keepalived
Keepalived: настройка высокой доступности и плавающих IP адресов в CentOS 7
17.03.2022
Андрей
CentOS, Linux
комментариев 6
В этой статье мы рассмотрим настройку отказоустойчивой конфигурации из двух прокси серверов squid для доступа пользователей в Интернет из корпоративной сети с простой балансировкой нагрузки через Round Robin DNS. Для построения отказоустойчивой конфигурации мы создадим HA-кластер с помощью keepalived.
HA-кластер — это группа серверов с заложенной избыточностью, которая создается с целью минимизации времени простоя приложения, в случае аппаратных или программных проблем одного из членов группы. Исходя из этого определения, для работы HA-кластера необходимо реализовать следующее:
-
Проверка состояния серверов;
Обе эти задачи позволяет выполнить keepalived. Keepalived – системный демон на Linux системах, позволяющего организовать отказоустойчивость сервиса и балансировку нагрузки. Отказоустойчивость достигается за счет “плавающего» IP адреса, который переключается на резервный сервер в случае отказа основного. Для автоматического переключения IP адреса между серверами keepalived используется протокол VRRP (Virtual Router Redundancy Protocol), он стандартизирован, описан в RFC (https://www.ietf.org/rfc/rfc2338.txt).
Принципы работы протокола VRRP
В первую очередь нужно рассмотреть теорию и основные определения протокола VRRP.
- VIP — Virtual IP, виртуальный IP адрес, который может автоматически переключаться между серверами в случае сбоев;
- Master — сервер, на котором в данный момент активен VIP;
- Backup — сервера на которые переключится VIP, в случае сбоя мастера;
- VRID — Virtual Router ID, сервера объединенные общим виртуальным IP(VIP) образуют так называемый виртуальный роутер, уникальный идентификатор которого, принимает значения от 1 до 255. Сервер может одновременно состоять в нескольких VRID, при этом для каждой VRID должны использоваться уникальные виртуальные IP адреса.
Общий алгоритм работы:
-
Master сервер с заданным интервалом отправляет VRRP пакеты на зарезервированный адрес multicast (многоадресной) рассылки 224.0.0.18, а все slave сервера слушают этот адрес. Multicast рассылка — это когда отправитель один, а получателей может быть много.
Важно. Для работы серверов в режиме multicast, сетевое оборудование должно поддерживать передачу multicast трафика.
Установка и настройка keepalived на CentOS
Установку и настройку будем проводить на примере серверов proxy-serv01 и proxy-serv02 на Centos 7 с установленным прокси сервером Squid. В нашей схеме мы будем использовать простейший способ распределения (балансировки) нагрузки — Round Robin DNS. Этот способ предполагает, что для одного имени в DNS регистрируется несколько IP адресов, и клиенты, при запросе получают поочередно сначала один адрес, потом другой. Поэтому нам понадобится два виртуальных IP адреса, которые будут зарегистрированы в DNS на одно имя и на которые в итоге будут обращаться клиенты. Схема сети:
У каждого Linux сервера есть два физических сетевых интерфейса: eth1 с белым IP адресом и доступом в Интернет, и eth0 в локальной сети.
В качестве реальных IP адресов серверов используются:
192.168.2.251 — для proxy-server01
192.168.2.252 — для proxy-server02
В качестве виртуальных IP адресов, которые будут автоматически переключаться между серверами в случае сбоев используются:
192.168.2.101
192.168.2.102
Важно. При настройке VRRP, в качестве адреса для виртуального IP не используется реальный адрес сервера, так как, в случае сбоя, его адрес переместится на соседний, и при восстановлении, он окажется изолированным от сети. Дело в том, чтобы вернуть свой адрес, нужно отправить в сеть VRRP пакет, но не будет IP адреса, с которого это возможно сделать.
Установить пакет keepalived нужно на обоих серверах, командой:
yum install keepalived
После завершения установки на обоих серверах правим конфигурационный файл
/etc/keepalived/keepalived.conf
Цветом выделены строки с отличающимися параметрами:
на сервере proxy-serv01 | на сервере proxy-serv02 |
![]() |
![]() |
Разберем опции более подробно:
- vrrp_instance — секция, определяющая экземпляр VRRP;
- state
— начальное состояние при запуске; - interface — интерфейс, на котором будет работать VRRP;
- virtual_router_id — уникальный идентификатор VRRP экземпляра, должен совпадать на всех серверах;
Примечание. Можно встретить множество примеров, в которых при настройке VRRP используется опция authentication. Однако в документации keepalived упоминается о том, что аутентификация была удалена из VRRPv2 в спецификации RFC3768(https://tools.ietf.org/html/rfc3768) в 2004 году, так как не обеспечивала реальной безопасности. Рекомендуется избегать использования этой опции.
Если текущая сетевая конфигурация не позволяет использовать multicast, в keepalived есть возможность использовать unicast, т.е. передавать VRRP пакеты напрямую серверам, которые задаются списком. Чтобы использовать unicast, понадобятся опции:
- unicast_src_ip — адрес источник для VRRP пакетов;
- unicast_peer — блок IP адресов серверов, на которые будут рассылаться VRPP пакеты.
Таким образом, наша конфигурация определяет два VRRP экземпляра, proxy_ip1 и proxy_ip2. При штатной работе, сервер proxy-serv01 будет MASTER для виртуального IP 192.168.2.101 и BACKUP для 192.168.2.102, а сервер proxy-serv02 наоборот, будет MASTER для виртуального IP 192.168.2.102, и BACKUP для 192.168.2.101.
Если на сервере активирован файрвол, то нужно добавить разрешающие правила для multicast траффика и vrrp протокола с помощью iptables:
iptables -A INPUT -i eth0 -d 224.0.0.0/8 -j ACCEPT
iptables -A INPUT -p vrrp -i eth0 -j ACCEPT
Активируем автозагрузки и запустим службу keepalived на обоих серверах:
systemctl enable keepalived
systemctl start keepalived
После запуска службы keepalived, виртуальные IP будут присвоены интерфейсам из конфигурационного файла. Посмотрим текущие IP адреса на интерфейсе eth0 серверов:
На сервере proxy-serv01:
На сервере proxy-serv02:
Keepalived: отслеживание состояния приложений и интерфейсов
Благодаря протоколу VRRP штатно обеспечивается мониторинг состояния сервера, например, при полном физическом отказе сервера, или сетевого порта на сервере или коммутаторе. Однако, возможны и другие проблемные ситуации:
- ошибка в работе службы прокси сервера — клиенты, которые попадут на виртуальный адрес этого сервера, будут получать сообщение в браузере с ошибкой, что прокси сервер недоступен;
- отказ в работе второго интерфейса в интернет — клиенты, которые попадут на виртуальный адрес этого сервера, будут получать сообщение в браузере с ошибкой, что не удалось установить соединение.
Для обработки перечисленных выше ситуаций, воспользуемся следующими опциями:
- track_interface — мониторинг состояния интерфейсов, переводит VRRP экземпляр в состояние FAULT, если один из перечисленных интерфейсов находится в состоянии DOWN;
- track_script — мониторинг с использованием скрипта, который должен возвращать 0 если проверка завершилась успешно , 1 — если проверка завершилась с ошибкой.
Обновим конфигурацию, добавим мониторинг интерфейса eth1 (по умолчанию, VRRP экземпляр будет проверять интерфейс, к которому он привязан, т.е. в текущей конфигурации eth0):
track_interface < eth1
Директива track_script запускает скрипт с параметрами, определенными в блоке vrrp_script, который имеет следующий формат:
vrrp_script < script interval - периодичность запуска скрипта, по умолчанию 1 секунда fall - количество раз, которое скрипт вернул не нулевое значение, при котором перейти в состояние FAULT rise - количество раз, которое скрипт вернул нулевое значение, при котором выйти из состояния FAULT timeout - время ожидания, пока скрипт вернет результат, после которого вернуть ненулевое значение. weight - значение, на которое будет уменьшен приоритет сервера, в случае перехода в состояние FAULT. По умолчанию 0, что означает, что сервер перейдет в состояние FAULT, после неудачного выполнения скрипта за количество раз, определенное параметром fall. >
Настроим мониторинг работы Squid. Проверить, что процесс активен, можно командой:
Создадим vrrp_script, с параметрами периодичности выполнения каждые 3 секунды. Этот блок определяется за пределами блоков vrrp_instance.
vrrp_script chk_squid_service < script "/usr/sbin/squid -k check" interval 3 >
Добавим наш скрипт в мониторинг, внутри обоих блоков vrrp_instance:
track_script
Теперь при ошибке в работе службы прокси Squid, виртуальный IP адрес переключится на другой сервер.
Вы можете добавить дополнительные действия при изменении состояния сервера.
Если Squid настроен на прием подключений с любого интерфейса, т.е. http_port 0.0.0.0:3128, то при переключении виртуального IP адреса, никаких проблем не возникнет, Squid будет принимать подключения на новом адресе. Но, если настроены конкретные IP адреса, например:
http_port 192.168.2.101:3128 http_port 192.168.2.102:3128
то Squid не узнает о том, что в системе появился новый адрес, на котором нужно слушать запросы от клиентов. Для обработки подобных ситуаций, когда нужно выполнить дополнительные действия при переключении виртуального IP адреса, в keepalived заложена возможность выполнения скрипта при наступлении события изменения состояния сервера, например, с MASTER на BACKUP, или наоборот. Реализуется опцией:
notify "путь к исполняемому файлу"
Keepalived: тестирование переключения при отказе
После настройки виртуальных IP, проверим, насколько корректно происходит обработка сбоев. Первая проверка — имитация сбоя одного из серверов. Отключим от сети внутренний сетевой интерфейс eth0 сервера proxy-serv01, при этом он перестанет отправлять VRRP пакеты и сервер proxy-serv02 должен активировать у себя виртуальный IP адрес 192.168.2.101. Результат проверим командой:
На сервере proxy-serv01:
На сервере proxy-serv02:
Как и ожидалось, сервер proxy-serv02 активировал у себя виртуальный IP адрес 192.168.2.101. Посмотрим, что при этом происходило в логах, командой:
cat /var/log/messages | grep -i keepalived
Keepalived_vrrp[xxxxx]: Kernel is reporting: interface eth0 DOWN Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Entering FAULT STATE Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) removing protocol VIPs. Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Now in FAULT state
Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Transition to MASTER STATE
И проверим, что после включения в сеть интерфейса eth0 на сервере proxy-serv01, виртуальный IP 192.168.2.101 переключится обратно.
Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) forcing a new MASTER election Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Transition to MASTER STATE Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Entering MASTER STATE Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) setting protocol VIPs. Keepalived_vrrp[xxxxx]: Sending gratuitous ARP on eth0 for 192.168.2.101
Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Received advert with higher priority 255, ours 100 Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Entering BACKUP STATE Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) removing protocol VIPs.
Вторая проверка – имитация сбоя интерфейса внешний сети, для этого отключим от сети внешний сетевой интерфейс eth1 сервера proxy-serv01. Результат проверки проконтролируем по логам.
Keepalived_vrrp[xxxxx]: Kernel is reporting: interface eth1 DOWN Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Entering FAULT STATE Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) removing protocol VIPs. Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Now in FAULT state
Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Transition to MASTER STATE Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Entering MASTER STATE Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) setting protocol VIPs. Keepalived_vrrp[xxxxx]: Sending gratuitous ARP on eth0 for 192.168.2.101
Третья проверка — имитация сбоя работы службы прокси Squid, для этого вручную оставим службу командой: systemctl stop squid Результат проверки проконтролируем по логам.
Keepalived_vrrp[xxxxx]: VRRP_Script(chk_squid_service) failed Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Entering FAULT STATE Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) removing protocol VIPs. Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Now in FAULT state
Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Transition to MASTER STATE Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Entering MASTER STATE Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) setting protocol VIPs. Keepalived_vrrp[xxxxx]: Sending gratuitous ARP on eth0 for 192.168.2.101
Все три проверки пройдены успешно, keepalived настроен корректно. В продолжении этой статьи будет произведена настройка HA-кластера с помощью Pacemaker, и рассмотрена специфика каждого из этих инструментов.
Итоговый конфигурационный файл /etc/keepalived/keepalived.conf для сервера proxy-serv01:
vrrp_script chk_squid_service < script "/usr/sbin/squid -k check" interval 3 >vrrp_instance proxy_ip1 < state MASTER interface eth0 virtual_router_id 1 priority 255 virtual_ipaddress < 192.168.2.101/24 dev eth0 label eth0:1 >track_interface < eth1 >track_script < chk_squid_service >> vrrp_instance proxy_ip2 < state BACKUP interface eth0 virtual_router_id 2 priority 100 virtual_ipaddress < 192.168.2.102/24 dev eth0 label eth0:2 >track_interface < eth1 >track_script < chk_squid_service >>
Итоговый конфигурационный файл /etc/keepalived/keepalived.conf для сервера proxy-serv02:
vrrp_script chk_squid_service < script "/usr/sbin/squid -k check" interval 3 >vrrp_instance proxy_ip1 < state BACKUP interface eth0 virtual_router_id 1 priority 100 virtual_ipaddress < 192.168.2.101/24 dev eth0 label eth0:1 >track_interface < eth1 >track_script < chk_squid_service >> vrrp_instance proxy_ip2 < state MASTER interface eth0 virtual_router_id 2 priority 255 virtual_ipaddress < 192.168.2.102/24 dev eth0 label eth0:2 >track_interface < eth1 >track_script < chk_squid_service >>
Предыдущая статья Следующая статья
Отказоустойчивый кластер с балансировкой нагрузки с помощью keepalived
Сегодня я расскажу о том, как быстро собрать отказоустойчивый кластер с балансировкой нагрузки с помощью keepalived на примере DNS-серверов.
Итак, предположим, что у нас есть сервер, который должен работать без перебоев. Его нельзя просто так взять и выключить посреди рабочего дня — клиенты или пользователи не поймут. Тем не менее любой сервер время от времени надо обслуживать, ставить обновления, менять аппаратную конфигурацию или сетевые настройки. Кроме того, нужно быть готовым к росту нагрузки, когда мощности сервера перестанет хватать. У сервера должна быть предусмотрена возможность быстрого масштабирования. Если вы озаботились этими проблемами, то вам нужно организовать отказоустойчивый кластер.
Чаще всего такие задачи приходится делать с HTTP-серверами. Я сегодня покажу сборку кластера на примере DNS, потому что опробовал технологию именно на нем, но с минимальными изменениями то же самое можно сделать и с серверами, работающими по TLS или HTTP.
Лирическое отступление о проблемах DNS
В принципе, DNS задуман так, чтобы необходимости городить огород с кластерами не возникало. В каждой зоне можно прописать множество NS-записей, в каждой сети можно раздать список DNS-серверов с помощью DHCP. DNS-сервера умеют реплицировать зоны, поэтому они хорошо масштабируются. Однако на практике это плохо работает. Когда я попробовал добавить 2-й DNS-сервер, то обнаружил, что
- Половина пользователей сидят со статическими настроенными адресами DNS-серверов. Ставят себе 4 восьмерки в качестве primary и локальный DNS в качестве secondary.
- Многие Linux-сервера не умеют из коробки корректно обновлять настройки DNS. Там такой зоопарк из glibc, nsswitch.conf, resolv.conf, NetworkManager, resolvconf, systemd-resolved, hosts, dhclient.conf и т. п., которые конфликтуют между собой, что рассчитывать на автоматическое обновление по DHCP просто не приходится.
- Windows шлет запросы одновременно на все сервера, но обязательно дожидается ответа или таймаута от 1-го
- Linux сначала обращается к 1-му DNS в списке и только в случае ошибки переходит к следующему.
Если долгое время в сети используется DNS-сервер с определенным IP, то он оказывается прописан в десятках разных мест. Например:
- Директива resolver в nginx.conf
- daemon.json в docker
- В настройках docker-контейнеров
- В конфигах модных нынче систем вроде kubernetes или openshift во внутренних файлах на каждой ноде и еще там же в конфигах dnsmasq.
- В конфигах почтовых серверов.
- В настройках VPN-серверов.
Никакими плейбуками и DHCP-декларациями это все обновить просто нереально. Поэтому было бы очень хорошо, если бы собираемый кластер можно было повесить на 1 уже существующий IP. Тогда для пользователей ничего не изменится, и софт перенастраивать не понадобится.
Поэтому я выбрал решение с keepalived и протоколом VRRP.
Подготовка
Собирая кластер из нескольких серверов, желательно уметь их различать на стороне клиента, чтобы не бегать искать по логам серверов, какой запрос, куда попал. Я для этого в bind9 завел вот такую зону.
/var/named/zones/load.balance.zone
$ORIGIN load.balance. $TTL 1h load.balance. 86400 IN SOA ns.mydomain.ru. dnsmaster.mydoamin.ru. ( 1603065098 3600 1800 604800 30 ) load.balance. IN NS ns.mydomain.ru. health IN TXT =nameserver-1=
На 1-м сервере ресурсная запись TXT для health.load.balance содержит текст =nameserver-1=, на 2-м сервере — =nameserver-2=, и т. д. Таким образом, отправляя запрос в кластер, я по ответу могу определить, какой сервер мне ответил, что очень удобно для отладки.
Если у вас HTTP-сервер, то поместите эту информацию в HTTP-заголовок. Например, для nginx я использую вот такую директиву
add_header serega-trace "$hostname" always;
Убедитесь, что ваши сетевые файерволлы не блокируют IP-трафик протокола 112 по адресу 224.0.0.18. Этот адрес будут использовать ваши сервера, чтобы договариваться между собой о том, кто из них MASTER, а кто BACKUP.
Открыть VRRP в iptables
iptables -t filter -I INPUT -p vrrp -d 224.0.0.18 -j ACCEPT iptables -t filter -I OUTPUT -p vrrp -d 224.0.0.18 -j ACCEPT
При организации DNS нужно выделить мастер-сервер, на который не будут идти клиентские запросы. DNS-мастер используется только для управления. Он реплицирует свои зоны на slave-сервера, которые уже видны пользователям, и именно на них идет нагрузка. Далее речь будет идти о кластеризации именно DNS-slave.
Уровень 1 (Easy)
Если вам просто достаточно резервирования на случай аварии, то рекомендую рассмотреть самый быстрый и простой вариант. 2 одинаковых сервера разделяют между собой общий виртуальный IP (далее буду называть его VIP). У кого в данный момент в сетевом интерфейсе прописан VIP, тот сервер и работает. 2-й сервер следит за мастером (имеется в виду мастер VRRP, а не DNS), и как только обнаруживает, что он перестал вещать, сразу объявляет мастером себя и поднимает VIP на своем сетевом интерфейсе.
Меня приятно удивило то, как быстро удалось поднять кластер по такому варианту. Несмотря на то, что раньше я никогда не имел дело с keepalived, уже через час все работало. Так что если вам нужно решить задачу быстро, то уровень 1 вам подойдет в самый раз.
Сбор информации
Для успешного развертывания вам понадобится собрать следующую информацию. Здесь я привожу значения для примера. У вас эти значения должны быть свои.
Параметр | Возможное значение | Описание |
---|---|---|
vip | 10.2.1.5 | виртуальный IP, на который шлют запросы клиенты |
dev0 | eth0 | 1-й сетевой интерфейс на узлах кластера |
ip01 | 10.2.1.2 | IP 1-го узла кластера на 1-м сетевом интерфейсе |
ip02 | 10.2.1.3 | IP 2-го узла кластера на 1-м сетевом интерфейсе |
net0 | 10.2.1.0/24 | подсеть, которой принадлежат ip01 и ip02 |
Установите keepalived и snmpd. SNMP ставить необязательно, но мне кажется, что, если серверов с виртуальными IP будет много, он будет полезен.
setenforce 0 # если вдруг у вас selinux dnf install -y keepalived nmap-ncat net-snmp net-snmp-utils systemctl enable keepalived systemctl enable snmpd
Netcat нужен для диагностики и healthcheck-ов.
В файл /etc/sysconfig/keepavlied добавьте опцию -x. Она нужна для взаимодействия keepalived с snmpd. Если вы не собираетесь поднимать SNMP, то этот шаг можете пропустить.
Отредактируйте файл /etc/snmp/snmpd.conf следующим образом:
/etc/snmp/snmpd.conf
master agentx rocommunity public
В /etc/keepalived положите вот такой скрипт keepalived-notify.sh:
/etc/keepalived/keepalived-notify.sh
#!/bin/sh umask -S u=rwx,g=rx,o=rx exec echo "[$(date -Iseconds)]" "$0" "$@" >>"/var/run/keepalived.$1.$2.state"
Этот скрипт будет вызываться демоном keepalived при изменении состояния кластера. Он запишет в каталог /var/run статусный файл, который удобно использовать для диагностики.
Отредактируйте основной конфигурационный файл keepalived.conf следующим образом:
global_defs < enable_script_security >vrrp_script myhealth < script "/bin/nc -z -w 2 127.0.0.1 53" interval 10 user nobody >vrrp_instance VI_1 < state BACKUP interface eth0 virtual_router_id 5 priority 100 advert_int 1 nopreempt notify /etc/keepalived/keepalived-notify.sh root authentication < auth_type PASS auth_pass KPSjXfRG >virtual_ipaddress < 10.2.1.5 >track_script < myhealth >>
Блок global_defs содержит единственную необходимую настройку enable_script_security, которая по умолчанию отключена.
Блок vrrp_script описывает скрипт, который демон keepalived будет использовать для определения работоспособности своего сервера. Если этот скрипт вернет ошибку, то демон перейдет в состояние FAIL, и не будет претендовать на роль MASTER. В этом же блоке описывается периодичность выполнения healthchek-ов и указывается пользователь, от имени которого запускается скрипт. В нашем случае используется утилита netcat, которая устанавливает соединение c локальным DNS-сервером по TCP-порту 53. Можно использовать разные проверки, например, прозвонить UDP-порт 53 утилитой dig.
В блоке VRRP_INSTANCE задаются настройки 1 экземпляра сервера с виртуальным IP.
- state задает начальное состояние сервера BACKUP или MASTER. В режиме nopreempt единственное допустимое значение — BACKUP.
- interface указывает, на каком сетевом интерфейсе будет поднят VIP
- virtual_router_id уникальный идентификатор роутера VRRP. Возможные значения от 1 до 255. У всех узлов кластера это значение должно быть одинаковым. Рекомендуется в качестве router_id использовать последний байт VIP, чтобы не запутаться, когда у вас таких виртуальных адресов будет много.
- priority задает приоритет данного экземпляра при выборе мастера. Мастером назначается сервер, у которого значение параметра priority выше. Если у нескольких серверов priority одинаковый, то мастер будет выбран случайным образом.
- advert_int определяет, с какой периодичностью мастер должен сообщать остальным о себе. Если по истечению данного периода сервера не получат от мастера широковещательное уведомление, то они инициируют выборы нового мастера.
- nopreempt означает, что если мастер пропал из сети, и был выбран новый мастер с меньшим приоритетом, то по возвращении старшего мастера, он останется в состоянии BACKUP. Т. е. если вы перезагрузили мастер, то он больше мастером не станет, пока новый мастер не отвалится. Если вы предпочитаете, чтобы мастером был какой-то конкретный сервер, то замените настройку nopreempt на preempt_delay.
- notify задает хук-скрипт, который будет вызываться при каждом изменении состояния сервера, и имя пользователя, от имени которого данный скрипт будет выполняться.
- authentication задает пароль, длиной до 8 символов, который будет защищать кластер от случайных коллизий с другими серверами в локальной сети.
- virtual_ipaddress задает VIP
- track_script указывает на описание скрипта, осуществляющего healthcheck.
Выполните указанные настройки на обоих серверах кластера и запустите сервисы:
systemctl start snmpd systemctl start keepalived
Проверьте логи и статусные файлы на наличие ошибок.
journalctl -u snmpd journalctl -u keepalived tail /var/run/keepalived.INSTANCE.VI_1.state
Если у вас используется selinux, не забудьте по данным audit.log обновить политики и вернуть enforcing mode командой set enforce 1.
Проверка
Если в логах ошибок нет, можно проверять. Поскольку мы кластеризовали DNS, то будем использовать dig. Для проверки HTTP-сервера подойдет curl.
Запустите на клиенте такой скрипт:
while true; do dig -4 +short +notcp +norecurse +tries=1 +timeout=1 \ -q health.load.balance. -t txt @10.2.1.5; sleep 1; done
Этот скрипт будет раз в секунду выдавать ресурсную запись health.load.balance/IN/TXT, которая содержит идентификатор сервера. В нашей конфигурации это будет тот сервер, который сейчас VRRP-мастер.
Зайдите на этот сервер и убедитесь, что в файле /var/run/keepalived.INSTANCE.VI_1.state в последней строке указано MASTER.
Перезапустите на мастере сервис keepalived. Если у вас все сделано правильно, то мастер поменяется. На 1-м сервере в файле keepalived.INSTANCE.VI_1.state появятся строки STOP и BACKUP, на втором сервере в этом же файле появится строка MASTER, а клиентский скрипт станет выдавать ресурсную запись с идентификатором нового мастера.
[2020-10-13T10:48:00+00:00] /etc/keepalived/keepalived-notify.sh INSTANCE VI_1 BACKUP 100 [2020-10-13T11:26:29+00:00] /etc/keepalived/keepalived-notify.sh INSTANCE VI_1 MASTER 100
"=nameserver-1=" "=nameserver-1=" "=nameserver-1=" "=nameserver-2=" "=nameserver-2 spoiler" role="button" tabindex="0"> /etc/keepalived/keepalived.conf global_defs < enable_script_security >vrrp_instance VI_1 < state BACKUP interface eth0 virtual_router_id 5 priority 100 advert_int 1 nopreempt notify /etc/keepalived/keepalived-notify.sh root authentication < auth_type PASS auth_pass KPSjXfRG >virtual_ipaddress < 10.2.1.5 >> virtual_server 10.2.1.5 53 < protocol UDP delay_loop 10 lvs_sched rr lvs_method NAT real_server 10.2.1.2 53 < DNS_CHECK < type txt name health.load.balance >> real_server 10.2.1.3 53 < DNS_CHECK < type txt name health.load.balance >> > virtual_server 10.2.1.5 53 < protocol TCP delay_loop 10 lvs_sched rr lvs_method NAT real_server 10.2.1.2 53 < TCP_CHECK < connect_timeout 3 >> real_server 10.2.1.3 53 < TCP_CHECK < connect_timeout 3 >> >
Начало конфигурации аналогично предыдущему варианту без балансировки, только из блока vrrp_instance исчез track_script, соответственно за ненадобностью был удален блок vrrp_script.
Главное отличие в новой конфигурации заключается в блоках virtual_server. Для DNS требуется 2 виртуальных сервера, для 53-го порта TCP и для 53-го порта UDP. В случае HTTP-сервера аналогично потребуются сервера для 80-го и 443-го портов TCP.
Каждый виртуальный сервер идентифицируется 3 значениями: IP, порт и протокол. IP и порт через пробел указываются в заголовке блока virtual_server, а протокол определяется параметром protocol внутри блока. Допустимые протоколы TCP и UDP. В случае DNS как раз нужны оба.
Параметр delay_loop задает периодичность, с которой балансировщик опрашивает бэкенды для определения их состояния.
Самые важные параметры в виртуальном сервере — это lvs_sched и lvs_method. lvs_sched задает алгоритм, по которому балансировщик определяет, куда отправить очередной IP-пакет. lvs_method задает механизм, который использует балансировщик для направления пакетов в выбранный пункт назначения.
В приведенном примере lvs_sched равен rr, что означает round robin, т. е. балансировка равномерно по очереди. lvs_method используется NAT. Кроме NAT доступны также механизмы DR (direct routing) и TUN (tunneling). На мой взгляд, NAT — единственный рабочий вариант. Остальные методы работают только в очень специфических условиях.
Каждый виртуальный сервер состоит из нескольких реальных серверов, что отражено в соответствующих вложенных блоках real_server. Внутри блока real_server надо описать способ опроса его состояния, т. е. healthcheck.
После такой настройки keepalived работает следующим образом:
- Принимает IP-пакет с адресом получателя равным VIP.
- Выбирает real_server, куда необходимо направить пакет, анализируя протокол, порт, lvs_sched и результаты healthcheck-ов.
- Заменяет в IP-пакете адрес получателя на IP-адрес выбранного реального сервера и отправляет его дальше.
Только для работы этого недостаточно. Выбранный реальный сервер отправит ответный IP-пакет, в котором адрес отправителя будет равен его собственному IP-адресу. Клиент дропнет такой пакет, потому что он отправлял запрос на VIP и ожидает ответы от VIP, а не с IP-адреса реального сервера.
Чтобы решить эту проблему, нужно заставить реальный сервер отправить ответ не на IP клиента, а на IP мастера, чтобы тот выполнил обратную подстановку реального IP на виртуальный.
Для этого понадобится itpables и некоторые настройки ядра.
dnf -y install iptables iptables-services systemctl enable iptables systemctl start iptables
echo "net.ipv4.ip_forward=1" >>/etc/sysctl.d/99-sysctl.conf echo "net.ipv4.vs.conntrack=1" >>/etc/sysctl.d/99-sysctl.conf sysctl -w net.ipv4.ip_forward=1 sysctl -w net.ipv4.vs.conntrack=1
Добавьте в iptables следующее правило:
iptables -t nat -I POSTROUTING 1 -d 10.2.1.0/24 -j SNAT --to-source 10.2.1.5 service iptables save
Действие SNAT означает, что после маршрутизации в IP-пакете IP-адрес источника будет заменен на IP-адрес to-source. Вместо SNAT можно также использовать действие MASQUERADE, которое делает то же самое, только определяет исходящий IP автоматически.
Поскольку были внесены изменения в такие вещи как iptables и параметры ядра, рекомендуется перезагрузить сервер и убедиться, что ничего из этого не потерялось.
Выполните описанные действия на обоих серверах кластера. Проверьте логи и статусные файлы. Если ошибок нет, то выполните проверку работы кластера способом, описанным выше. Теперь должен получиться вот такой вывод:
"=nameserver-1=" "=nameserver-2=" "=nameserver-1=" "=nameserver-2=" "=nameserver-1 plaintext">"=nameserver-1=" "=nameserver-1=" "=nameserver-1=" "=nameserver-1=" "=nameserver-1 scrollable-table"> Параметр Возможное значение Описание vip 10.2.1.5 виртуальный IP, на который шлют запросы клиенты dev0 eth0 1-й сетевой интерфейс на узлах кластера dev1 eth1 2-й сетевой интерфейс на узлах кластера ip01 10.2.1.2 IP 1-го узла кластера на 1-м сетевом интерфейсе ip02 10.2.1.3 IP 2-го узла кластера на 1-м сетевом интерфейсе ip11 10.2.1.6 IP 1-го узла кластера на 2-м сетевом интерфейсе ip12 10.2.1.7 IP 2-го узла кластера на 2-м сетевом интерфейсе net0 10.2.1.0/24 подсеть, которой принадлежат ip01 и ip02