Развёртывание отказоустойчивого веб-кластера на базе keepalived и nginx

Проблема

Одиночный сервер, на котором работают nginx и ваше веб-приложение, неизбежно становится точкой отказа. Выход из строя аппаратного обеспечения, сбой питания, плановое обслуживание или даже кратковременная потеря сетевой связности приводят к тому, что пользователи теряют доступ к сервису. В небольших проектах, где ещё нет полноценного облачного балансировщика, администраторы часто мирятся с простоями, хотя добавить высокую доступность можно буквально за час. Keepalived в связке с nginx позволяет организовать отказоустойчивый кластер из двух и более узлов, где один сервер активно обрабатывает запросы, а второй находится в горячем резерве и автоматически подхватывает трафик при сбое основного. При этом клиентам не нужно менять IP-адрес: виртуальный IP (VIP) всегда остаётся одним и тем же.

Решение

Мы построим классическую схему Active-Passive с двумя узлами. На обоих серверах будет установлен nginx, обслуживающий один и тот же набор сайтов. Keepalived управляет виртуальным IP-адресом: пока мастер-узел жив, VIP висит на нём; как только мастер перестаёт отвечать, VIP моментально мигрирует на резервный узел. Механизм базируется на протоколе VRRP (Virtual Router Redundancy Protocol), описанном в RFC 3768 и реализованном демоном keepalived, чья документация доступна на официальном сайте. В качестве health-проверки будем использовать vrrp_script, который следит за состоянием nginx: если веб-сервер упал, мастер добровольно отдаёт VIP резервному узлу, чтобы тот начал отвечать на запросы, пока проблема не будет устранена.

Пошаговая инструкция

Шаг 1. Подготовка двух серверов и настройка сети

Понадобятся два сервера с Linux (Debian/Ubuntu или RHEL-подобные). Оба должны находиться в одном L2-сегменте (одна подсеть), так как VRRP использует multicast 224.0.0.18. Пример конфигурации:

  • Узел 1 (master): IP 192.168.1.10
  • Узел 2 (backup): IP 192.168.1.11
  • Виртуальный IP (VIP): 192.168.1.100

Убедитесь, что сетевые интерфейсы сконфигурированы статически и оба сервера могут пинговать друг друга.

Шаг 2. Установка nginx на оба сервера

На обоих узлах выполните:

bash

sudo apt update && sudo apt install nginx -y   # Debian/Ubuntu
# sudo dnf install nginx -y                    # RHEL/Rocky Linux

Для теста замените содержимое стандартного index.html на что-то, указывающее на конкретный сервер:

bash

echo "Server 1" | sudo tee /var/www/html/index.html   # на первом
echo "Server 2" | sudo tee /var/www/html/index.html   # на втором

Проверьте, что nginx отвечает локально: curl localhost.

Шаг 3. Установка keepalived

На обоих серверах установите пакет keepalived. Он доступен в стандартных репозиториях:

bash

sudo apt install keepalived -y

После установки демон запустится и будет читать конфигурацию из /etc/keepalived/keepalived.conf.

Шаг 4. Настройка keepalived на мастере (Узел 1)

Создайте конфигурационный файл /etc/keepalived/keepalived.conf:

bash

sudo nano /etc/keepalived/keepalived.conf

Содержимое для мастер-узла:

nginx

global_defs {
    router_id SRV1
}

# Скрипт проверки, жив ли nginx
vrrp_script chk_nginx {
    script "killall -0 nginx"      # возвращает 0, если процесс существует
    interval 2                     # интервал проверки, секунды
    weight -2                      # сколько вычесть из приоритета при провале
}

vrrp_instance VI_1 {
    state MASTER                   # начальное состояние
    interface eth0                 # замените на ваш интерфейс (ip a)
    virtual_router_id 51           # уникальный ID (1-255), должен совпадать на обоих узлах
    priority 100                   # приоритет (на мастере выше)
    advert_int 1                   # интервал анонсов VRRP, секунды

    authentication {
        auth_type PASS
        auth_pass secret123        # общий пароль (только первые 8 символов значимы)
    }

    virtual_ipaddress {
        192.168.1.100/24           # виртуальный IP
    }

    track_script {
        chk_nginx                  # отслеживаем состояние nginx
    }
}

Пояснения:

  • router_id — произвольное имя, полезно для логов.
  • vrrp_script chk_nginx каждые 2 секунды запускает killall -0 nginx. Если процесс не найден, скрипт возвращает ненулевой код, и приоритет мастера снижается на 2 (weight -2). В результате приоритет становится 98, что ниже, чем у резервного узла (приоритет 99), и VIP переезжает.
  • auth_pass secret123 — пароль для VRRP-аутентификации; должен совпадать на обоих узлах. Хотя VRRP-аутентификация не является надёжным шифрованием, она защищает от случайного появления в сети другого VRRP-роутера.

Шаг 5. Настройка keepalived на резервном узле (Узел 2)

Файл /etc/keepalived/keepalived.conf на втором сервере:

nginx

global_defs {
    router_id SRV2
}

vrrp_script chk_nginx {
    script "killall -0 nginx"
    interval 2
    weight -2
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 99
    advert_int 1

    authentication {
        auth_type PASS
        auth_pass secret123
    }

    virtual_ipaddress {
        192.168.1.100/24
    }

    track_script {
        chk_nginx
    }
}

Отличия: state BACKUPpriority 99router_id SRV2. Всё остальное идентично.

Шаг 6. Запуск и проверка кластера

На обоих серверах перезапустите службу keepalived и убедитесь, что она активна:

bash

sudo systemctl restart keepalived
sudo systemctl status keepalived

Проверьте, что на мастер-узле VIP появился на интерфейсе:

bash

ip addr show eth0 | grep 192.168.1.100

Выполните тестовый HTTP-запрос на VIP:

bash

curl http://192.168.1.100

Вы должны увидеть «Server 1».

Теперь сымитируем отказ nginx на мастере:

bash

sudo systemctl stop nginx

Через несколько секунд VIP должен мигрировать на резервный узел. Повторите curl http://192.168.1.100 — теперь ответом должно быть «Server 2». Запустите nginx снова (sudo systemctl start nginx). VIP вернётся на мастер, так как его приоритет снова станет выше.

Шаг 7. Мониторинг и логи

Логи keepalived записываются в системный журнал. Просматривайте их для диагностики:

bash

sudo journalctl -u keepalived -f

При переключении вы увидите сообщения о смене состояния (MASTER/BACKUP) и причине (например, снижение приоритета из-за провала скрипта проверки).

Для более детального мониторинга можно настроить оповещения через почту или скрипты, используя директивы notify_masternotify_backupnotify_fault в конфигурации VRRP-инстанса.

Устранение распространённых проблем

СимптомВероятная причинаРешение
VIP не появляется ни на одном узле, в логах «Keepalived started» и тишинаРазные virtual_router_id на узлах, multicast заблокирован firewall или интерфейсы в разных VLANПроверьте, что ID совпадают. Убедитесь, что firewall разрешает протокол VRRP (IP protocol 112). Временно отключите брандмауэр для теста: sudo ufw disable.
VIP одновременно висит на обоих узлах (split-brain)Потеря связи между узлами (сетевой разрыв), multicast не доходитПроверьте связность ping 192.168.1.11 с первого узла и наоборот. Убедитесь, что switch не блокирует multicast. Добавьте опцию garp_master_delay 5 в vrrp_instance для задержки Gratuitous ARP.
При остановке nginx VIP не уходит с мастераСкрипт killall -0 nginx не работает или track_script не настроенПроверьте скрипт вручную: killall -0 nginx; echo $?. Убедитесь, что пакет psmisc установлен (для killall). Добавьте логирование в скрипт: echo "nginx is dead" >> /tmp/vrrp.log.
VIP возвращается на мастер слишком быстро после восстановления nginxНизкий advert_int или отсутствие задержкиУвеличьте advert_int до 2-3 секунд и добавьте preempt_delay 60 в инстанс, чтобы мастер ждал минуту перед возвратом VIP.
Keepalived не запускается, ошибка «Configuration file error»Синтаксическая ошибка в keepalived.confПроверьте конфигурацию командой sudo keepalived -t. Логи укажут на строку с ошибкой.

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

Menu