IPVS (Linux Virtual Server) — ядровой L4 балансировщик, который распределяет TCP/UDP‑трафик по пулу бэкендов с минимальными накладными расходами. Он прост, очень быстрый, стабилен и идеален, когда нужен максимум пропускной способности и низкая латентность без L7‑логики. На VDS это один из самых предсказуемых способов поднять отказоустойчивый фронт. Ниже — рабочие схемы и проверенные настройки.
Когда выбирать L4 и IPVS
Если вам нужен только транспортный проксирование/балансировка (TCP/UDP) без анализа HTTP/SMTP/прочих протоколов, IPVS даёт максимальную производительность. Он работает в ядре, не парсит заголовки и не держит сложные контексты приложения. Это снижает задержки и экономит CPU. Типичные кейсы: HTTP(S) фронт без необходимости модифицировать заголовки, базы данных (TCP), бинарные протоколы, gRPC на TCP, DNS (UDP/TCP), RADIUS и т.п.
IPVS — не замена L7‑прокси. Если вам нужны переписывание заголовков, сложные правила маршрутизации, канареечные релизы по cookie/URI — берите L7 (например, на фронте), а L4 используйте как быстрый транспортный слой под ним.
Если нужен альтернативный вариант на базе Nginx stream, посмотрите материал про балансировку TCP/UDP в Nginx stream: разбор stream‑балансировки.
Режимы LVS: NAT, DR и TUN
IPVS поддерживает три способа доставки пакетов к бэкендам (real servers):
- NAT — директор (LB) делает DNAT запросам и SNAT ответам. Весь трафик (вход/выход) проходит через LB.
- DR (Direct Routing) — LB меняет только MAC назначения и отправляет пакет в L2 к бэкенду без изменения IP. Ответ уходит напрямую от бэкенда к клиенту, минуя LB.
- TUN — инкапсуляция IP‑в‑IP (IPIP). Применяется реже, полезно, когда между LB и бэкендами есть L3‑сегменты без единого L2.
Для VDS‑сценариев в пределах одного L2 (или одного провайдера) чаще всего актуальны NAT и DR. TUN удобен при сложной маршрутизации между площадками, но вносит инкапсуляционные накладные расходы и вопросы с MTU.

Что выбрать: NAT или DR
Быстрый выбор:
- Нужна простота, все пакеты и ответы должны идти через балансировщик — выбирайте NAT. Проще в отладке и безопасности, но LB становится узким местом по трафику.
- Нужен максимум пропускной способности, ответы должны идти напрямую от RS к клиенту — выбирайте DR. Минимум нагрузки на LB, но есть нюансы с ARP и L2‑топологией.
По опыту, DR даёт существенно более высокую пиковую пропускную способность (особенно на больших ответах), так как обратный трафик не проходит через LB. В NAT режиме директор обрабатывает и запросы, и ответы, быстрее упираясь в CPU/IRQ/сетевую карту.
Схемы потоков пакетов
NAT
Клиент обращается к VIP на LB. IPVS выполняет DNAT к одному из бэкендов. Ответы бэкенд отправляет на LB (благодаря SNAT), а директор возвращает их клиенту. Контроль полностью у LB: удобно для ограничения, аудита, метрик и TLS‑терминации на внешнем уровне при необходимости. Сертификаты удобно хранить и обновлять через SSL-сертификаты.
DR
Клиент обращается к VIP. LB на L2 меняет MAC назначения на MAC бэкенда и отправляет пакет. Бэкенд видит VIP как локальный адрес (на интерфейсе loopback) и отвечает клиенту напрямую. LB задействуется только на входящих пакетах. Нужно правильно погасить ARP‑ответы на VIP со стороны бэкендов, иначе случится ARP‑флит и трафик будет идти мимо LB.
Алгоритмы балансировки и персистентность
IPVS поддерживает множество алгоритмов:
- rr — классический round‑robin.
- wrr — взвешенный rr.
- lc, wlc — (взвешенная) наименьшая загрузка (по количеству соединений).
- sh — source hashing (по IP клиента).
- mh — консистентный хеш по 5‑tuple/адресам для стабильного распределения.
- sed, nq — алгоритмы с минимизацией задержек/очередей.
Для stateful приложений без разделяемых сессий часто выбирают персистентность: IPVS «приклеивает» клиента к бэкенду на заданное время. Это задаётся параметрами персистентности, а также алгоритмами sh/mh. Если у вас CDN/прокси спереди, продумайте, что будет являться источником персистентности: реальный src IP клиента или адрес прокси/CDN. В DR режиме шифрование и terminations обычно не на L4, поэтому персистентность чаще строят именно по IP.
Keepalived: VRRP, виртуальные серверы и проверки
Keepalived — удобный менеджер для IPVS и VRRP. Он поднимает VIP, обеспечивает failover между двумя LB, управляет таблицей IPVS и делает health‑checks бэкендов. Конфигурация состоит из двух частей: VRRP‑блоки (виртуальные маршрутизаторы) и virtual_server‑блоки (настройка IPVS).
VRRP даёт быстрый перехват VIP вторым балансировщиком при отказе первого. При правильной настройке общий даунтайм — считанные сотни миллисекунд.
Подготовка системы
Установите инструменты и модули ядра:
apt update
apt install -y keepalived ipvsadm
# Загрузить модули
modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr
modprobe ip_vs_sh
# Зафиксировать загрузку модулей на старте
printf "%s\n" ip_vs ip_vs_rr ip_vs_wrr ip_vs_sh > /etc/modules-load.d/ipvs.conf
Общие sysctl‑настройки для L4 LB (безопасные значения по умолчанию могут отличаться в разных дистрибутивах, проверьте):
# Включить маршрутизацию (для NAT и DR)
sysctl -w net.ipv4.ip_forward=1
# Увеличить очереди и минимизировать потери на pps
sysctl -w net.core.somaxconn=1024
sysctl -w net.core.netdev_max_backlog=5000
# TCP параметры для лучшей производительности и устойчивости
sysctl -w net.ipv4.tcp_max_syn_backlog=4096
sysctl -w net.ipv4.tcp_syncookies=1
# Коннтрек для NAT (см. раздел NAT)
# Примерно: sysctl -w net.netfilter.nf_conntrack_max=262144
NAT: быстрая и понятная схема
В NAT режиме бэкенды не должны знать о VIP, никакой особой настройки на них не требуется. Директор делает DNAT входящего трафика и SNAT исходящего ответа. Это упрощает безопасность (весь трафик проходит через LB), но увеличивает нагрузку на LB.
Пример keepalived для NAT
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 150
advert_int 1
authentication {
auth_type PASS
auth_pass strongpass
}
virtual_ipaddress {
203.0.113.10/32 dev eth0
}
}
virtual_server 203.0.113.10 80 {
delay_loop 2
lb_algo wlc
lb_kind NAT
protocol TCP
persistence_timeout 300
real_server 10.0.0.11 80 {
weight 2
TCP_CHECK {
connect_timeout 3
connect_port 80
nb_get_retry 2
delay_before_retry 2
}
}
real_server 10.0.0.12 80 {
weight 1
TCP_CHECK {
connect_timeout 3
connect_port 80
nb_get_retry 2
delay_before_retry 2
}
}
}
Второй балансировщик получает такой же конфиг, но со state BACKUP и меньшим priority. VIP будет перемещаться между ними по VRRP.
Особенности NAT
- Нужен трекинг соединений. Если потоков много, увеличьте
nf_conntrack_max, выделите память под таблицу и мониторьтеconntrack -S. - Ставьте адекватные таймауты в IPVS для TCP/UDP, иначе таблица коннтрека может разрастаться.
- Для hairpin‑трафика проверьте политику маршрутизации; при необходимости добавьте правила, чтобы возвращаемый SNAT шёл обратно через LB.
DR: максимум пропускной способности
В DR LB обрабатывает только входящие пакеты, перенаправляя их в L2 на выбранный бэкенд. Ответы идут напрямую от RS к клиенту. Основная тонкость — ARP‑поведение: бэкенды не должны отвечать на ARP запросы по VIP, иначе трафик обойдёт LB.
Настройка бэкендов для DR
На каждом бэкенде добавьте VIP на loopback и настройте ARP:
# Добавляем VIP на lo (маска /32, чтобы не было маршрутизации в подсети)
ip addr add 203.0.113.10/32 dev lo
ip link set lo up
# Гасим ARP для VIP
sysctl -w net.ipv4.conf.all.arp_ignore=1
sysctl -w net.ipv4.conf.all.arp_announce=2
sysctl -w net.ipv4.conf.lo.arp_ignore=1
sysctl -w net.ipv4.conf.lo.arp_announce=2
# rp_filter может ломать DR, отключаем строгость
sysctl -w net.ipv4.conf.all.rp_filter=0
sysctl -w net.ipv4.conf.default.rp_filter=0
Эти значения зафиксируйте в /etc/sysctl.d/*.conf, чтобы переживали перезагрузки.
Пример keepalived для DR
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 150
advert_int 1
authentication {
auth_type PASS
auth_pass strongpass
}
virtual_ipaddress {
203.0.113.10/32 dev eth0
}
}
virtual_server 203.0.113.10 443 {
delay_loop 1
lb_algo sh
lb_kind DR
protocol TCP
persistence_timeout 600
real_server 10.0.0.21 443 {
weight 1
TCP_CHECK {
connect_timeout 3
connect_port 443
nb_get_retry 2
delay_before_retry 2
}
}
real_server 10.0.0.22 443 {
weight 1
TCP_CHECK {
connect_timeout 3
connect_port 443
nb_get_retry 2
delay_before_retry 2
}
}
}
Алгоритм sh (source hashing) помогает держать стабильное соответствие клиент → бэкенд без sticky‑таблиц. Если важен равномерный вес с стабильностью, рассмотрите mh.
DR и сеть
DR требует, чтобы LB и бэкенды находились в общем L2 (или сквозной L2‑доставке). Если между ними L3‑роутер, пакет с заменённым MAC может не дойти. В таких случаях практичнее NAT или TUN. Проверьте MTU на всех участках, чтобы исключить фрагментацию.
Health‑checks: TCP против HTTP
Keepalived умеет как TCP‑проверки (простая попытка подключения к порту), так и HTTP(S)‑проверки (запрос URI с проверкой кода). Для L4 обычно достаточно TCP_CHECK: он быстрый и мало затратный. Если сервис сложный и «успешный TCP» ещё не гарантирует работоспособность (например, нужен доступ к БД), включите HTTP_GET с проверкой кода/строки.
virtual_server 203.0.113.10 80 {
delay_loop 2
lb_algo wrr
lb_kind NAT
protocol TCP
real_server 10.0.0.11 80 {
weight 2
HTTP_GET {
url {
path "/health"
digest 9b74c9897bac770ffc029102a200c5de
}
connect_timeout 3
nb_get_retry 2
delay_before_retry 2
}
}
}
Для внешнего контроля живости удобно подключить blackbox‑пробинг. См. практику: проверки Prometheus Blackbox (HTTP/TCP/ICMP).
Производительность L4: практическая оптимизация
Сетевые очереди и IRQ
Чаще всего упираются в PPS/IRQ и NUMA, а не в «сырые» мегабайты. На виртуальных серверах важно правильно распределить IRQ по vCPU и включить RSS/RPS на драйвере:
# Посмотреть IRQ и распределить по CPU
cat /proc/interrupts
# Примерно: установить smp_affinity для очередей NIC
# echo <mask> > /proc/irq/<IRQ>/smp_affinity
# RPS: количество очередей RX и маппинг CPU
# Настраивается через /sys/class/net/eth0/queues/rx-*/rps_cpus
Следите, чтобы vCPU балансировались равномерно, а NUMA‑пересечения были минимальными (для крупных инстансов). Виртуализация может скрывать детали, но общие принципы работают.

Offload‑ы
GRO/LRO, TSO/GSO снижают нагрузку на CPU при больших потоках. Для L4 LB это обычно плюс, но тестируйте: иногда GRO мешает точному измерению PPS. Проверяйте текущие параметры через ethtool -k и меняйте точечно.
Таймауты IPVS и conntrack
Для NAT‑сценариев увеличьте лимиты nf_conntrack пропорционально нагрузке, а также выставьте адекватные таймауты. Для коротких HTTP‑запросов таймауты держите ниже, чтобы быстрее очищать состояние. Для длительных TCP — выше, чтобы не терять соединения.
IPVS имеет собственные параметры в /proc/sys/net/ipv4/vs (например, conn_reuse_mode, expire_nodest_conn, expire_quiescent_template) — изучите их и подберите под профиль нагрузки. Практически полезно включить повторное использование шаблонов соединений при агрессивном коротком трафике.
Очереди сокетов
Повышение net.core.somaxconn и net.core.netdev_max_backlog часто уменьшает потери на пиках. Для TCP‑сервисов также посмотрите на net.ipv4.tcp_max_syn_backlog и tcp_synack_retries. Не забывайте, что увеличение очередей без достаточного CPU даёт рост задержек.
Алгоритмы и персистентность
Если у вас сильно неоднородные бэкенды, используйте взвешенные алгоритмы (wrr, wlc) и динамически меняйте веса. Для sticky‑поведения выбирайте persistence_timeout и sh/mh. Старайтесь, чтобы таймаут персистентности был соизмерим с жизненным циклом сессии приложения; слишком длинные значения мешают перераспределению нагрузки.
Наблюдаемость и отладка
Основные инструменты:
ipvsadm -Ln --stats --rate— состояние виртуальных серверов и бэкендов, текущие скорости.watch -n1 cat /proc/net/ip_vs_stats— агрегированные счётчики.conntrack -S— состояние коннтрека (NAT).ss -s,ss -tn 'sport = :80'— быстрый обзор сокетов.- Логи keepalived — причины перевыборов VRRP, падения бэкендов.
При DR проверяйте ARP: ip neigh на LB и RS, отсутствие ARP‑ответов на VIP со стороны RS. При NAT смотрите, не упёрлись ли в nf_conntrack_max и скорость GC.
Деплой без даунтайма и дренаж трафика
Чтобы безопасно увести бэкенд на обновление, снизьте его weight до нуля или используйте механизмы quiesce, дождитесь падения активных соединений и только затем останавливайте сервис. В keepalived можно временно понизить вес или перевести бэкенд в DOWN через health‑check. Для приложений с долгими соединениями (веб‑сокеты, стриминг) планируйте «мягкие» рестарты с достаточным временем дренажа.
Типичные проблемы и решения
- Не работает DR: проверьте
arp_ignore/arp_announceна RS,rp_filter, L2‑доставку, MTU, наличие VIP на loopback с маской /32. - Высокая нагрузка на LB в NAT: включите/проверьте offload‑ы, увеличьте лимиты conntrack, распределите IRQ, подумайте о переходе на DR.
- Потери пакетов на пиках: увеличьте
netdev_max_backlog,somaxconn, проверьте очереди NIC и RSS/RPS, пингуйте IRQ по CPU. - Неровномерный трафик при sticky: пересмотрите алгоритм (например,
mh) и таймаут персистентности. - Флап VRRP: проверьте стабильность сети,
advert_int, приоритеты, NTP/время, загрузку CPU (watchdog keepalived не должен голодать).
Методика измерения производительности
Чтобы получить репрезентативные цифры, тестируйте с нескольких клиентов (генераторов нагрузки) против LB, избегайте ситуации «один клиент — один узкий TCP‑поток». Для HTTP используйте утилиты наподобие wrk или hey с достаточным количеством соединений и потоков. Для TCP‑уровня подойдут tcpkali, hping3 в соответствующих режимах. Пингуйте CPU, IRQ, сетевые очереди, фиксируйте PPS и latency‑квантили. Сравнивайте NAT и DR на одинаковых профилях нагрузки.
Контрольная карта настроек
Минимальный набор, который почти всегда нужен:
- Включить
ip_forwardи загрузить модули IPVS. - Настроить keepalived: VRRP + virtual_server с алгоритмом и проверками.
- Для NAT — поднять
nf_conntrack_max, следить за GC и таймаутами. - Для DR — VIP на loopback RS,
arp_ignore=1,arp_announce=2,rp_filter=0. - Оптимизировать IRQ/RSS/RPS, проверить offload‑ы.
- Подобрать алгоритм (
wlc/wrr/sh/mh) и персистентность. - Наладить наблюдаемость:
ipvsadmstats/rate, conntrack, логи keepalived.
Итоги
IPVS остаётся одним из самых эффективных способов L4‑балансировки. В связке с keepalived вы получаете простой, предсказуемый и очень быстрый кластер с автоматическим failover. Выбор между NAT и DR — это компромисс между простотой и максимальной пропускной способностью. Правильные sysctl, аккуратная работа с ARP и разумные health‑checks обеспечат стабильность под нагрузкой. Настройте наблюдаемость и отработайте дренаж — и у вас будет быстрый и надёжный L4‑фронт, который масштабируется вместе с приложением.


