HAProxy давно стал стандартом де‑факто для балансировки трафика на уровне L4/L7. Он предельно предсказуем, отлично документирован и позволяет строить надежные схемы отказоустойчивости без лишней магии. В этом обзоре соберу базовые, но практичные подходы к конфигурации для HTTP и TCP, разберу health‑checks, типичные ошибки и приемы отладки. Цель — чтобы вы могли быстро поставить HAProxy на VDS, включить мониторинг состояния бэкендов и уверенно вести его в продакшене.
Когда выбирать HAProxy
Сильные стороны HAProxy — стабильность, производительность, гибкий набор проверок работоспособности и прозрачная диагностика. Он одинаково хорошо подходит для:
- L7 HTTP балансировки с ACL, cookie‑стикерингом, заголовками и политиками роутинга.
- L4 TCP балансировки для баз данных, очередей и внутренних сервисов.
- Сценариев, где критична скорость failover и понятные health‑checks.
Если нужен «просто балансировщик, который не подводит» — HAProxy обычно отличный выбор. А когда понадобится сложная логика на уровне HTTP, он не упирается в потолок.
Архитектура и терминология
Минимальный набор сущностей:
- global — общие настройки: логи, тюнинг производительности.
- defaults — таймауты, политики ретраев, стратегии балансировки по умолчанию.
- frontend — точка входа трафика, порты, ACL, маршрутизация на backends.
- backend — список целевых серверов, метод балансировки, health‑checks.
Принцип: клиенты подключаются к frontend; по ACL/правилам запросы уходят в подходящий backend; внутри backend находится пул серверов с проверками доступности.

Базовая установка и подготовка
На распространенных дистрибутивах достаточно установить пакет и включить автозапуск. Для чистоты эксперимента держите конфиг в одном файле, а отдельные сниппеты — в директории include. Журналирование можно вести в системный журнал: так проще анализировать поведение и собирать метрики. Для оперативной диагностики полезно включить административный сокет.
global
log stdout format raw local0
maxconn 20000
daemon
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
Минимальный каркас конфига
Ниже — безопасные дефолты, с которых стоит начинать и постепенно ужесточать под реальную нагрузку.
global
log stdout format raw local0
maxconn 20000
daemon
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 3s
timeout client 30s
timeout server 30s
retries 2
option redispatch
# HTTP входной фронтенд
frontend fe_http
bind :80
# X-Forwarded-For/Proto пригодятся приложению
option forwardfor header X-Forwarded-For
http-request set-header X-Forwarded-Proto http
# Пример ACL и роутинга
acl is_api path_beg -i /api/
use_backend be_api if is_api
default_backend be_web
# Бэкенд для веба
backend be_web
balance roundrobin
option httpchk GET /healthz
http-check expect status 200
server app1 10.0.0.11:8080 check inter 2s fall 3 rise 2
server app2 10.0.0.12:8080 check inter 2s fall 3 rise 2
# Бэкенд для API (например, приоритет живых узлов)
backend be_api
balance leastconn
option httpchk GET /ready
http-check expect status 200
server api1 10.0.0.21:8080 check inter 1s fall 2 rise 2
server api2 10.0.0.22:8080 check inter 1s fall 2 rise 2
HTTP health‑checks: что именно проверять
Суть хорошего health‑check — минимальный, быстрый и правдивый показатель «готовности принимать запросы». Это не просто процесс жив, а приложение работает и имеет доступ к своим зависимостям. Чаще всего используют два эндпоинта:
- /healthz — базовая «живость» (liveness): процесс на месте, готов отвечать.
- /ready — «готовность» (readiness): например, прогрет кэш, подключена БД и т. п.
В HAProxy это настраивается так:
backend be_app
balance roundrobin
option httpchk
http-check send meth GET uri /ready ver HTTP/1.1 hdr Host example
http-check expect status 200
server app1 10.0.0.31:8080 check inter 2s fall 3 rise 2
server app2 10.0.0.32:8080 check inter 2s fall 3 rise 2
Почему явный Host? Некоторые приложения требуют валидный хост для корректной маршрутизации или middleware. Можно отправлять и дополнительные заголовки, например маркер версии:
http-check send meth GET uri /ready ver HTTP/1.1 hdr Host example hdr X-Check v1
Подбор порогов:
inter— период проверки. Для API с жесткими SLO можно 1–2 с, для спокойных сайтов достаточно 3–5 с.fall— сколько подряд неудач переводят сервер в DOWN. Обычно 2–3.rise— сколько подряд успехов возвращают сервер в UP. Обычно 2–3.
Если сервер ушел в DOWN, можно завершить его сессии, чтобы быстрее освободить трафик:
backend be_app
on-marked-down shutdown-sessions
TCP балансировка и проверки
Для баз данных, брокеров сообщений и прочих двоичных протоколов используется режим tcp. Здесь нельзя опираться на HTTP‑статусы, поэтому применяют простейшую проверку подключения или протокольный диалог.
defaults
mode tcp
timeout connect 3s
timeout client 30s
timeout server 30s
frontend fe_pg
bind :5432
default_backend be_pg
backend be_pg
balance leastconn
option tcp-check
# Минимум: умеем соединяться на нужный порт
# tcp-check connect port 5432
# Продвинутый вариант: приветствие протокола (пример для Redis)
# tcp-check send PING\r\n
server pg1 10.0.1.11:5432 check inter 2s fall 3 rise 2
server pg2 10.0.1.12:5432 check inter 2s fall 3 rise 2
TCP‑диалоги особенно полезны для сервисов типа Redis:
backend be_redis
balance roundrobin
option tcp-check
tcp-check connect
tcp-check send PING\r\n
tcp-check expect string +PONG
tcp-check send QUIT\r\n
tcp-check expect string +OK
server r1 10.0.2.11:6379 check inter 1s fall 3 rise 2
server r2 10.0.2.12:6379 check inter 1s fall 3 rise 2
Таймауты, ретраи и балансировка
Грамотно выставленные таймауты — половина успеха. Базовые значения:
timeout connect— сколько ждать установления TCP‑соединения до первого SYN‑ACK. Типично 2–3 с.timeout clientиtimeout server— обрыв неактивных сессий. Для API 20–60 с, для стриминга больше.retries— число попыток соединиться с другим сервером в бэкенде при неуспехе.
Популярные стратегии балансировки:
roundrobin— равномерное распределение, хороший старт.leastconn— предпочтение серверу с наименьшим числом активных соединений, отлично для долгих запросов.source— консистентный хеш по IP клиента; работает как «бедный» стейтик без cookie.
Sticky‑сессии: когда нужны и как включить
Если приложение держит серверную сессию в памяти и пользователь должен попадать на один и тот же бэкенд, используйте cookie‑стикеринг:
backend be_web_sticky
balance roundrobin
cookie SRV insert indirect nocache
server app1 10.0.0.11:8080 cookie app1 check
server app2 10.0.0.12:8080 cookie app2 check
HAProxy будет устанавливать клиенту cookie и маршрутизировать запросы в соответствующий сервер. Для микросервисов чаще берут stateless подход, но в монолитах это спасает от «разрыва» сессий.
Логирование и разбор инцидентов
Логи HAProxy — это ваш лучший друг в проде. В формате httplog вы увидите метод, путь, коды ответов, тайминги этапов запроса и имя сервера в бэкенде. Ключевые поля для диагностики:
- код ответа и флаги завершения — почему сессия оборвалась;
- TR, Tw, Tc, Tr, Tt — где тратится время: ожидание в очереди, соединение с бэкендом, время ответа;
- srv_name — какой именно сервер отвечал или где произошел отказ.
Для TCP‑режима используйте tcplog. А чтобы быстро видеть состояние серверов, включайте административный сокет и периодически опрашивайте его метрики.
global
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
Управление весами и вывод узлов в сервис
Живая эксплуатация редко обходится без плановых работ. Пара приемов:
- Плавный ввод после рестарта приложения:
slowstart 30sна сервере, чтобы вес нарастал постепенно. - Вывод из трафика без разрыва активных сессий: перевести сервер в
maintenanceили снизитьweightдо нуля, дождаться обнуления активных соединений.
Пример:
backend be_web
balance roundrobin
server app1 10.0.0.11:8080 check slowstart 30s
server app2 10.0.0.12:8080 check slowstart 30s
DNS и динамические пулы
Если адреса бэкендов меняются динамически, используйте встроенный резолвер и server-template для автоподхвата узлов по DNS. Это упрощает интеграцию с сервис‑дискавери. На старте можно обойтись статическим списком серверов, но при масштабировании динамика сильно облегчает жизнь.
Тонкая настройка HTTP
Пара простых тумблеров, которые улучшают поведение под нагрузкой:
option http-keep-aliveвdefaultsили бэкенде — держит соединения к приложению, снижая накладные расходы на handshake.http-reuse safe— экономит коннекты к бэкендам, особенно под короткие запросы.option http-buffer-request— аккуратно буферизует запросы для корректной маршрутизации по ACL.
И не забывайте про заголовки для приложения:
frontend fe_http
option forwardfor header X-Forwarded-For
http-request set-header X-Forwarded-Proto http
http-request add-header X-Request-Start t=%Ts

TLS/HTTPS терминация
Частый паттерн — терминировать TLS на HAProxy и отдавать HTTP в бэкенд. Для этого добавьте HTTPS‑фронтенд и редирект с 80‑го порта.
frontend fe_http
bind :80
http-request redirect scheme https if !{ ssl_fc }
frontend fe_https
bind :443 ssl crt /etc/haproxy/certs/site.pem alpn h2,http/1.1
option forwardfor header X-Forwarded-For
http-request set-header X-Forwarded-Proto https
default_backend be_web
Сертификаты можно оформить через SSL. За деталями по выпуску и автоматическому продлению смотрите наше руководство по настройке HTTPS и HSTS, а требования по современным шифрам и версиям протоколов — в статье лучшие практики TLS.
Чек‑лист перед запуском в прод
- Определен режим:
httpилиtcpдля каждого фронтенда. - Таймауты выставлены осознанно,
retriesне мешают идемпотентности методов. - Health‑checks быстрые, стабильные, с адекватными
inter,fall,rise. - Логи читаемы:
httplogилиtcplog, есть план их ротации и анализа. - Стратегия балансировки соответствует профилю нагрузки:
leastconnдля долгих запросов,roundrobinдля равномерности. - Есть план вывода узлов из трафика и плавного ввода (
slowstart, веса). - Добавлены X‑Forwarded заголовки для приложения, где это важно.
Отладка: что смотреть в первую очередь
- Логи фронтенда: всплески 5xx, коды завершения, рост времени на подключение к бэкендам.
- Счетчики health‑checks: много ли переходов UP/DOWN, нет ли флаппинга.
- Количество активных соединений и очередь в бэкенде — признак нехватки ресурсов приложения.
- Системные метрики VDS: CPU, сети, диски, сокет‑лимиты, file descriptors.
Полезные команды:
haproxy -c -f /etc/haproxy/haproxy.cfg
echo "show info" | socat stdio /run/haproxy/admin.sock
echo "show servers state" | socat stdio /run/haproxy/admin.sock
Расширяем базу: ACL и маршрутизация
Даже в базовой раскладке полезно уметь направлять часть трафика по хосту или пути. Например, отделяем статические файлы в отдельный бэкенд:
frontend fe_http
acl is_static path_end -i .css .js .png .jpg .svg .ico
use_backend be_static if is_static
default_backend be_app
backend be_static
balance roundrobin
option httpchk GET /healthz
http-check expect status 200
server s1 10.0.0.41:8080 check
server s2 10.0.0.42:8080 check
Так можно независимее масштабировать статику и приложение, а также точнее анализировать перформанс.
Безопасность по минимуму
HAProxy не заменяет WAF, но ряд простых мер лишними не будут:
- Ограничение методов: пропускать только необходимые, остальное — 405.
- Запрет прямого доступа к служебным путям (/internal, /.well-known в проде, если не нужны).
- Белые списки по IP для административных панелей.
Пример запрета методов, кроме GET/HEAD/POST:
frontend fe_http
acl allowed_meth method GET HEAD POST
http-request deny if !allowed_meth
Итоги
Базовая конфигурация HAProxy для HTTP и TCP опирается на несколько простых принципов: честные и быстрые health‑checks, адекватные таймауты, понятные логи и осторожная стратегия балансировки. Добавьте к этому минимальную безопасность, план управляемого вывода узлов и наблюдаемость — и у вас получится предсказуемый балансировщик, который выдерживает рост нагрузки и не превращается в «черный ящик». Запустите шаблоны на тестовом VDS, проверьте поведение при отказах и пиках — и от этих дефолтов двигайтесь к тонкой настройке под ваше приложение.


