· 16 мин чтения

HAProxy + Keepalived: отказоустойчивый балансировщик нагрузки для корпоративных сервисов

HAProxy + Keepalived: отказоустойчивый балансировщик нагрузки для корпоративных сервисов

Привет! Меня зовут Евгений Сергеевич Семёнов, и я директор ITFresh. Если спросите меня про любимый инструмент для балансировки нагрузки, то это, бесспорно, HAProxy! Он удивительно лёгок, буквально летает, а документация к нему — просто песня. При этом HAProxy спокойно выдерживает десятки тысяч соединений даже на совсем скромном оборудовании. Но есть одна загвоздка, которая не даёт мне покоя: сам HAProxy, как ни крути, может стать той самой единственной точкой отказа. Представьте: если он вдруг «упадёт», всё, что за ним, тоже перестанет работать. Именно поэтому в боевом окружении я ни за что не рискну поставить один-единственный HAProxy. Всегда, слышите, всегда использую его только в паре с Keepalived. И вот тут-то я и покажу вам весь наш процесс: от установки до того, как система молниеносно переключится всего за 3 секунды, если активный узел вдруг решит взять отпуск.

Задача и архитектура

Представьте себе такую ситуацию: у нас есть три веб-сервера, на каждом из которых работают Nginx и 1С веб-клиент. В пиковые часы трафик взлетает до 500 запросов в секунду. Нам нужен один, единственный HTTPS-адрес для входа — пусть будет 10.10.10.100. Что здесь самое критичное? Во-первых, если вдруг один из веб-серверов «ляжет», весь трафик обязан моментально переключиться на живые. Во-вторых, а если «упадёт» сам балансировщик? Его дублёр должен подхватить виртуальный IP в считанные секунды. И, пожалуй, самое главное условие: никаких, абсолютно никаких разрывов пользовательских сессий!

Архитектура:

Для балансировщиков мы обычно выбираем довольно скромные виртуальные машины. Например, мне вполне хватает 2 vCPU, 2 ГБ оперативной памяти и 20 ГБ диска. И, конечно же, старый добрый Debian 12. По нашему опыту, HAProxy на таком железе легко справляется с нагрузкой в 20-30 тысяч запросов в секунду. Просто без каких-либо видимых проблем!

Установка HAProxy и Keepalived

Что ж, приступим к делу: на обеих наших виртуалках первым делом устанавливаем необходимые пакеты. Берём их, конечно, прямо из официального репозитория Debian. Я всегда стараюсь использовать HAProxy 2.8 LTS, забирая его из backports. Почему именно эта версия? Да просто потому, что она, на мой взгляд, предлагает лучшую поддержку HTTP/2 и TLS 1.3.

# На lb01 и lb02
sudo apt update
sudo apt install -y haproxy keepalived

# Включаем forwarding и non-local bind (нужно для VIP)
cat << EOF | sudo tee /etc/sysctl.d/99-haproxy.conf
net.ipv4.ip_nonlocal_bind = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system

Параметр ip_nonlocal_bind позволяет HAProxy слушать VIP даже на пассивной ноде — иначе бэкап-нода при поднятии адреса не сможет принять соединения.

Конфиг HAProxy

Конфигурация у нас абсолютно идентичная на обеих нодах. Чтобы избежать расхождений, мы всегда синхронизируем её через rsync. Обычно это происходит прямо из нашего git-репозитория в процессе деплоя — так надёжнее.

# /etc/haproxy/haproxy.cfg
global
    log /dev/log local0
    log /dev/log local1 notice
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin
    stats timeout 30s
    user haproxy
    group haproxy
    daemon
    maxconn 20000
    ssl-default-bind-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
    ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11

defaults
    log global
    mode http
    option httplog
    option dontlognull
    timeout connect 5s
    timeout client 30s
    timeout server 30s
    retries 3

frontend web_https
    bind *:80
    bind *:443 ssl crt /etc/haproxy/certs/portal.corp.ru.pem alpn h2,http/1.1
    http-request redirect scheme https unless { ssl_fc }
    http-request set-header X-Forwarded-Proto https
    default_backend web_pool

backend web_pool
    balance leastconn
    cookie SRVID insert indirect nocache
    option httpchk GET /health HTTP/1.1\r\nHost:\ portal.corp.ru
    http-check expect status 200
    server web01 10.10.10.201:443 check ssl verify none cookie w1
    server web02 10.10.10.202:443 check ssl verify none cookie w2
    server web03 10.10.10.203:443 check ssl verify none cookie w3

listen stats
    bind 127.0.0.1:9000
    stats enable
    stats uri /
    stats refresh 5s
    stats admin if TRUE

Есть несколько ключевых настроек, на которые стоит обратить внимание: * `balance leastconn`: эта директива заставляет HAProxy выбирать бэкенд с наименьшим числом активных соединений. При обработке «тяжёлых» или долгих запросов это куда эффективнее классического `round-robin`. * `Cookie SRVID`: обеспечивает так называемые «sticky sessions». Благодаря этой настройке клиент всегда привязывается к одному и тому же бэкенду через специальную cookie. * `Option httpchk` с `HTTP 1.1`: позволяет нам проверять, живы ли наши бэкенды. Проверка происходит каждые две секунды — так мы уверены, что трафик всегда идёт на рабочие серверы.

Конфиг Keepalived на MASTER

Так что же такое Keepalived? Если говорить просто, это VRRP-демон, его задача — следить за тем, чтобы виртуальный IP (VIP) всегда был назначен кому-то из узлов. Интересно, что конфигурация на наших `lb01` и `lb02` практически идентична. Главное отличие — их роли и, конечно, приоритеты.

# /etc/keepalived/keepalived.conf на lb01 (MASTER)
global_defs {
    router_id LB01
    script_user root
    enable_script_security
}

vrrp_script chk_haproxy {
    script "/usr/bin/killall -0 haproxy"
    interval 2
    weight 2
    fall 2
    rise 2
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 150
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass ДлинныйПароль17Знаков!
    }
    virtual_ipaddress {
        10.10.10.100/24 dev eth0
    }
    track_script {
        chk_haproxy
    }
    notify_master "/etc/keepalived/notify.sh MASTER"
    notify_backup "/etc/keepalived/notify.sh BACKUP"
    notify_fault  "/etc/keepalived/notify.sh FAULT"
}

Конфиг Keepalived на BACKUP

# /etc/keepalived/keepalived.conf на lb02 (BACKUP)
global_defs {
    router_id LB02
    script_user root
    enable_script_security
}

vrrp_script chk_haproxy {
    script "/usr/bin/killall -0 haproxy"
    interval 2
    weight 2
    fall 2
    rise 2
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass ДлинныйПароль17Знаков!
    }
    virtual_ipaddress {
        10.10.10.100/24 dev eth0
    }
    track_script {
        chk_haproxy
    }
}

Основные отличия кроются в двух строчках: на резервном сервере мы указываем `state BACKUP` вместо `MASTER`, а приоритет снижаем до `priority 100` вместо `150`. Вот и всё! Заметьте, всё остальное остаётся идентичным. И это критично, особенно для `virtual_router_id` и `auth_pass` — без них ноды просто не смогут «увидеть» друг друга и начать корректно взаимодействовать.

Скрипт уведомления о переключении

Знаете, когда система переключается между MASTER и BACKUP, я моментально получаю алерт в Telegram. Для меня это не просто уведомление, а очень критичное событие. О таком нужно знать в реальном времени, без каких-либо промедлений, чтобы держать руку на пульсе!

#!/bin/bash
# /etc/keepalived/notify.sh
TYPE=$1
BOT_TOKEN="1234567890:AAA..."
CHAT_ID="-1001234567890"
HOST=$(hostname)
TIME=$(date '+%Y-%m-%d %H:%M:%S')

curl -sSf -X POST "https://api.telegram.org/bot$BOT_TOKEN/sendMessage" \
  -d "chat_id=$CHAT_ID" \
  -d "text=HAProxy VRRP transition: $HOST → $TYPE at $TIME"

logger -t keepalived-notify "Transition to $TYPE"
sudo chmod +x /etc/keepalived/notify.sh
sudo systemctl enable --now keepalived haproxy
ip addr show eth0 | grep 10.10.10.100

Таблица: рекомендации по параметрам

ПараметрЗначениеОбоснование
advert_int1 секБыстрое обнаружение падения, 3 секунды до переключения
priority (MASTER)150Запас 50 пунктов над BACKUP для track_script weight
track_script weight+2 (positive)Если HAProxy жив — даёт бонус к приоритету
fall/rise2/2Не ведёт к флапам от разовых затыков
virtual_router_id1-255Уникальный в пределах L2-домена, иначе конфликт с другим кластером

Проверка отказоустойчивости

После того, как всё запущено, мы обязательно проводим целенаправленное тестирование. И, конечно, делаем это не на production. Лично я всегда прогоняю три основных сценария проверки:

  1. Падение HAProxy на MASTER: sudo systemctl stop haproxy на lb01 → через 4 секунды VIP переезжает на lb02, алерт в Telegram.
  2. Перезагрузка MASTER: sudo reboot на lb01 → VIP переезжает, через 2 минуты lb01 возвращается и забирает VIP обратно (если preemption on).
  3. Падение бэкенда: останавливаем nginx на web02 → HAProxy выводит из пула, трафик идёт на web01/web03 без потерь.

Кейс: HA-балансировщик для медицинской сети

В мае 2026 года к нам обратился клиент — крупная сеть из девяти клиник по Москве и области. У них был единый портал для записи на приём. Проблема в том, что до нас всю нагрузку держал один HAProxy, запущенный на обычной виртуалке. И как вы думаете? Раз в пару месяцев он стабильно «падал» примерно на час, причины были самые разные. Что это означало для бизнеса? Запись в клиники попросту вставала, а пациенты, естественно, не могли попасть к врачу и начинали жаловаться.

Мы быстро развернули пару `lb01`/`lb02` на виртуалках прямо в дата-центре МТС. Настроили Keepalived, присвоив ему виртуальный IP 10.50.0.100. За этим балансировщиком расположились шесть бэкендов, на каждом из которых трудились Nginx и PHP-приложение. Конечно же, мы позаботились о сертификате `portal.clinic.ru`, включили HTTP/2, активировали сжатие `gzip` и настроили кэширование статики прямо на балансировщике. Что же показали первые два месяца работы?

Весь проект обошёлся в 110 000 рублей, и мы уложились всего в три рабочих дня. Это без учёта стоимости самого железа, конечно.

Типичные ошибки

Развернём отказоустойчивый балансировщик под ключ

Настраиваем HAProxy + Keepalived для корпоративных веб-сервисов, 1С веб-клиента, SQL-прокси, почтовых серверов. Пара виртуалок, VIP, health-checks, SSL termination, алерты — за 2-3 рабочих дня.

Телефон: +7 903 729-62-41
Telegram: @ITfresh_Boss
Семёнов Евгений Сергеевич, директор АйТи Фреш

FAQ — частые вопросы по HAProxy и Keepalived

Зачем нужен Keepalived поверх HAProxy?
HAProxy балансирует трафик между бэкендами, но сам становится точкой отказа. Keepalived через VRRP присваивает виртуальный IP активному узлу и автоматически переключает его на резервный при падении.
Что такое VRRP?
Virtual Router Redundancy Protocol — протокол выбора мастера в группе роутеров. Один узел держит виртуальный IP, остальные следят за ним через multicast. Если мастер пропал — выбирается новый по приоритету.
Active-active или active-passive?
Active-passive проще в настройке и диагностике: один узел работает, второй ждёт. Active-active с двумя VIP и round-robin DNS даёт вдвое больше ёмкости, но сложнее в отладке и требует синхронизации сессий.
Нужен ли выделенный vlan для VRRP?
Не обязательно, но желательно. На одном vlan с боевым трафиком VRRP-пакеты могут потеряться при шторме. Я выношу управляющий трафик на отдельный интерфейс или vlan.
Как проверить, что VIP переключился?
На активном узле ip addr show покажет виртуальный IP на интерфейсе. На пассивном — его не будет. journalctl -u keepalived пишет все транзиции MASTER/BACKUP.

Подпишитесь на рассылку ITfresh

Кстати, раз в неделю мы публикуем практические гайды. Они будут полезны руководителям IT и сисадминам: делимся опытом по безопасности, работе с 1С, миграциям, резервному копированию и, конечно, рассказываем о лайфхаках из наших реальных проектов.

Реквизиты оператора персональных данных

ООО «АЙТИ-ФРЕШ», ИНН 7719418495, КПП 771901001. Юридический адрес: 105523, г. Москва, Щёлковское шоссе, д. 92, корп. 7. Контакт: info@itfresh.ru, +7 903 729-62-41. Оператор обрабатывает e-mail подписчика в целях рассылки информационных и рекламных материалов до момента отзыва согласия.