Пример использования keepalived на Linux
Используемые термины: Keepalived, Linux.
Мы рассмотрим пошаговую процедуру установки keepalived и настройки кластера Master - Slave с плавающим IP-адресом (VIP — virtual ip). Проверку работоспособности сервиса будем выполнять на примере с веб-сервером NGINX.
Также мы не будем привязываться к конкретному дистрибутиву Linux, учитывая разные варианты.
Настройка сетевого экрана
Установка keepalived
Конфигурирование кластара
Настройка действия при смене состояния
Настройка безопасности
Для корректной работы кластера нужно предусмотреть некоторые настройки безопасности системы.
Брандмауэр
Keepalived для обеспечения высокой доступности использует протокол VRRP. Для его работы фаервол должен пропускать трафик для протокола vrrt на широковещательный адрес 224.0.0.18.
В зависимости от утилиты управления брандмауэром наши действия будут отличаться.
а) Для iptables (как правило, в системах на основе deb):
iptables -I INPUT -p vrrp -d 224.0.0.18 -j ACCEPT
Чтобы сохранить правила, можно использовать iptables-persistent:
apt install iptables-persistent
netfilter-persistent save
б) Для firewalld (как правило, в системах на основе rpm):
firewall-cmd --permanent --add-rich-rule='rule protocol value="vrrp" accept'
firewall-cmd --reload
SELinux
Для систем, где используется SELinux (по умолчанию, в RPM) мы можем столкнуться с проблемами запуска скриптов notify.
Иногда, администраторы предпочитают просто отключать SELinux. Для этого нужно ввести несколько команд:
setenforce 0
sed -i 's/^SELINUX=.*/SELINUX=disabled/g' /etc/selinux/config
* первая команда отключит SELinux для текущей загрузки, вторая — для последующих. Подробнее в инструкции Как отключить SELinux.
Но мы также рассмотрим варианты настройки сервера без отключения SELinux. Об этом будет ниже (в разделе с настройкой notify).
Установка
В популярных дистрибутивах Linux keepalived включен в официальный репозиторий и может быть установлен из него. В зависимости от типа Linux действия будут немного отличаться.
а) Для систем на базе Deb (Debian / Ubuntu / Astra Linux):
apt update
apt install keepalived
б) Для систем на базе RPM (Rocky Linux / РЕД ОС):
yum install keepalived
Настройка кластера
Предположим, что есть два сервера nginx, и нам нужно, чтобы пользователи подключались только к одному из них. Мы настроим кластер с плавающим IP-адресом, который будет добавляться на сетевой интерфейс только для одного из серверов.
Если мы работаем на тестовых серверах, на которых нет nginx, выполняем его установку одной из команд:
apt install nginx
yum install nginx
* первая команда для дистрибутивов deb, вторая — rpm.
Создаем конфигурационный файл.
а) На первом сервере:
vi /etc/keepalived/keepalived.conf
global_defs {
enable_script_security
}
vrrp_script nginx_check {
script "/usr/bin/curl http://127.0.0.1"
interval 5
user nginx
}
vrrp_instance web {
state MASTER
interface eth0
virtual_router_id 254
priority 100
advert_int 2
authentication {
auth_type PASS
auth_pass 12345678
}
virtual_ipaddress {
192.168.0.254
}
track_script {
nginx_check
}
}
б) На втором сервере:
vi /etc/keepalived/keepalived.conf
global_defs {
enable_script_security
}
vrrp_script nginx_check {
script "/usr/bin/curl http://127.0.0.1"
interval 5
user nginx
}
vrrp_instance web {
state BACKUP
interface eth0
virtual_router_id 254
priority 50
advert_int 2
preempt_delay 30
authentication {
auth_type PASS
auth_pass 12345678
}
virtual_ipaddress {
192.168.0.254
}
track_script {
nginx_check
}
}
* оба конфигурационных файла отличаются опцией state. На первом сервере мы задаем ей значение MASTER, предполагая, что он будет основным по умолчанию, второму — BACKUP. Также на втором сервере дополнительна указана директива preempt_delay.
** пройдем по разделам:
- global_defs — задает глобальные настройки. В нашем примере мы разрешаем использование скриптов. В противном случае, keepalived будет возвращать ошибки при использовании скриптов проверки состояния и запуска notify (о нем ниже).
- vrrp_script — описание процесса проверки сервиса. Мы не ограничены в способах — shell-скрипт должен вернуть 0, если все хорошо или другой код ответа, если все плохо. В данном примере мы отправляем запрос на 80 порт, на котором слушает веб-сервер. Если он работает, то команда вернет правильный код ответа. Однако, nginx может слушать на другом порту и это нужно учитывать. Также есть и другие варианты проверки работы nginx, например, команды killall -0 nginx и pidof nginx. Опция interval указывает на периодичность проверки в секундах; опция user задает пользователя. от которого будет выполняться скрипт.
- vrrp_instance — настройки для экземпляра сервиса. В нашем примере мы дали название экземпляру web. Вы можете задать свое.
*** и опишем опции раздела vrrp_instance:
- state — задает начальное состояние ноды. В нашем случае первая MASTER, вторая BACKUP. Важно отметить, что если в конфигурации будет опция nopreempt, возможен только вариант BACKUP.
- interface — название сетевого интерфейса, на который будет добавлен VIP адрес, если сервер станет мастером.
- virtual_router_id — идентификатор VRRP. Может принимать значение от 1 до 255. Должен быть одинаковым для всех узлов, входящих в кластер.
- priority — приоритет узла. Мастером будет назначен сервер с работающим сервисом и самым высоким приоритетом.
- advert_int — время в секундах, с которой мастер должен сообщать о себе другим нодам. Если за данное время он не успеет отправить широковещательный сигнал, начнутся выборы другого мастера.
- preempt_delay — опция позволяет определить поведение мастера при восстановлении сервиса. Задает время в секундах, после которого сервер с более высоким приоритетом заберет обратно себе роль мастера. Стоит отметить, что при наличии опции nopreempt бывшему мастеру не разрешается возвращать свое старое состояние. Опция игнорируется на сервере, где в качестве начального состояния указано MASTER.
- authentication — данный блок описывает опции авторизации. Так как запросы широковещательные, очень важно использовать аутентификацию. В данном примере используется пароль 12345678.
- virtual_ipaddress — блок задает VIP.
- track_script — указываем скрипт, с помощью которого будет проверяться работоспособность сервиса.
Так как для проверки работы сервиса мы используем утилиту curl, убедимся, что она есть в системе, установив ее.
а) Для систем на базе Deb (Debian / Ubuntu / Astra Linux):
apt update
apt install curl
б) Для систем на базе RPM (Rocky Linux / РЕД ОС):
yum install curl
Теперь проверим работу keepalived.
Разрешим автозапуск сервиса и запустим его:
systemctl enable keepalived
systemctl start keepalived
Проверим его состояние командой:
systemctl status keepalived
Теперь командой:
ip a
... мы должны на мастере увидеть дополнительный адрес (в нашем примере 192.168.0.254). Это VIP, назначенный keepalived.
Попробуем на этом же сервере остановить nginx:
systemctl stop nginx
VIP должен оказаться на втором сервере.
Теперь запустим nginx:
systemctl start nginx
Через какое-то время, в соответствии с параметром preempt_delay, VIP вернется.
Автоматизация при смене состояния
Keepalived предусматривает возможность запуска скрипта, который выполняет любые команды при смене состояния с MASTER на BACKUP и наоборот. Рассмотрим подробнее.
В конфигурационные файлы (раздел vrrp_instance) добавим:
vi /etc/keepalived/keepalived.conf
vrrp_instance web {
...
notify /etc/keepalived/notify-web.sh root
}
* при смене состояния должен быть выполнен скрипт /etc/keepalived/notify-web.sh от пользователя root.
Теперь создадим сам скрипт, примерно, такого содержания:
vi /etc/keepalived/notify-web.sh
#!/bin/bash
PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
SCRIPT_NAME=$0
TYPE=$1
INST_NAME=$2
STATE=$3
PRIOR=$4
ALL_ARGS=$@
case $STATE in
"MASTER") echo "[$(date)] MASTER UP with prior ${PRIOR}" >> "/var/log/keepalived/${INST_NAME}.log"
;;
*) echo "[$(date)] change MASTER. I am slave with prior ${PRIOR}" >> "/var/log/keepalived/${INST_NAME}.log"
;;
esac
* в данном примере мы просто добавляем строку в файл лога. Для сервера, который стал мастером и остальными серверами текст немного отличается. Также обратите внимание на аргументы, которые keepalived передаст скрипту:
- $0 — путь до скрипта, который запускает (в нашем примере /etc/keepalived/notify-web.sh).
- $1 — тип vrrp. Может быть GROUP или INSTANCE (как в нашем случае).
- $2 — имя инстанса или группы. У нас это web.
- $3 — состояние. Могут быть MASTER, BACKUP, FAULT, * (любое).
- $4 — приоритет ноды, который указан в конфигурационном файле keepalived.
- $@ — все вышеперечисленные параметры через пробел.
Разрешив запускать скрипт на выполнение:
chmod +x /etc/keepalived/notify-web.sh
В нашем конкретном случае также нужно создать каталог для логов:
mkdir /var/log/keepalived
Перезапустим keepalived:
systemctl restart keepalived
Пробуем поиграть с остановкой и запуском nginx на мастере. Мы должны увидеть изменения в логе.
Работа с SELinux
Как было сказано выше, в работе notify могут быть сбои, если система использует SELinux. Для решения проблемы можно использовать разные способы.
1. Изменить контекст безопасности для скрипта
SELinux сверяет контексты безопасности процессов и файлов с политиками доступа. Например, для запуска на выполнение скриптов, файлу должен быть присвоен контекст keepalived_unconfined_script_exec_t. В нашем примере это можно сделать командой:
semanage fcontext -a -t keepalived_unconfined_script_exec_t /etc/keepalived/notify-web.sh
Это задаст политику назначения контекста. Чтобы его применить также вводим:
restorecon -R -v /etc/keepalived/notify-web.sh
* не забываем поменять /etc/keepalived/notify-web.sh на полный путь к вашему скрипту.
2. Использовать специальный каталог для хранения скриптов
Второй способ может показаться проще. Нужно использовать каталог, для которого уже выставлен контекст keepalived_unconfined_script_exec_t.
Путь до него — /usr/libexec/keepalived. Переносим наш скрипт в него и меняем путь в конфигурационном файле keepalived.