Как стать автором
Обновить

Как в датацентре доставить трафик до сервиса?

Уровень сложностиСредний
Время на прочтение13 мин
Количество просмотров1.5K

Вспомним немножко, что же это такое — сети дата-центров?

В целом, наверное, уже второе десятилетие, как вся индустрия сетевой инженерии и сетевой архитектуры пришла к тому, что сети в дата-центрах перешли от так называемой “классической трёхуровневой архитектуры” (где у нас есть железки уровня доступа, железки уровня агрегации, кор и какой-то внешний выход) к сетям Leaf-Spine (или она же Clos-архитектура).

Leaf-Spine - ну очевидно, потому что есть листья (Leaf), потому что есть хребты (Spine), есть супер-хребты, и всё такое. Думаю, всем, кто хоть раз вводил в гугле или спрашивал у своего старшего (или у младшего, более свежего, товарища) “сеть дата-центра”, скорее всего, выдавалась какая-то такая картинка.

Итак, почему в принципе Clos? Почему индустрия пришла к этому? Какие преимущества есть у данной топологии?

  1. Первое, что приходит в голову, — конечно, масштабируемость. Топология позволяет легко добавлять какие-то новые устройства, увеличивать пропускную способность без изменения архитектуры. Появились у нас какие-то новые сервера? Вот здесь вот мы поставили новый свич, ткнули его сюда, подняли LACP. По факту, с точки зрения архитектуры, ничего не изменилось, но мы таким образом увеличили количество серверов, которое можем обслуживать.

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

  3. Линки, которые здесь нарисованы, могут утилизироваться одновременно — в этом преимущество. Обычно это какая-то IP-фабрика, где у нас используется протокол динамической маршрутизации, который позволяет использовать несколько путей одновременно, в отличие от какого-нибудь мутный STP, который блокирует линки.

  4. Универсальность. Да, так как это IP-фабрика, поверх этой IP-фабрики могут бегать любые сервисы. Это могут быть разные VPN, там GRE, вы можете запускать разные VXLAN и так далее, и тому подобное. То есть IP-фабрика строится под любой тип сервиса, который уже, например, в виде оверлейной сети может доставлять трафик до конечного сервиса.

  5. Часто упоминают некую “экономическую эффективность”, но тут вызывает вопросики, потому что, конечно, это всё надо считать. Пунктик такой спорный.

Ну а вообще, сети сами по себе мало кому интересны — всем важны сервисы, которые они поддерживают. Как сетевые архитекторы и инженеры, мы всегда должны помнить, что людям важны именно сервисы. А чтобы эти сервисы работали, нужны сети. Вот такая простая логика.

А что же нужно сервисам (помимо сети, конечно)? Как ни странно, сервисам нужно всё то же самое.

  • Лёгкость масштабирования: Например, если мы создаём сайт с котиками и у нас появляется много пользователей, нам нужно добавить ещё один сервер и распределить трафик с помощью балансировки. Инфраструктура должна легко поддерживать это. С увеличением количества пользователей должно расти и количество хранилищ данных, так как хранилище — это тоже сервис, который должен уметь масштабироваться.

  • Отказоустойчивость: Если мы сделали сайт с котиками, и один сервер вышел из строя, пользователи всё равно должны иметь доступ к своим котикам. Даже если целый дата-центр перестанет работать, пользователь не должен это заметить — ему важны котики.

  • Эффективное использование ресурсов: Здесь на помощь приходят облачные технологии. Почему облачные вычисления стали популярными? Благодаря гибкости управления ресурсами. Сегодня у вас 10 пользователей, завтра 100, а послезавтра снова 15. Нужно уметь гибко масштабироваться. Для этого используются контейнерные технологии и другие современные облачные решения.

Деплоим сайт с котиками

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

  • Добавляем пачку серверов с фотографиями котиков

  • Делаем отказоустойчивость на уровне датацентра\региона

  • Делаем геораспределение по всему миру

  • Настраиваем балансировку

  • ???

  • PROFIT

Тут начинают возникать вопросики…

Вот, допустим, мы сделали инфраструктуру, которая хостит наших котиков:

Как пользователю добраться до сайта с котиками если серверов несколько?

Пользователь приходит в датацентр, и чё? Куда ему идти? До этих котиков?

Или до вот этих вот?

И если до вторых котиков, то как конкретно пробраться туда? Вот так?

Или вот так вот?

Но допустим, мы эту проблему каким-то образом решили.

Как пользователю добраться до сайта с котиками если датацентров несколько?

Ведь дальше мы начинаем масштабироваться - нам становится тесно в датацентре, ещё и эти стойки по 5КВатт всего. Делаем какой-то мультизональный котиковый сайт. Каждая зона - это датацентр в одном регионе\городе. Какой-то DataCenter Interconnect (DCI) между ними - тёмная оптика, крашенная оптика, L2 VPN, не важно:

Куди идти за котиками? Непонятно :(

Как пользователю добраться до сайта с котиками если котики разбросаны по миру?

С котиками всегда происходит одно и тоже - они очень популярны! И ваши котики теперь востребованы по всем миру. Нужна мировая экспансия вашего гениального сайта про котиков - делаем регион в Штатах, Европе, Ботсване и, конечно, Магадане!

Куда пойти гордому кахазу смотреть котов? А?

Попытаемся решить наши вопросики

А давайте попробуем попытаться решить возникшие вопросики. Да, как нам трафик то доставить?

В какой регион пригнать трафик пользователя?

Итак у нас есть пользователи в Казахстане, есть сайты с котиками, разбросаные по всему миру. Что собственно можно делать?

1. Можно вообще не заморачиваться. Просто анонсируем наш публичный IP через BGP без всяких политик и смотрим, что получится. Какая-никакая балансировка всё равно возникнет: часть трафика пойдёт в один дата-центр, часть — в другой. Но если кто хоть раз работал у провайдера или просто шарит, как устроен интернет — говорить тут про ‘оптимальное распределение’ как-то… ну, смешно. Скорее всего, всё перекосит: какие-то дата-центры начнут жрать львиную долю трафика, а остальные так и останутся полупустыми.

2. Второй вариант — раскидываем IP по миру. Берём четыре адреса: один анонсируем из Штатов, второй — из Европы, ну и из Ботсваны и Магадана тоже. Прописываем их в DNS как 4ре A-записи с одним именем (round-robin сделает своё дело). Плюсы - трафик в теории распределится плюс\минус равномерно между регионами. Минус - DNS-рулетка скорее всего будет стрелять криво, и жителю Ботсваны придётся пиздовать за котиками в Магадан :(

3. Самый толковый вариант — глобальные балансировщики (GSLB). Это умный DNS, который смотрит откуда клиент и подсовывает ему ближайший дата-центр: Казахстан — Европа, Канада — Штаты. Вроде бы идеально, но на практике всё равно придётся постоянно мониторить и подкручивать — трафик любит течь не туда, куда планировалось. Зато если настроить — будет работать лучше любого round-robin’а. Вот таким образом пользователь, находясь в Казахстане, скорее всего, придёт куда-то в Европу. Находящийся в Канаде, скорее всего, придёт куда-то в США.

В какой датацентр в регионе пригнать трафик?

Теперь нам нужно доставить трафик внутри региона. Здесь в принципе методы балансировки те же самые.

1. Не делать в принципе ничего — положиться на дикий BGP. Просто анонсируем из дата-центров один и тот же IP и смотрим, что получится) Авось как то разбаланисируется - главное стыки со всякими разными операторами заиметь в разных местах

2. Второй вариант — снова играем в DNS-рулетку, но уже внутри региона. Раздаём каждому дата-центру свой уникальный /24 и общий резервный /22. Если один ДЦ отвалится — трафик автоматически перекинется на остальные через общую сеть. Работает? Вроде да. Идеально? Ну…

3. Третий вариант — пусть трафик идёт в любой дата-центр региона, будь то Ховрино или Бутово. Разницы нет — главное, что он в нашей сети. А дальше в дело вступает какой-нибудь MPLS TE: он автоматически раскидает трафик между дата-центрами пропорционально их мощностям. Если в одном ДЦ два рабочих сервера, а в другом один — то первый получит две трети трафика, второй оставшуюся треть. Никакой магии — просто умная система сама поддерживает баланс по количеству активных серваков. Реализация - дело ваше - моё дело предложить гениальную идею xD

В общем, здесь тоже есть варианты и трафик в датацентр мы, допустим, доставили.

До какого сервера доставить трафик внутри датацентра?

А что можно сделать здесь? До какого сервера доставить трафик внутри дата-центра?

1.Опять таки - не делаем НИХУЯ НИЧЕГО*, а полагаемся на чистый рандом (утрировано) и отработку стандартных механизмов ECMP в фабрике, используя anycast - все сервера доступны по одному и тому же IP. Однако есть нюанс- если сервис сдох, а сервер ещё дышит и рассказывает об этом в сеть, трафик будет проливаться в чёрную дыру. Никакой проверки состояния живости сервисов нету :(

*Но да, если у вас в фабрике BGP - ECMP, скорее всего, придётся включить и слегка подтюнить )

2. Добавляем немного мозгов балансировке - ставим какой-нить L3\L4 балансировщик. Самое дешёвое что приходит в голову - базовый модуль ядра Linux под названием IPVS с базовыми keepalived-проверками. Теперь нам хотябы понятно, кто реально жив и готов принять трафик, а кто просто машет из гроба своим IP-адресом. Мозгов хоть и добавили, но всё равно балансировка туповата - оперируем только IP и портами, а что внутри пакетов — не понятно.

3. Добавляем к пункту 2 какой-то Application балансировщик. Вот тут уже настоящая магия: NGINX или HAProxy ковыряются в HTTP-трафике. Хочешь — раскидывай запросы по URL (/cats — на один кластер, /dogs — на другой). Хочешь — привязывай пользователей к серверам через куки. SSL? Оффлоадим прямо тут! - бекенду и так хватает проблем. Минус один - всё это надо уметь готовить )

Идеальная иерархия балансировки в дата-центре

1. Входная дверь (ECMP + Anycast)

Трафик пользователя залетает в фабрику через обычный IP-роутинг. ECMP раскидывает его по L3/L4 балансировщикам (NLB) по простому советскому роутингу. Anycast позволяет всем NLB отвечать с одного IP. Просто и эффективно, но без мозгов.

2. Среднее звено (L4 → L7)

Здесь начинается магия:

  • NLB (L3/L4) принимает трафик и строит туннель (GRE/IPIP) до ALB

  • Проверяет здоровье сервисов через health checks

  • Может использовать DSR для обратного трафика (пакеты идут в обход NLB)

  • Распределяет нагрузку между кучей Application LB

3. Финиш (L7-балансировка)

ALB работают с прикладным уровнем:

  • Разбирают HTTP/HTTPS как заправские криптоаналитики

  • Маршрутизируют по URL (/cats → cluster1, /dogs → cluster2)

  • Оффлоадят SSL

  • Поддерживают sticky sessions через куки

И это хорошо

  • Гибкая масштабируемость: можно добавлять слои NLB/ALB

  • Оптимальный путь: DSR сокращает нагрузку на NLB для обратного трафика

  • Фатальные ограничения: упрётесь только в физику (провода, мощность серверов)

Масштабируем!

  1. Городской уровень (Бутово, Щукино и др.)

  2. Международный уровень

    • Континентальные точки присутствия (Европа, Азия, США)

    • Тот же принцип, но с доп. слоями:

      1. Гео-DNS (клиент из Берлина получает IP франкфуртского ДЦ)

      2. Межконтинентальные Anycast (BGP + локализованные anycast-IP)

      3. Глобальный GSLB с учётом:

        • Задержек между континентами

        • Юридических ограничений (GDPR в ЕС)

        • Цены на транзит в регионе

    “Это. Просто. Охуенно.” (с) Анонимный сетевой инженер

Примеры балансировщиков

1. L7 (Application Load Balancers) :

a. Nginx

b. HAProxy

c.Traefik

d.Envoy

e.Istio (Service Mesh)

2. L3/L4 (Network Balancers):

a. IPVS (LVS)

b. F5 BIG-IP

3. Облачные решения:

a. AWS ALB

b. GCP HTTP(S) LB

c. Azure Application Gateway

Дальше была идея сделать небольшое практическое “демо” как сделать простейшую балансировку в лабе с помощью ECMP+Anycast+Linux IPVS, но мне лень. Делайте сам

Проблемы и вопросы сетевой (ECMP) балансировки

Дальше напишу немножко про НЮАНСИКИ которые стоит помнить при работе с ECMP

ЖУТКИЙ ДИСКЛЕЙМЕР. ЛУЧШЕ НЕ РАСКРЫВАЙТЕ

Базу для этой статейки я готовил достаточно давно, а написав всё и оформив я ОСОЗНАЛ, что эта часть статьи ПОВТОРЯЕТ статью Марата!

Я НЕ ХОТЕЛ, ТАК ПОЛУЧИЛОСЬ. Где-то на подкорке отложилось. В общем, изложение своими словами получилось со знатной долей чудной отсебятины

Кто кандидат на равнозначность?

А как вообще включить эту самую ECMP, как маршрутам попасть в группу счастливчиков? Требований не много на самом деле

  • Оборудование должно поддерживать ECMP в принципе. Наверное мало кто НЕ поддерживает в 2025-м то.

  • Маршруты должны быть из одного протокола маршрутизации. При этом протокол маршрутизации должен поддерживать multipath. Ну стоит помнить что например у OSPF\ISIS - это дефолтная опция, а у BGP - не всегда*

  • Маршруты должны иметь одинаковую стоимость с точки зрения протокола.

BGP “со звёздочкой”, потому что не везде multipath для него включен, ну и в кейсах когда у вас eBGP в фабрике стоит помнить про bgp multipath as-path relax

Куда пакет-то отправлять?

Ок, ну допустим ECMP мы включили-настроили, и вот в такой схеме у нас два возможных пути:

И чё?
И чё?

Когда перед коммутатором два “равнозначных” пути, возникает ключевой вопрос: по какому принципу распределять трафик? Варианта два — оба с подводными камнями.

Варианта по-сути два:

  1. Per-packet. Каждый пакет по round-robin раскладывается то в один порт, то в другой.

    И для некоторых кейсов это может быть даже ок:

    Если сеть стабильна, с предсказуемой задержкой, то наверное это даже бОльшую равномерность даст.

    Но как только придёт TCP ANYCAST…

    Потому норм пацаны юзают вариант два

  2. Per-flow. Считается хеш от параметров потока:

    • MAC-addresses + EtherType для L2

    • 5 tuple для udp\tcp

То есть у нас вот по такой простой картинке считается некий Хеш:

Этому хешу ставится в соответствие некий выходной порт. Дальше приходит пакетик, для него ещё раз считается хеш и если параметры потока не поменялись - хеш получается тот же самый, а у нас уже есть для него выходной интерфейс - ну туда его и отправим. А если про поток ничего не известно было заранее - отправим в новый порт и в табличку запишем. В итоге трафик в рамках одной и той же tcp сессии. Будет всегда идти в один и тот же интерфейс… Ну как “всегда”…

Вот есть у нас девственно чистая безпоточная сеточка:

Три выходных интерфейса, хешей нет, табличка пуста. Приходит первый поток, посчитали хеш, решили положить его в первый интерфейс, заполнили табличку:

Потом ещё пару пацанов пришло:

Равномерно распределили, в общем, а потом ещё подъехали ребята:

Казалось бы, что может пойти не так? Может, например, какая-нибудь фигня произойти в сети. А фигни в сети происходят постоянно - это норма. Ну в общем, потерялся вот у нас один балансировщик из сети - сломался малый. Так у нас вся эта наша табличка по пизде пойдёт - ПОРТ ВЫПАЛ ИЗ БАЛАНСИРОВКИ, АААА, МИР ПЕРЕВЕРНУЛСЯ, СРОЧНО ВСЁ ПЕРЕСЧИТАТЬ.

Только 4-му потоку повезло оказатся в тойже корзинке.Непрятная ситуация - tcp сессии текущие почти все развалились, котики не докачались :( И щито делать?

Resilient Hashing

В целом, умные дядьки давно уже всё придумали и обозвали это “неунывыющий хэшинг”. Подробно наверное, можно почитаться вот туть - https://docs.nvidia.com/networking-ethernet-software/cumulus-linux-41/Layer-3/Equal-Cost-Multipath-Load-Sharing-Hardware-ECMP/ Я немного вкратце скажу про это, своровав картинки оттуда же. Итак, вот произошёл у нас такой кейс, было 4-ре выходных интерфейса, один сломался:

Первое правило консистентного хеширования - не трожь рабочие потоки! Заполни место выпавшего next-hop-а живыми:

Итоге - рабочее не ломаем, сломавшееся чиним. Занятно, но проблема становится более “проблемной” когда речь не про сломавшийся путь, а про новый next-hop, который надо вклинить в табличку, расталкав существующие потоки:

То есть появление нового балансировщика привносит больше проблем чем сломанный старый! В общем, будьте аккуратней, ребята, не деплойте новые балансировщики в ЧНН и избегайте флапов!)

Поляризация трафика

Ещё одна вещичка, про которую уже все забыли. Обычно, фабрику строят на оборудовании одного и того же вендора, и даже если это разные железки, логика расчёта хеша и сопоставление хеша некст-хопу может быть одинаковая. Поэтому вполне вероятен такой кейс. Приходит, значит поток на нижний коммутатор и по ECMP раскладывается влево:

Свитч чутка повыше такой же абсолютли и использует такую жо логику расчёта выходных портов. Потому разложит так:

Второй поток придя в фабрику разложится направо:

И ещё раз направо:

Третий поток допустим разложится пару раз в лево:

Чуете чем пахнет, А?

Чуете?

Пахнуло ПОЛЯРИЗАЦИЕЙ. Ну а для решения проблемы с неприятным запахом нужна простая советская…

Умные инженеры подмешивают в хеш уникальный параметр (обычно кусок системного MAC-адреса) - после этого результат работы хеш функции будет разным и как следствие выходные порты - тоже.

И последнее.

Когда мы наконец решили проблемы с правильным хешированием и распределением наших потоков и посыпали всё солью, решив проблему поляризации приходят они….

…снова.

Кто-то?

Мыши, говорю (mouse flows):

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

И слоны (elephant flows):

Это длинные, большие по объему потоки данных, которые могут занимать значительную часть пропускной способности сети. Они обычно состоят из большого количества пакетов и могут представлять такие задачи, как передача больших файлов или резервное копирование данных. Эти потоки могут создавать заторы в сети, если их не обрабатывать должным образом.

Почему это вообще проблема?

(и тут я понимаю что пора научится делать GIF-ки) В общем, смотрим за картинками, опять. Первой пришла мышка. Отправили её вверх.

Потом пришёл слон. Его поток разложился вниз:

Потом слон, и ещё один слон. Распределили

В итоге слонов и мышей набежало так, что по количеству потоков мы, кажется, линки нагрузили равномерно, но вот по “тяжести” потоков как то не очень :(

Как же усмирить слонов и не раздавить мышей?

Вводим новый термин - flowlet и балансируем по ним!

Flowlet — это “кусочек” TCP-потока, разделённый естественными паузами (например, пока клиент обрабатывает данные и не выслал ACK) от других таких же кусочков. В общем иногда, TCP ничего не делает )

В отличие от классического ECMP, который тупо хеширует весь поток и ведёт его одним путём до конца, flowlet-балансировка ловит эти паузы и использует их для перераспределения трафика на менее загруженные пути. То есть хоть flow и один - его кусочки (те самые flowlet-ы) летают по разным путям в фабрике! Ничёси!

Тут условие только одно - главное чтобы фловлет номер 2 не прилетел раньше первого - иначе вообще фигня получится! Теоретически, такое может произойти если свитч решил отправит flowlet номер один через Австралию например (фигасе у вас фабрика!) - ну то есть по пути, задержка которого по сравнению с задержкой пути для второго флоулета, больше длительности паузы между ними. Ещё раз на пальцах:

  1. Допустим предполагаемая пауза между фловлетами - 50 мкс

  2. Для фловлета один выбран путь, по которому он приедет на 80 мкс

  3. Для фловлета два выбран путь, который достави его за 20 мкс

В момент времени t0 мы отправили фловлет номер 1 в путь. Он прибудет через 80 мкс. Подождали 50 мкс и отправили фловлет номер два в путь. Относительно момента t0, фловлет два приедет до хоста через 50+20 мкс = 70 мкс. То есть на 10 мкс раньше чем фловлет номер 1. Хотел сделать лучше, а получилось как всегда :(

В общем, идея хорошая но наша сеть тут должна обладать недюжим интеллектом:

  1. Нужно понимать вообще чё по латенси на альтернативных путях.

  2. Нужно уметь предсказывать длину пауз от только что прибывшего кусочка до следующего. Выглядит как задача для AI, ну то есть для серьёзной математики. Ознакомится с серьёзностью математики предлагаю вот тут - https://www.eecs.umich.edu/courses/eecs589/papers/p503-alizadeh.pdf или вот тут - https://groups.csail.mit.edu/netmit/wordpress/wp-content/themes/netmit/papers/texcp-hotnets04.pdf Я такое не читаю, так как меня даже такие формулы начинают пугать в сетях

Вторая ссылка - один их первых документов по концепции фловлетов вообщем, первая - это про механимз CONGA, который является математической основой для цисковской реализации всей это магии, которая называется Dynamic Load Balancing и применяется в ACI. Ну кстати, да, кажется в SDN-е таким вещам самое место. А вот Juniper не парится и вполне себе несёт это всё в железную фабрику, обозвав Адаптивная Балансировка. Juniper молодец - будь как Juniper!

Ах, да кажется что применять такой подход для среды с Anycast-овыми сервисами стоит с некоторой осторожностью - не факт что ваша фабрика в теме, что за разными путями могут скрываться РАЗНЫЕ сервера - в итоге ваши TCP сессии будут регулярно разваливаться с таким подходом. Но я хз - я лично такое в проде пока не встречал, в основном теоретизирую тут. Встречал ли кто-то? Мне кажется нет и это всё пиздёшь)

ВЫВОДЫ

  1. Помнить что серебряной пули нет

  2. Анализировать ваши требования к сервису, ваш паттерн трафика

  3. Применять гибридные подходы - на каком-то участке использовать один тип балансировки, где-то другой

  4. Изучать и исправлять ошибки

Всё, расходимся. Тут не на что больше смотреть. А побольше смотреть есть тут

Теги:
Хабы:
+7
Комментарии2

Публикации

Ближайшие события