Привет! Меня зовут Яков Жданов, я руковожу командой, которая разрабатывает облачную сеть и сетевые сервисы в MWS. Наша основная задача — обеспечить связность облачных ресурсов. Мы делаем так, чтобы виртуальные машины могли общаться друг с другом, выходить в интернет и принимать обратные соединения. В этой статье расскажу, какие подходы и решения мы выбрали для построения нашей сети.
С чего начинали
В конце 2023 года мы приступили к задаче — разработать функционал виртуальной сети, схожий с основным функционалом таких лидеров индустрии, как Google Cloud, Amazon Web Services, «Яндекс.Облако». Для старта мы решили найти ответы на главные вопросы: какими будут наши андерлей- и оверлей-сети, как спроектировать управляющий слой?
Underlay-сеть. Сначала нужно разобраться с underlay-сетью — это физическая сеть, где живёт облачная нагрузка, которую запускают пользователи.
Overlay-сеть. Второй момент — выбрать подход к имплементации overlay-сети. А значит, определиться с технологией построения туннелей между облачными ресурсами, чтобы обеспечить связность нужных ресурсов и ограничить её для разных тенантов, которые между собой коммуницировать не должны в целях изоляции и безопасности.
Управляющий слой. Спроектировать и реализовать управляющий слой overlay-сети, который отвечает за конфигурацию конфиг-плейна и дата-плейна на тех хостах, где мы запускаем облачную нагрузку.
Расскажу подробнее, какие вызовы нас ждали на этих этапах.
Выбор решения для физической (underlay) сети
Underlay-сеть — те самые хосты в дата-центре, скоммутированные железными проводами: здесь всё должно работать надёжно, безотказно и чётко. Мы стремимся к максимальной простоте в решениях и использованию commodity-оборудования, чтобы легко масштабироваться.
Наши требования при построении физической сети были такими:
— максимальная надёжность;
— максимальная простота, чтобы обойтись commodity-оборудованием;
— IP (только L3-связность) + протокол маршрутизации, например BGP;
— без переподписки, чтобы не терять пакеты пользователей при пиковых нагрузках.
Мы решили идти проверенным путем и остановились на топологии Клоза Leaf-Spine с двойным подключением — Dual Homing. Физические серверы в стойках подключены к Leaf- или Top-of-the-rack-коммутаторам. На верхнем уровне находятся Spine-коммутаторы. Leaf-коммутатор подключён к каждому Spine’у, и каждый сервер из каждой стойки — в два Leaf’а. Так мы достигаем большей надёжности: при выходе из строя одного из Leaf-коммутаторов у нас будет некоторая деградация для обслуживаемых им стоек, но не полный отказ.
Такая топология позволяет нам строить надёжную фабрику и гибко масштабироваться — у неё нет специфических требований к оборудованию. Всё строится на commodity-железе, что снижает зависимость от вендоров и позволяет развивать сеть вне зависимости от ситуаций на рынке и в мире.
Итак, физическая сеть строится. Хосты приезжают, собираются, подключаются, коммутируются. Настало время подумать об overlay-сети.
Выбор решения для виртуальной (overlay) сети
Overlay-сеть — виртуальная сеть, аналог той самой физической сети, о которой мы только что говорили, но она обеспечивает связность и одновременно изоляцию виртуальных ресурсов. Буквально это туннели, которые будут связывать виртуальные машины. Решение должно быть безопасным для нас, как для провайдера, и для наших пользователей. Мы должны обеспечивать высокую степень масштабируемости на всех уровнях: по количеству виртуальных машин, физических серверов и по центрам обработки данных. При этом решение должно быть гибкое с точки зрения простоты вносимых изменений и, соответственно, развития более высокоуровневой функциональности.
В первую очередь мы рассматривали доступные решения, которые уже есть на рынке, пытались проанализировать их, понять сильные и слабые стороны. Первый продукт — это OVN, Open Virtual Network. Другой — OpenSDN, прямая замена довольно известному продукту Tungsten Fabric. Оба продукта доступны под лицензией Apache 2.0. У них есть обширная история применения и большой список инсталляций, а значит, накоплен некоторый опыт и сформированы сообщества пользователей.
В обоих этих продуктах туннелирование выполняется с хоста — это позволяет держать андерлейную сеть максимально статичной и простой. Возможно организовать туннелирование с маршрутизатора, но этот подход не применяется в облаках, потому что требует скоординированных усилий пользователя облака и администраторов физической сети.
На каждой машине есть такая сущность, как виртуальный роутер. Он инкапсулирует (туннелирует) пакеты, которые получает от виртуальных машин, а потом передаёт их по андерлей-сети. На хосте-приёмнике инкапсуляция снимается, и пакет доставляется той виртуальной машине, для которой он предназначен. Ещё есть контроллер, через него проходит обмен конфигурационными параметрами, маршрутной информацией.
Давайте разберёмся, как происходит маршрутизация пакета, который, например, не покидает физический хост. Две пользовательские виртуальные машины находятся на одном хосте за одним виртуальным роутером. В этом случае виртуальный роутер, получив этот пакет, передаёт его без каких-либо изменений.
Если виртуальный роутер видит, что адресат находится на другом хосте, он должен разрешить маршрут в физической сети до хоста с целевой виртуальной машиной, обернуть пакет, чтобы он был правильно понят андерлей-сетью. По андерлей-сети через коммутаторы пакет дойдёт до нужного хоста, дальше виртуальный роутер снимет всю инкапсуляцию и отдаст его той ВМ, в которую пакет и должен был попасть.
Рассмотрев готовые решения OVN и OpenSDN, мы пришли к следующим выводам: безопасность и надежность нас устраивают, но по масштабированию и производительности есть вопросы. Возможно, они подошли бы для приватных платформ, но для публичного облака могут быть не лучшим выбором. Кроме того, технологии инкапсуляции, которые используются в этих продуктах — VXLAN либо Geneve, — могут усложнять переход между сегментами сети, требуя дополнительных усилий, чтобы обеспечить связность между дата-центрами.
Представим, что внутри ЦОД мы используем VXLAN, а в магистральной сети — MPLS. При передаче пакетов из одного ЦОД в другой у нас появляется state на пограничных устройствах, что усложняет масштабирование на более чем один ЦОД. Инфраструктура МТС насчитывает десятки ЦОД с разным сетевым стеком, поэтому нам было важно найти универсальное решение, чтобы облегчить масштабирование.
Адаптация SRv6
Мы начали искать решение и поняли, что нам могла бы подойти технология SRv6. Идея использовать SRv6 в МТС пришла Дмитрию Дементьеву. По ссылке можно посмотреть его доклад на Nexthop.
В SRv6 функция маршрутизации кодируется непосредственно в IP-адрес пакета. Обычно выделяют два сегмента в адресе. Первый сегмент — это локатор, функция маршрутизации, которая будет отвечать за маршрутизацию пакета к тому хосту, на который пакет должен быть доставлен. Предположим, мы можем выделить 64 бита из 128-битного IPv6-адреса.
Вторая часть — функция и опциональные аргументы. То, что нужно сделать с этим пакетом на хосте-приёмнике.
Получив пакет от виртуальной машины, мы инкапсулируем его в SRv6, вкладывая IPv4-пакет в IPv6-пакет. Далее IPv6-пакет отправляется по физической сети до нужного хоста, там декапсулируется и передаётся той виртуальной машине, которой предназначен. Отмечу, что в SRv6-инкапсуляции у нас обычная IPv6-маршрутизация. У нас нет специальных требований ни к коммутаторам, ни к маршрутизируемому трафику.
Ещё, в отличие от решений, рассмотренных ранее, в этой технологии underlay-сеть может получать и использовать информацию из overlay-сети. Например, underlay-сети достаточно «взглянуть» на заголовок IPv6 пакета, чтобы определить, какой виртуальной машине и какому конкретному пользователю облака принадлежит этот пакет, ведь в заголовке пакета закодирована та виртуальная машина, для которой этот пакет предназначен. И underlay-сеть может принимать какие-то решения, опираясь на эту информацию.
Подход к построению контроллера виртуальной сети
Для того чтобы наша виртуальная сеть работала, мы должны уметь распространять маршруты до виртуальных машин. Для этого у нас появляется центральный контроллер, который мы видели в рассматриваемых коробочных решениях, — и особенно нас интересует та часть, которая будет отвечать за обмен маршрутной информацией. Для простоты реализации мы будем использовать BGP. У нас появляется отдельная сущность Route Server, которая будет работать в физической сети, и для надёжности будут работать минимум два экземпляра Route Server. Ещё нам будет нужен некоторый BGP speaker, который используется для обмена маршрутной информацией между автономными системами в интернете, — мы планируем использовать FRR.
Когда планировщик сервиса Compute определяет хосты для размещения виртуальных машин и подготавливает все необходимые ресурсы, включая сетевые, он обращается к сетевому контроллеру для создания виртуальных интерфейсов с нужными адресами на определённых хостах.
Сетевой контроллер передаёт спецификации агентам на хостах, которые, помимо других действий, сделают анонс маршрута через FRR и сконфигурируют data plane для инкапсуляции пакетов. Анонсированные маршруты распространяются на все хосты через route-серверы, развёрнутые в нескольких экземплярах для повышения отказоустойчивости.
На уровне data plane на хосте мы рассматривали использование Linux Kernel с iproute2 для SRv6-инкапсуляции, но это решение не оптимальное по производительности, потому что пакеты обрабатываются в ядре ОС.
В итоге мы выбрали Vector Packet Processing (VPP), который обрабатывает пакеты в юзерспейсе и обеспечивает высокую производительность за счёт одновременной обработки большого числа пакетов — так называемого вектора. VPP — фреймворк с открытым исходным кодом и массой разработанных для него готовых плагинов. Что в сумме даёт большие возможности кастомизации логики обработки пакетов и выстраивания разных пайплайнов.
Описанное решение показалось нам самым масштабируемым и гибким:
— Минимальные требования к физической сети — используется только ipv6-маршрутизация.
— Вся инфраструктура управления без центральных нагруженных компонентов.
— Мы полностью владеем всем набором рантаймов, обеспечивая себе значительную гибкость, которая будет нужна для доработок и добавления новой функциональности в наше облако.
Решение строить собственную технологию на основе SRv6 было непростым, поскольку требует значительных инженерных усилий для имплементации, но мы видим в этом подходе чистоту и универсальность, которые заключаются, с одной стороны, в том, что мы полностью контролируем все аспекты поведения, и, с другой стороны, всё ещё используем общеизвестный стандарт, специально продуманный под такого рода задачи.
Как устроен центральный SDN-контроллер
Software Defined Network контроллер — «источник правды» (source of truth) для конфигурации Data Plane и Control Plane на хостах, состоит из глобального контроллера для управления глобальными сущностями и зонального контроллера, который работает в зоне доступности. Другими словами, зона доступности — это центр обработки данных с минимальными задержками между своими серверами. Для управления зональными сущностями и сетевого агента на каждом хосте, который отвечает за применение конфигурации.
Центральный контроллер состоит из нескольких слоёв:
Глобальный контроллер: управляет глобальными сущностями, такими как сети и IP-адреса. Он взаимодействует с зональным контроллером.
Зональный контроллер: работает в зоне доступности и управляет зональными ресурсами, например сетевыми адаптерами.
Сетевой агент: На уровне хоста выполняет конфигурацию операционной системы и бинарников для обеспечения связности.
Немного о технологиях, которые мы используем при построении сети: контроллер разрабатываем на Kotlin, хостовый компонент на Go, а data plane компоненты на C — всё это деплоится в Kubernetes. Кластер глобального контроллера растянут на все зоны доступности, и его база данных реплицируется во все зоны доступности, что позволяет облаку оставаться работоспособным даже при потере зоны или в перспективе даже нескольких зон. Зональный контроллер деплоится в отдельные кластеры с собственной базой данных в своей зоне.
После интеграции со смежными командами начали покрывать систему end-to-end-тестами. Эти тесты используют public API: запуск виртуальных машин, взаимный ping, проверку доступа в интернет и возможности обратного соединения. Ещё мы работаем над бенчмарками, которые помогают нам контролировать производительность системы и детектировать её регресс.
Что в итоге
Мы начали работу с чистого листа в 2023 году, а теперь у нас есть рабочий прототип, который обеспечивает связность виртуальных машин, их выход в интернет и приём обратных соединений. Мы продолжаем вести активную работу, добавляя новую функциональность в наше облако и внедряя новые технологии и улучшая существующие решения. Особое внимание уделяем повышению производительности и надёжности, а также масштабируемости системы для поддержки роста числа пользователей и ресурсов.