
Привет, Хабр! Я Павел Михайлик, архитектор в центре сетевых решений «Инфосистемы Джет». Сегодня я расскажу о балансировке в сети и почему она важна при наблюдении за манулами.
«Балансирование нагрузки», «ADC», «GSLB», anycast, ECMP, — много разных терминов и ещё больше разных сценариев реализации, как в постановке задачи, так и в методах и механике реализации. Итак, давайте попробуем для начала наметить основные критерии, по которым можно разделить разные типы балансирования нагрузки.
Цель — распределение нагрузки, отказоустойчивость, специфическая обработка в соответствии с содержимым
Модификация заголовков и/или содержимого
Методы health check
Принципы дифференциации потоков
Механика перенаправления
Методы сигнализации о доступности сервиса
Мы не будем сильно углубляться в технические детали и просто рассмотрим последовательно, что у нас происходит в сети на разных этапах и участках. Итак, приступим.
В интернете любят котиков — данный тезис широко известен, и мы не будем подвергать его сомнению. Попробуем, однако, рассмотреть вопрос чуть более подробно. Допустим, мы интересуемся манулами, а к зиме манул должен достигнуть идеальной формы, а идеальная форма — это шар…
Всё ли хорошо с процессом зажировки?
Итак, мы подключаемся к сети и генерируем запрос, нечто в стиле:

Сформировали строку поиска, Google нам выдал список сайтов, далее по DNS получили IPадрес ресурса, сформировали IP-пакет запроса к frontend, как-то распределились средствами CDN или сразу на локальный backend и получили искомое.
Всё просто? Давайте посмотрим чуть подробнее.
Прежде чем мы получим адрес ресурса, нам нужно провести корреляцию между URL и IP
(resolve), даже когда мы идём на google.com для того, чтобы инициировать поиск, сначала мы получаем IP-адрес для google.com от DNS, и уже потом наш пакет полетит устанавливать соединение на целевой IP узла поискового сервиса, посему сначала надо добраться до DNS. Итак, мы включили телефон и открыли браузер — наши пакетики полетели на адрес DNS-сервера, который нам назначил оператор (ну, или мы сами, если умеем).
На уровне базовых станций идёт распределение нагрузки между узлами PGW (Packet gateway — пакетный шлюз). Оно может учитывать географическую доступность точек размещения PGW, их загрузку и иную логику, требуемую оператору связи. Это своего рода инфраструктурная балансировка нагрузки — занесём в память условно как №1 — «BS > PGW LB». В данном случае не делается никаких манипуляций с содержимым пакета, решается только задача распределения нагрузки на инфраструктуру оператора, ну и, конечно, резервирование.
Идём далее. Трафик обработан PGW и выпущен в IP-сеть, однако на данном этапе нам назначают адрес из некого «серого» пула адресов, обычно RFC1918, а с такими адресами в интернет ходить «не принято». Срочно нужен белый адрес, а значит — CGNAT. Но сначала оператор захочет посмотреть статистику, разобрать потоки по тарифным планам, что значит — DPI. При этом трафика-то много, в одну коробочку терабит не влезет. Поэтому нам нужно балансировать нагрузку между сервисными узлами. Тут в игру вступает своего рода сетевая балансировка, но просто ECMP недостаточно — необходимы симметрия потоков и контроль доступности как минимум, обычно для этого задействуются выделенные аппаратные устройства, условно обозначим №2 — «DPI LB».
Помимо симметрии нам важно обеспечить гарантированное приземление всех потоков от одного абонента на один узел DPI, соответственно, есть специфика по классификации потока.

На следующем шаге у нас появляется ТСПУ (технические средства противодействия угрозам). Технически это тот же DPI, посему не будем выделять это в отдельный случай.
Ну хорошо, мы прошли через «досмотр» и попали на CGNAT, как ни странно, тут также требуется балансирование нагрузки между сервисными узлами, ибо здесь всё тот же терабит, упорно отказывающийся влезать в одну коробку. Технически задача несколько проще, чем в случае с DPI, поскольку для обеспечения симметрии можно использовать маршруты к локальным «белым» пулам адресов вместо синхронизации политик и зеркальных hash. Пометим данный случай как №3 — «CGNAT LB». На этом этапе происходит модификация заголовка IP-пакета — подмена source-адреса на адрес из публичного пула.

Допустим, мы всё же прошли CGNAT и получили белый адрес. Уже, казалось бы, всё, но нет. В комплексе при прохождении через ядро оператора (помимо обработки собственно пользовательского трафика) обрабатывается достаточно много различного «сопряженного/сигнального трафика», а именно:
Авторизация. Трафик распределяется между узлами на основании внутренних атрибутов протоколов посредством, условно, «radius balancer».
Тарификация. Также требует балансирования, причем балансировщик должен различать сессии разных пользователей в рамках одной сигнальной tcp-сессии, DRA / TCP multiflow.
Статистика. Обогащение данных — препроцессинг данных от нескольких источников перед их консолидацией и распределением между конечными коллекторами/анализаторами.
В данном случае у нас происходит обработка с учётом атрибутов прикладных протоколов, модификация содержимого, дифференциация пользователей на базе внутренних атрибутов сессии.
СОРМ. Как для пользовательского, так и для сигнального трафика производится его отведение, при необходимости — фильтрация, снятие и/или назначение заголовков, клонирование/слияние или распределение потоков между анализаторами посредством пакетного брокера (NPB).
А тут у нас не только гранулярная дифференциация, но и перенаправление и распределение трафика на базе не только сетевых таблиц, но и на уровне физических портов.
Назовём это условно №4 — «AAA LB» и №5 — «FLOW LB»

И только пройдя всё это, мы попадаем в интернет. Итак, мы вышли в «открытое море» и доплыли до DNS (а их много, anycast / ecmp…), получили адрес сервера, который обработает поисковый запрос, и далее получили от него URL целевого ресурса (на самом деле, тут тоже много всякой балансировки, но рассмотрим для упрощения только фазу после получения URL).
Поисковый запрос отработан, и у нас есть URL, мы снова идём на DNS за IP уже целевого ресурса. И тут тоже не всё так просто — целевой сайт может жить в распределённом облаке CDN, а DNS может использовать не просто Round Robin, но и «умную балансировку», например:
Метрики загрузки ЦОД
Геопривязку
Часовой пояс/время
Тарифные планы и стоимость ресурсов
Метрики доступности
Ровно такая же история на самом деле происходит даже на этапе открытия поисковой системы. Таким образом фиксируем ещё один тип балансирования, №6 — «DNS LB».
Ну, хорошо, мы получили IP-адрес, теперь-то всё определено? И снова нет!
При «размазывании» нагрузки между ЦОД, даже посредством обычного anycast, у нас будет распределение между «точками входа» в соответствии с метриками маршрутизации, при этом дополнительно уже на уровне DCI (datacenter interconnect) может производиться выравнивание либо принудительное перенаправление нагрузки между ЦОД, например, на основании метрик ёмкости вычислительных ресурсов. Назовем это условно №7 — «ARCH LB».

Но всё же, допустим, мы добрались до ЦОД, в котором, собственно, будет производиться обработка нашего запроса, что же происходит внутри? А внутри у нас дублирующие устройства, множество параллельных каналов, агрегированные каналы и прочая красота, характерная для современных фабрик.
Фактически, прежде чем мы доберёмся до сервисных слоев, должно быть реализовано распределение нагрузки на сетевом уровне, как между точками входа в ЦОД, так и внутри, причём на каждом из шагов со своей спецификой.

Распределение потоков между точками входа в облако
Расчет L3/L2 hash, выбор удаленного VTEP
Для выбранного VTEP выбор транзитного SPINE, для выбранного Spine – выбор порта
Расчет L3/L2 hash, выбор пути к VTEP (а в случае MC-LAG общий адрес размещается на двух коммутаторах в рамках пары)
Выбор исходящего порта – ECMP / LAG
Расчет L3/L2 hash, выбор исходящего порта к серверу в случае локального LAG
При этом не стоит забывать об эффекте поляризации (Hashing Design in Modern Networks:
Challenges and Mitigation Techniques). Или, например, о необходимости обеспечения энтропии при расчете hash для overlay трафика (UDP source port / Inner Headers). Назовем это условно №8 — «NET LB». В некоторых случаях на этом уровне нам необходимо напрямую управлять назначением алгоритмов расчета hash, включая выбор полиномов и входных параметров.
Так вот, сервисный слой, и тут снова не всё так просто — в дело вступает безопасность. NGFW, AntiDDOS, WAF и подобное, и данные сервисные узлы тоже требуется балансировать. А так как они часто еще и tcp-proxy, то просто сетевой балансировки может уже не хватать, поскольку для контроля доступности недостаточно icmp /bfd, требуется L7 Health check. Назовём это №9 — «NET LB+». На этом слое чаще всего у нас также происходит подмена заголовков и дешифровка пакета.
И только после всех этих приключений мы попадаем на «Frontend», да и то — на самом деле это ещё один слой балансирования, на котором реализуются уже манипуляции прикладного уровня:
SSL offload
L7 healthcheck
URL based LB
Header modification
iRule и его аналоги
Многое другое
Это уже то, что более привычно, условно №10 — «APP LB».
И вот, наконец, пройдя этот тяжкий путь, наш запрос попадёт на веб-сервер, который его обработает. А учитывая, что это часто нечто, живущее, например, в K8S, всё ещё только начинается.
Но это уже другая история, а пока давайте сложим все вместе.
Итак, у нас есть много слоёв балансирования, каждый со своей спецификой, да и встречаются многие из них на пути не раз и не два — «BS > PGW LB», «DPI LB», «CGNAT LB», «AAA LB», «FLOW LB», «DNS LB», «ARCH LB», «NET LB», «NET LB+», «APP LB». Даже в нашем упрощённом сценарии мы видим порядка 10 разных типов балансирования нагрузки, каждый со своей спецификой контроля ресурсов, модификации трафика и уровня/метода распределения.

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

