Выберите продукт

Высокая доступность веба на VDS: Nginx + keepalived/VRRP, плавающий IP и health check

Разбираем практическую схему высокой доступности веб-уровня на двух VDS: Nginx + keepalived/VRRP с плавающим IP. Покрываем архитектуру, sysctl-тюнинг, health checks, unicast/multicast, методику тестов, мониторинг и типовые ловушки, чтобы сократить простои до секунд.
Высокая доступность веба на VDS: Nginx + keepalived/VRRP, плавающий IP и health check

Если у вашего проекта простой SPOF на единственном сервере, то апгрейды ядра, кривые обновления или даже «битая» планка RAM мгновенно превращают сайт в «503». В этой статье я соберу рабочий минимум для высокой доступности (high availability, HA) веб-уровня на VDS: два узла с Nginx, один плавающий IP и отказоустойчивость через keepalived/VRRP с проверкой здоровья. Без лишних абстракций — с акцентом на то, что реально спасает в проде.

Зачем VRRP и что даёт плавающий IP

VRRP — протокол выбора «мастера» среди нескольких узлов, у которых общий виртуальный (плавающий) IP. В норме один узел держит IP и отвечает на трафик, второй стоит «в засаде». При сбое мастера backup за секунды перехватывает IP и продолжает обслуживать запросы. Это существенно уменьшает время простоя и позволяет делать обслуживание без полной недоступности.

Важно: VRRP работает на L2-сегменте. Оба узла должны «видеть» один и тот же broadcast-домен, иначе плавающий IP не сможет быстро переезжать с корректной раздачей ARP.

Базовая архитектура

Мы берём два VDS в одной подсети. На обоих установлен Nginx и keepalived. Виртуальный IP (VIP) «плавает» между ними, а внешние DNS-записи на домен указывают именно на VIP (A/AAAA). Если вы настраиваете новый домен — удобно совместить это с регистрация доменов.

Сценарий активный/пассивный: один обслуживает, второй готов перехватить.

Варианты роли Nginx:

  • Reverse proxy перед backend’ами (PHP-FPM, Node.js, Python и т.п.) — наиболее распространённый вариант. State хранится не на прокси, а в БД/Redis.
  • Статический контент (файлы) — синхронизация через rsync/obj-storage; при failover статика остаётся доступной.
  • Терминирование TLS — сертификаты одинаковые на обоих узлах, автоматизация обновления обязательна: используйте надёжные SSL-сертификаты.

Требования и сетевые нюансы

Чтобы VRRP и плавающий IP работали предсказуемо, проверьте:

  • Оба VDS в одной L2-сети. При облачном провайдере это обычно один и тот же сегмент/виртуальный свитч.
  • Multicast для VRRP может быть ограничен. Если мультикаст запрещён, используйте unicast-режим keepalived.
  • ARP-обновление после failover: нужна корректная рассылка gratuitous ARP, чтобы гейтвей и соседи перестроили таблицы.
  • Понимание, что существующие TCP-сессии при переключении сорвутся. HA на L4/L7 без state replication не «мигрирует» активные соединения.

Unicast и multicast VRRP: схема сети и VIP

Подготовка системы

ОС — любая популярная серверная Linux. Примеры далее для Debian/Ubuntu и RHEL-подобных.

# Debian/Ubuntu
sudo apt update
sudo apt install -y nginx keepalived curl jq

# RHEL/Alma/Rocky
sudo dnf install -y nginx keepalived curl jq

Рекомендуемый sysctl-тюнинг для VIP и корректной ARP-семантики (на обоих узлах):

sudo tee /etc/sysctl.d/99-ha-vip.conf > /dev/null << 'EOF'
net.ipv4.ip_nonlocal_bind = 1
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.default.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.default.arp_announce = 2
EOF
sudo sysctl --system

net.ipv4.ip_nonlocal_bind позволяет Nginx слушать адрес даже до прихода VIP (или если VIP временно у соседа), а параметры arp_ignore/arp_announce снижают риск ARP-флукса при перемещении адреса.

Минимальная конфигурация Nginx

Если Nginx — реверс-прокси к вашему backend на 127.0.0.1:9000 или upstream-пулу, хватит базовой конфигурации. Главное — она должна быть одинаковой на обоих узлах и обновляться атомарно.

# /etc/nginx/conf.d/site.conf
server {
    listen 80;
    server_name example.com;

    location /health {
        access_log off;
        return 200 'ok';
    }

    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_pass http://127.0.0.1:9000;
    }
}

Блок /health — это наш локальный health check для keepalived. Он должен отвечать 200 быстро и без внешних зависимостей.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Конфигурация keepalived: VRRP + health check

Это сердце HA. Настроим одну vrrp_instance, VIP в формате /32 и проверку Nginx через vrrp_script. Пример для «левого» узла (Node A):

# /etc/keepalived/keepalived.conf (Node A)
vrrp_script chk_nginx {
    script "/usr/bin/curl -fsS http://127.0.0.1/health >/dev/null || exit 1"
    interval 2
    rise 2
    fall 2
    timeout 2
    weight -20
}

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

    # Используем unicast, если multicast недоступен
    unicast_src_ip 10.0.0.11
    unicast_peer {
        10.0.0.12
    }

    authentication {
        auth_type PASS
        auth_pass s3cr3tPass
    }

    virtual_ipaddress {
        203.0.113.10/32 dev eth0 label eth0:vip
    }

    garp_master_delay 1
    garp_master_repeat 5

    preempt_delay 5
    nopreempt

    track_script {
        chk_nginx
    }
}

Для второго узла (Node B) конфигурация идентична, но с другой исходной unicast_src_ip и меньшим priority, например 150. Поле nopreempt полезно, если не хотите, чтобы первоначальный мастер «отбирал» VIP назад сразу после краткого сбоя второго узла. Если нужна обратная логика, уберите nopreempt и используйте preempt_delay, чтобы избежать «дерганья» VIP.

Опции garp_master_delay и garp_master_repeat помогают агрессивнее разослать gratuitous ARP при переключении — это ускоряет обновление ARP-таблиц соседей и гейтвея.

Заметки по безопасности VRRP

В IPv4 VRRPv2 можно включить простую аутентификацию (auth_type PASS), но это не криптостойкая защита. Основной щит — сетевой периметр и unicast. В IPv6 (VRRPv3) встроенной аутентификации нет: полагайтесь на сегментацию и фильтрацию.

Запуск и проверка

sudo systemctl enable --now nginx
sudo systemctl enable --now keepalived

# Проверяем VIP
ip addr show dev eth0 | grep 203.0.113.10 || echo "VIP не на этом узле"

# Смотрим VRRP-анонсы
sudo tcpdump -ni eth0 ip proto 112 -vv

На одном из узлов вы должны увидеть VIP на интерфейсе. Если нет — читайте логи keepalived и убедитесь, что интерфейс/адреса указаны корректно, а мультикаст/юникаст-достижимость работает.

Failover-тесты: как убедиться, что HA реальное

Проведите серию тестов в непиковое время, но с реальными клиентскими запросами (или генератором нагрузки):

  1. Остановите Nginx на активном узле. Health check на мастере провалится — при достаточном «весе» проверок его приоритет станет ниже, и VIP переедет на backup.
  2. Остановите keepalived на активном узле. VIP должен уехать на backup почти мгновенно.
  3. Перегрузите сеть интерфейса (down/up) — убедитесь, что ARP обновляется корректно, нет «залипания» на маршрутизаторе.
# Примеры
sudo systemctl stop nginx
sleep 5
curl -I http://203.0.113.10/ || echo "Проверка с клиента"

sudo systemctl stop keepalived
sleep 3
ip addr show dev eth0 | grep 203.0.113.10 || echo "VIP ушел на соседа"

Фиксируйте RTO для клиентов: при корректном тюнинге failover занимает секунды. Помните: существующие TCP-сессии разорвутся — это нормально для L7-прокси без state sync.

Тестирование failover и VRRP-анонсы на tcpdump

Продвинутые health checks

Минимальный health check проверяет локальный /health. Но полезно контролировать и жизнеспособность бэкенда или TLS:

  • HTTP к upstream через Nginx: если backend упал, отдавайте 502 на /health и валите проверку.
  • Проверка порта: nc -z 127.0.0.1 80 или ss -lnt как быстрый индикатор.
  • Валидность сертификата: периодическая проверка сроков и перезапуск Nginx при обновлении.
# Пример скрипта более строгой проверки
sudo tee /usr/local/bin/check_nginx.sh > /dev/null << 'EOF'
#!/usr/bin/env bash
set -euo pipefail
# 1) сам Nginx
curl -fsS http://127.0.0.1/health >/dev/null
# 2) один из бэкендов
curl -fsS --max-time 1 http://127.0.0.1/backend-health >/dev/null
exit 0
EOF
sudo chmod +x /usr/local/bin/check_nginx.sh
vrrp_script chk_nginx {
    script "/usr/local/bin/check_nginx.sh"
    interval 2
    rise 2
    fall 2
    timeout 2
    weight -30
}

weight задаёт, насколько «штрафовать» приоритет при провале проверки. Если на мастере проверки провалились, он уступит VIP.

FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

Согласованность конфигураций и деплой

Одинаковые версии и конфиги Nginx на обоих VDS упрощают жизнь. Применяйте атомарный деплой: выкатывайте на пассивный узел, переключайтесь, затем обновляйте второй. Если используете CI/CD, добавляйте шаги синтакс-проверки (nginx -t) и canary-раздачу, чтобы не уронить оба узла единовременно. Для сценариев переноса полезно заглянуть в гайд по миграции без даунтайма.

Sticky-сессии и пользовательский опыт

При простом VRRP-переключении TCP-сессии рвутся, а IP клиента на новом мастере может прийти к другому узлу бэкенда. Для веб-приложений используйте хранение сессий вне «фронтов» (например, в Redis), а не в памяти Nginx/PHP-FPM. Если есть персистентность на уровне балансировщика (cookie, ip_hash), при failover неизбежны кратковременные промахи — их стоит учитывать.

Логи и мониторинг

Мониторьте:

  • Состояние VRRP: логи keepalived, событие смены мастера.
  • Время ответа /health, коды ответа, RPS.
  • Сетевые показатели: дропы пакетов, ошибки на интерфейсе, переполнения conntrack.
  • Использование CPU/IO — чтобы избежать «ложных» флапов от перегруза.

Для расследований полезен tcpdump ip proto 112 и разметка логов момента «переброса» VIP. Сохраняйте таймлайны и связывайте их с алертами.

Типичные проблемы и как их лечить

  • VIP «залип» у соседа: увеличьте garp_master_repeat, проверьте ARP/ND кеши на гейтвее, убедитесь, что VIP действительно добавлен на интерфейс.
  • Failover слишком «шумный»: уберите preempt или добавьте preempt_delay, увеличьте fall/rise у проверок.
  • Мультикаст режется: переходите на unicast-конфиг (unicast_src_ip и unicast_peer).
  • Nginx не стартует до прихода VIP: включён net.ipv4.ip_nonlocal_bind=1? Либо слушайте 0.0.0.0, либо управляйте рестартом через notify-хуки keepalived.
  • Сертификаты не обновляются: автоматизируйте выпуск и раскатку на оба узла, тестируйте nginx -t перед рестартом.

Хуки keepalived для тонкой логики

Keepalived поддерживает скрипты notify_master, notify_backup, notify_fault. Например, можно включать/отключать дополнительный сервис или метрики.

vrrp_instance VI_1 {
    # ... остальной конфиг ...
    notify_master "/usr/local/bin/on_master.sh"
    notify_backup "/usr/local/bin/on_backup.sh"
}

Скрипты должны быть простыми, быстрыми и с явным логированием. Никогда не вешайте на них тяжёлые миграции или долгие блокирующие операции — это ухудшит RTO.

Резервирование уровня хранения

Если Nginx отдаёт статический контент, позаботьтесь о репликации: либо регулярный rsync, либо хранение в объектном хранилище с локальным кэшем. Для пользовательских загрузок — синхронизация по событию, чтобы при переключении контент не «исчезал». Для устойчивости к ЧС держите резервные копии в S3.

План внедрения (чек-лист)

  1. Два VDS в одном L2-сегменте, выделенный VIP.
  2. Установка Nginx и keepalived, настройка sysctl.
  3. Единые конфиги Nginx, маршрут health check.
  4. Конфиг keepalived: VRID, приоритеты, unicast/multicast, VIP, GARP.
  5. Health checks и веса, опционально хуки notify.
  6. Тесты failover: Nginx stop, keepalived stop, link flap.
  7. Мониторинг, алерты, документация runbook’а.

Итоги

Связка Nginx + keepalived/VRRP с плавающим IP — простой и понятный способ получить высокую доступность фронтенда на VDS. Ключ к успеху — дисциплина: единые конфиги, корректные health checks, аккуратный тюнинг ARP и предсказуемая процедура переключения. Так вы сократите простои до секунд и сможете обслуживать систему без страха «уронить прод» при каждом обновлении ядра или прокси.

Поделиться статьей

Вам будет интересно

Debian/Ubuntu: как исправить Device is busy у Docker network, volume и namespace OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как исправить Device is busy у Docker network, volume и namespace

Если Docker на Debian или Ubuntu отвечает Device is busy при удалении сети, тома или namespace, причина обычно в живом процессе, о ...
Debian/Ubuntu: как исправить Host key verification failed в Ansible при смене IP OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как исправить Host key verification failed в Ansible при смене IP

Ошибка Host key verification failed в Ansible на Debian и Ubuntu обычно возникает после переустановки сервера, смены IP или повтор ...
Debian/Ubuntu: duplicate address detected, DAD failed IPv6 — причины и исправление OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: duplicate address detected, DAD failed IPv6 — причины и исправление

Сообщения duplicate address detected и DAD failed в Debian/Ubuntu означают, что IPv6-адрес не прошёл проверку уникальности в локал ...