OSEN-НИЙ SAAALEСкидка 50% на виртуальный хостинг и VDS
до 30.11.2025 Подробнее
Выберите продукт

Floating IP для Nginx: keepalived VRRP, healthcheck и быстрый failover

Пошагово строим отказоустойчивый фронтенд на двух серверах Nginx с общим floating IP. Настраиваем keepalived (VRRP), HTTP health check, GARP и sysctl, добиваясь предсказуемого RTO и быстрого failover.
Floating IP для Nginx: keepalived VRRP, healthcheck и быстрый failover

Если вам нужен простой и предсказуемый high availability для фронтенда на Nginx без внедрения массивных балансировщиков, схема с floating IP и keepalived (VRRP) остаётся проверенной классикой. Один адрес «плавает» между двумя (или более) узлами в одной L2-сети: активный сервер обслуживает трафик, резервный мониторит здоровье и, при деградации или падении мастера, за считанные секунды принимает адрес и продолжает работу. В статье соберу практические детали: от ARP/GARP и тонких sysctl до настроек health check и проверки failover без сюрпризов.

Что такое floating IP и зачем он Nginx

Floating IP — это адрес, закреплённый не за «железом», а за сервисом. Он держится на активном узле и переезжает на резервный по сигналу протокола VRRP (реализован в keepalived). Для Nginx это даёт:

  • быстрый и локальный failover без зависимости от внешних DNS TTL;
  • прозрачность для клиентов: одна конечная точка, один IP;
  • простую операционку: два небольших конфига вместо целого зоопарка.

Если всё же рассматриваете DNS-failover, оцените влияние TTL и кешей резолверов: см. тестирование влияния TTL на кеширование DNS. Для практичного старта подойдёт пара узлов на облачном VDS в одном L2-домене.

Архитектура и принцип работы VRRP

VRRP (Virtual Router Redundancy Protocol) назначает роли: мастер анонсирует доступность виртуального IP, бэкап держит руку на пульсе. Состояние синхронизируется VRRP-пакетами (IP protocol 112), по таймингам рассчитывается, когда «мастер считается недоступным». Как только бэкап принимает лидерство, он добавляет VIP на интерфейс и рассылает серию GARP (Gratuitous ARP), чтобы коммутаторы и хосты обновили ARP-кеши и начали слать трафик на новый MAC.

В keepalived вы создаёте vrrp_instance с общим virtual_router_id и пулом virtual_ipaddress. Приоритеты определяют, кто лидер. advert_int задаёт период объявлений. Здоровье мастера отслеживается скриптами vrrp_script (health check): если Nginx не отвечает как ожидается, приоритет понижается, и лидерство переходит к резервному узлу.

Ключ к предсказуемому RTO — не просто отслеживать процесс Nginx, а проверять реальную готовность: открытый сокет и корректный HTTP-ответ нужного сервиса.

Конфигурация keepalived и health-check Nginx на экране админа

Предпосылки и требования к сети

Для стабильной работы необходимо:

  • оба узла в одном L2-домене (одна VLAN), интерфейсы в одинаковой подсети VIP;
  • разрешён протокол 112 (VRRP) на межсетевых экранах;
  • мультикаст VRRP не фильтруется или используется unicast-режим;
  • сетевое оборудование не подавляет GARP, либо есть альтернативы (адресный flush/arping к шлюзу);
  • на серверах согласованы sysctl для ARP и rp_filter.

Сетевые sysctl: ARP, rp_filter и nonlocal bind

Чтобы избежать ARP-флукса и гарантировать корректное поведение VIP, настройте:

  • net.ipv4.ip_nonlocal_bind=1 — позволяет Nginx слушать VIP заранее, даже когда адрес ещё не назначен интерфейсу;
  • net.ipv4.conf.all.arp_ignore=1 и arp_announce=2 — уменьшают вероятность ответов на ARP с «неправильного» интерфейса, стабилизируют ARP;
  • net.ipv4.conf.all.rp_filter=2 (loose) — полезно, если у вас асимметричные маршруты или несколько путей;
  • для IPv6 аналогично следим за ND (Neighbor Discovery), keepalived рассылает не ARP, а unsolicited NA.
# /etc/sysctl.d/99-vip.conf
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
net.ipv4.conf.all.rp_filter=2
net.ipv4.conf.default.rp_filter=2

После изменения не забудьте применить параметры и перезапустить Nginx/keepalived, если это необходимо. Часть настроек (ARP) может влиять на все интерфейсы, поэтому проверяйте влияние на другие сервисы.

Базовая конфигурация keepalived (VRRP + VIP)

Рассмотрим пару узлов: nodeA (приоритет 200) и nodeB (приоритет 100). VIP 203.0.113.10/32 на интерфейсе eth0. В unicast-сценариях обязательно указываем unicast_src_ip и unicast_peer. Если сеть допускает мультикаст VRRP, можно обойтись без peer-списка.

# /etc/keepalived/keepalived.conf
vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 200
    advert_int 1
    preempt_delay 5

    authentication {
        auth_type PASS
        auth_pass s3cret123
    }

    unicast_src_ip 203.0.113.21
    unicast_peer {
        203.0.113.22
    }

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

    garp_master_delay 0
    garp_master_repeat 5
    garp_lower_prio_delay 10

    track_script {
        chk_nginx
    }

    notify_master "/usr/local/sbin/vip-transition.sh master"
    notify_backup "/usr/local/sbin/vip-transition.sh backup"
    notify_fault "/usr/local/sbin/vip-transition.sh fault"
}

vrrp_script chk_nginx {
    script "/usr/local/sbin/check-nginx.sh"
    interval 2
    timeout 1
    fall 2
    rise 2
    weight -50
}

Обратите внимание на weight -50: если чек проваливается, приоритет снижается, что позволяет резервному узлу перехватить VIP. preempt_delay даёт времени «новому мастеру» прогреться (например, открыть сокеты) перед активной эксплуатацией.

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

Health check Nginx: проверяем не процесс, а ответ

Минимально надёжный health check проверяет открытие TCP и получение корректного HTTP-статуса. Например, отдаём 200 OK на локальном http://127.0.0.1/health и удостоверяемся, что это действительно Nginx, а не «фантом» от systemd socket activation или чужой процесс.

# /usr/local/sbin/check-nginx.sh
#!/bin/sh
curl -sS -o /dev/null --max-time 1 http://127.0.0.1/health || exit 1
exit 0

На стороне Nginx есть смысл держать отдельный серверный блок только для health:

# /etc/nginx/conf.d/health.conf
server {
    listen 127.0.0.1:80 reuseport;
    server_name localhost;
    location = /health {
        add_header X-Health ok;
        return 200 "ok\n";
    }
}

Такой чек дешёв по ресурсам, не зависит от внешней сети, и отражает реальную готовность воркеров Nginx. Если вы используете reverse proxy к бэкендам, можно усложнить проверку и сходить до апстрима (но аккуратно с нагрузкой и таймаутами).

Настройка Nginx для VIP: bind и тайминги

Чтобы Nginx был готов «принять» VIP сразу после перехода, обычно достаточно слушать все адреса (0.0.0.0) или явно прописать VIP и включить ip_nonlocal_bind. На высоконагруженных серверах полезны reuseport и аккуратные таймауты, чтобы уменьшить количество полуброшенных коннектов при переключении.

# /etc/nginx/conf.d/site.conf
server {
    listen 203.0.113.10:80 reuseport backlog=4096;
    server_name example.test;
    location / { proxy_pass http://app_upstream; }
}

server {
    listen 203.0.113.10:443 ssl http2 reuseport backlog=4096;
    server_name example.test;
    ssl_certificate /etc/ssl/live/fullchain.pem;
    ssl_certificate_key /etc/ssl/live/privkey.pem;
    location / { proxy_pass https://app_upstream; }
}

Во многих случаях проще оставить listen 80 и listen 443 ssl без привязки к VIP, а перевязку адреса на интерфейс обеспечит keepalived. Главное — nonlocal bind, чтобы nginx стартовал на резерве и сразу прошёл health check. Если требуется публичный HTTPS, заранее подготовьте и установите сертификат — подойдут SSL-сертификаты.

GARP и обновление ARP-кешей

После перехода VIP на новый узел важно быстро «переубедить» соседей, что MAC-адрес изменился. Keepalived умеет рассылать GARP сериями. Если в вашей сети GARP ограничен, применяйте дополнительный скрипт в notify_master: можно вызвать arping к gateway и broadcast, а также выполнить точечный flush соседей на локальном хосте.

# /usr/local/sbin/vip-transition.sh
#!/bin/sh
state="$1"
VIP="203.0.113.10"
IFACE="eth0"

logger -t vip "state=$state"
if [ "$state" = "master" ]; then
    ip neigh flush dev "$IFACE"
    arping -c 3 -A -I "$IFACE" "$VIP"
    arping -c 3 -U -I "$IFACE" "$VIP"
fi

Параметры -A и -U дают две формы gratuitous ARP, что повышает шансы на быстрое обновление таблиц у разных вендоров сетевого оборудования.

Тайминги failover: advert_int, мастер-даун и preempt

Время переключения складывается из нескольких частей: timeout VRRP, исполнение health check, назначение VIP, GARP/NA-обновление и время восстановления коннектов у клиентов. При advert_int 1 и fall 2 вполне реально держать RTO в районе нескольких секунд, не создавая избыточных ложных срабатываний.

preempt и preempt_delay контролируют возврат лидерства исходному мастеру. Если приоритеты фиксированы, мастер после восстановления «отберёт» VIP обратно. Многие предпочитают no-preempt поведение для стабильности: если резерв стал мастером, пусть работает до следующего планового окна. В keepalived это настраивается через nopreempt в vrrp_instance или через баланс веса скриптов.

IPv6: VIP и Neighbor Discovery

Для IPv6 вместо ARP используется ND. Keepalived сам разошлёт unsolicited Neighbor Advertisement. В конфиг добавляется блок virtual_ipaddress с адресом вида 2001:db8::10/128. Проверяйте, что сеть допускает эти объявления и не режет ICMPv6. Аналогично IPv4, держите health check локальным и быстрым.

Firewall и протокол 112

Если вы используете nftables/iptables, откройте VRRP (proto 112) между узлами. Также убедитесь, что политики не мешают GARP/NA. Типичные проблемы: stateful-фильтры вообще не видят «не-UDP/TCP» и дропают по умолчанию, либо на портах включена защита от spoofing, которая отвергает gratuitous объявления.

Тест-план failover: что и как проверять

  • Базовая смена ролей: остановите keepalived на мастере и убедитесь, что VIP появился на резерве. Проверьте ping VIP, curl http://VIP, логи.
  • Падение только Nginx: остановите Nginx на мастере, убедитесь, что vrrp_script снижает приоритет и происходит переключение.
  • Сбой линка: отключите интерфейс у мастера, проверьте срабатывание по отсутствию VRRP-анонсов.
  • Возврат мастера: проверьте политику preempt и что повторный переход не ломает активные клиенты (оцените процент RST и повторных TLS handshakes).
  • GARP-эффект: измерьте время от смены мастера до появления корректного next hop у клиентов. Если медленно — увеличьте повтор GARP, добавьте arping.

Тест-план failover: тайминги VRRP и рассылка GARP

Надёжные health checks: несколько сигналов

Один HTTP-чек — хорошо, но ещё лучше дополнить его наблюдением за системным сервисом и сетью. Keepalived позволяет комбинировать несколько vrrp_script с разными весами: падение интерфейса, ошибки на диске, исчерпание воркеров.

vrrp_script svc_systemd {
    script "/bin/systemctl is-active --quiet nginx"
    interval 2
    fall 1
    rise 1
    weight -20
}

vrrp_script iface_link {
    script "/usr/bin/test -d /sys/class/net/eth0 && /usr/bin/cat /sys/class/net/eth0/operstate | grep -q up"
    interval 1
    fall 1
    rise 1
    weight -30
}

Так вы снижаете шанс «ложного мастера», который вроде как отвечает по HTTP, но фактически потерял линк или ушёл в деградацию.

Особые случаи: контейнеры, облака и L2-ограничения

В контейнеризированных раскладках VRRP-пакеты могут не выходить за пределы namespace, а ARP может работать нетипично. Старайтесь запускать keepalived в host-сети и привязывать VIP к физическому интерфейсу. В облачных средах часто требуется включить «разрешённые адресные пары» для VIP, иначе гипервизор будет отбрасывать кадры с «неожиданным» исходным MAC/IP. Некоторые провайдеры предлагают свой механизм «плавающих адресов» — интеграция с ним надёжнее, чем ручной GARP.

Производительность и пользовательский опыт при переключении

Даже при быстром failover неизбежны обрывы части долгоживущих TCP-сессий. Чтобы сгладить эффект:

  • умеренные keepalive_timeout в Nginx;
  • разумные proxy_read_timeout и send_timeout на бэкенды;
  • ограничение очередей SYN, достаточные backlog и reuseport;
  • для TLS — корректная сессия резюмирования, чтобы повторное рукопожатие было быстрее.
FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

Если нужна липкость сессий, она не обеспечивается VRRP: придётся решать на уровне приложения, куки или распределённого хранилища сессий.

Наблюдаемость и тревоги

Включите подробные логи keepalived, метрики по состоянию VRRP-инстансов и тайминги health checks. Полезно собирать события переходов (notify-скрипт пишет в системный журнал) и строить графы времени до восстановления. Также контролируйте ARP-кеш на граничном маршрутизаторе: слишком долгий удерживающий таймер увеличит время недоступности после переключения.

Проверочный чеклист внедрения

  • Уточнить L2-возможности: VRRP (proto 112), мультикаст, GARP/NA, ограничения безопасности.
  • Согласовать sysctl: ip_nonlocal_bind, arp_ignore, arp_announce, rp_filter.
  • Установить keepalived, подготовить vrrp_instance и health checks.
  • Настроить Nginx: слушатели под VIP или 0.0.0.0, быстрый /health, таймауты.
  • Прописать notify-скрипт для GARP и логирования переходов.
  • Открыть firewall для VRRP и убедиться в отсутствии фильтрации GARP.
  • Провести тест-план: падение процесса, сети, сервера; замерить RTO и донастроить тайминги.

Пример полной связки: два узла, один VIP

Ниже — консолидированный пример, который можно взять за основу и адаптировать под свою сеть и требования. Обязательно замените адреса, интерфейсы, секреты, а тайминги подгоните под SLA.

# sysctl (общий для обоих узлов)
net.ipv4.ip_nonlocal_bind=1
net.ipv4.conf.all.arp_ignore=1
net.ipv4.conf.all.arp_announce=2
net.ipv4.conf.all.rp_filter=2

# keepalived (на мастере — priority 200, на бэкап — 100)
vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 200
    advert_int 1
    nopreempt

    authentication {
        auth_type PASS
        auth_pass s3cret123
    }

    unicast_src_ip 203.0.113.21
    unicast_peer { 203.0.113.22 }

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

    garp_master_repeat 5
    garp_lower_prio_delay 10

    track_script {
        chk_nginx
        svc_systemd
        iface_link
    }

    notify_master "/usr/local/sbin/vip-transition.sh master"
    notify_backup "/usr/local/sbin/vip-transition.sh backup"
    notify_fault "/usr/local/sbin/vip-transition.sh fault"
}

С таким набором у вас есть чёткие сигналы деградации, аккуратный переход и управляемое время недоступности. Дальше можно усложнять: несколько VIP, разделение по портам/протоколам, отдельные инстансы под IPv6. Если раскатываете на новых серверах — начните с пары на VDS, это сократит время запуска.

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

  • Долгое восстановление после переключения. Проверьте GARP: увеличьте garp_master_repeat, добавьте arping в notify-скрипт. Измерьте ARP timeouts на uplink.
  • VRRP-пакеты дропаются. Убедитесь, что firewall пропускает IP protocol 112. В unicast-режиме проверьте правильность unicast_src_ip и unicast_peer.
  • Ложный мастер. Увеличьте строгость health check и добавьте проверки линка/сервиса. Используйте отрицательные веса для приоритета.
  • Nginx не стартует на резерве. Включите ip_nonlocal_bind или слушайте 0.0.0.0 вместо VIP.
  • Сеть облака запрещает GARP. Используйте встроенные механизмы провайдера для плавающих IP или настраивайте «разрешённые адресные пары».

Заключение

Связка keepalived (VRRP) + Nginx с floating IP остаётся одним из самых понятных и экономичных способов дать фронтенду высокую доступность. Потратьте время на корректный health check, аккуратные sysctl и надёжное оповещение соседей через GARP — и вы получите предсказуемый failover без сложных внешних зависимостей. Для масштабирования горизонтально вы всегда сможете добавить ещё один уровень балансировки, но начать стоит именно с этого простого и хорошо контролируемого кирпичика.

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

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

DMARC: rua, p=quarantine и p=reject — как включить без потери доставляемости OpenAI Статья написана AI (GPT 5)

DMARC: rua, p=quarantine и p=reject — как включить без потери доставляемости

Пошаговое руководство для админов: что такое DMARC и агрегированные отчёты rua, как правильно оформить rua=mailto, собрать XML-отч ...
SYNPROXY в nftables: защита VDS от TCP SYN flood пошагово OpenAI Статья написана AI (GPT 5)

SYNPROXY в nftables: защита VDS от TCP SYN flood пошагово

SYN flood забивает TCP-очереди и conntrack на VDS, съедая CPU. SYNPROXY в nftables отсекает мусор до TCP-стека. Разбираем принцип, ...
S3 Select для CSV и JSON: быстрые выборки прямо в Object Storage OpenAI Статья написана AI (GPT 5)

S3 Select для CSV и JSON: быстрые выборки прямо в Object Storage

S3 Select позволяет выполнять SQL-запросы к объектам и возвращать только нужные строки и поля без скачивания всего файла. Разберём ...