
В современных облаках есть много задач, связанных с проблемами производительности и масштабируемости виртуальных сетей. Кроме этого, есть ряд задач, требующих интеграции с аппаратными сетевыми устройствами. Чтобы преодолеть этот барьер, в собственном SDN (Software Defined Network, программно-определяемая сеть) мы реализовали поддержку технологии EVPN. За это отвечает специальный компонент — EVPN-connector. Он использует OpenVSwitch для передачи данных и GoBGP для передачи информации и позволяет строить распределенные сети с поддержкой L2- и L3-режимов, а также обеспечивает интеграцию с аппаратными устройствами. В этой статье мы, команда IaaS Network в VK Cloud, расскажем о EVPN-connector в деталях.
Начнем с истории
VK Cloud — безопасная и технологичная платформа с широким набором облачных сервисов для эффективной разработки и работы с данными.
Платформа, тогда еще под названием Mail.ru Cloud Solutions (MCS), была публично представлена в 2017 году и изначально строилась на базе OpenStack.
В качестве сетевой подсистемы мы использовали SDN Neutron. Но полностью удовлетворить наши потребности вдолгую он не мог, поэтому к 2018 году мы эволюционно заменили SDN Neutron на SDN Sprut собственной разработки. Подробнее о предпосылках его создания и реализованных решениях рассказывали здесь.
По мере развития проекта мы приняли решение строить основу нашей новой SDN-инфраструктуры ��а технологии EVPN для реализации оверлейной сети, что успешно сделали в 2022 году. Об этом мы рассказывали в ходе доклада «Как выбрать SDN для высоких нагрузок и с наибольшим потенциалом роста» на Highload.
При этом в 2025 году мы начали постепенно выкладывать компоненты нашего SDN Sprut в Open Source, и одним из таких стал EVPN-connector, который уже доступен на GitHub.
Именно о нем сегодня и пойдет речь.
Устройство и принцип работы EVPN-connector
EVPN-connector — сервис на Python, обеспечивающий работу программного VTEP (Virtual Tunnel End Point), который взаимодействует с GoBGP по gRPC для обмена данными о клиентах, а также настраивает Open vSwitch для передачи трафика клиентов.
Чтобы понять, как работает EVPN-connector, рассмотрим небольшую схему.

Допустим, у нас есть вычислительный узел Cmp1, на котором запускаются виртуальные машины VM1 и VM2. За запуск и подключение ВМ к Open vSwitch отвечает отдельный компонент (например, NovaCompute в случае OpenStack).
Здесь же на узле располагается и EVPN-connector. Но сам по себе о виртуальных машинах он ничего не знает, поэтому для работы ему на вход нужно подавать конфиг evpn_connector.conf, который среди прочего содержит параметр configs_dir, указывающий путь к JSON-файлам с описанием подключенных ВМ, к которым нужно настроить связность.
Клиентские конфиги содержат описание типа конфига, секцию параметров ВМ, секцию сегментации, секцию подключения к OvS и имеют примерно следующий вид:
{ "cfg_type": "l2", "mac": "36:e7:a5:7e:0c:8d", "ip": "10.0.0.1", "vni": 123, "imp_rt": ["65512:123"], "exp_rt": ["65512:123"], "ofport": 1234, "type": "flat", "tag": 0 } | { "cfg_type": "l3", "mac": "36:e7:a5:7e:0c:8d", "routes": ["10.0.0.1/32", "10.0.10.1/32"], "vni": 123, "imp_rt": ["65512:123"], "exp_rt": ["65512:123"], "ofport": 1234, "type": "flat", "tag": 0 } |
После получения EVPN-connector читает конфиги и на их основе формирует локальное состояние, в котором фиксируется, какие клиенты есть и как для них нужно настроить сеть.
С этим локальным состоянием EVPN-connector идет в goBGP, который посредством BGP соединен с BGP Route Reflector и интегрирован в общую структуру, связанную с другими аналогичными гипервизорами.
Через BGP осуществляется обмен важной информацией, необходимой для координации действий всех узлов. Например, такая информация выглядит следующим образом: «Виртуальная машина VM1 находится в сегменте 10 на хосте Compute1, а виртуальная машина VM2 размещена в сегменте 20 на хосте Compute2».
Обмениваясь этими данными, мы создаем глобальное состояние представление (Global State) обо всех размещениях виртуальных машин внутри соответствующих сегментов. Забрав из GobiBGP полное состояние о том, где какая виртуальная машина в пределах нужных сегментов расположена, EVPN-connector формирует правила перенаправления трафика для Open vSwitch, обеспечивая передачу данных между виртуальными машинами по каналам VXLAN между гипервизорами.

После завершения текущего шага EVPN-connector не останавливается, а возвращается к началу цикла. Такой подход основан на шаблоне проектирования, известном как Reconciliation Loop. Суть паттерна заключается в постоянной перепроверке того, что сделали, с максимальной доступной частотой. Причем чем быстрее выполняется цикл, тем оперативнее выявляются изменения состояния.

Подробно об устройстве EVPN-connector рассказывали в ходе внутреннего доклада «eVPN Connector Deep Dive — как работает корпоративный eVPN: L2/L3 EVPN, OvS и VXLAN». Вместе с тем на некоторых аспектах здесь остановлюсь подробнее.
Обмен данными по BGP
При первом взгляде на схему может показаться, что она неоправданно переусложнена: использование BGP избыточно и фактически реализуется распределенная база данных, вместо которой можно взять обычную БД, сделать над ней стандартную HTTP API и обмениваться данными по HTTP.

Схема с обычной БД действительно допустима. Но она не учитывает, что наряду с программными VTEP могут быть и аппаратные VTEP (HW VTEP, Hardware VXLAN Tunnel End Point) — например, сетевые маршрутизаторы, которые не умеют работать по HTTP, но отлично работают по BGP.

Например, для построения оверлея компоненты HW VTEP также нуждаются в информации о расположении виртуальных машин, чтобы установить требуемые связи. И если через BGP передача таких сведений реализована успешно, то при работе через HTTP подобные механизмы отсутствуют.
Процесс обмена данными EVPN (Ethernet VPN) работает так: контроль трафика осуществляется по BGP через контрольную плоскость (EVPN ControlPlane), а сами данные передаются в VXLAN (DataPlane).
Но это не единственная причина, почему мы использовали BGP. Чтобы понять остальные особенности, немного погрузимся в специфику работы нашего SDN Sprut.
Использование EVPN-connector в SDN Sprut
Как уже было упомянуто, EVPN-connector — лишь один из компонентов нашего SDN Sprut. Так, SDN Sprut посредством Sprut Agent осуществляет настройку гипервизоров (в частности, Data Plane) и самого EVPN-connector, которому передается соответствующая конфигурационная информация. При этом Sprut Agents функционируют не автономно, а взаимодействуют с SDN Control Plane по HTTP.
Казалось бы, обмен всей необходимой информацией о местонахождении виртуальных машин можно осуществлять тоже по HTTP. Но практика реального проектирования выявила ряд нюансов. Например, виртуальным машинам необходима быстрая синхронизация изменений, происходящих динамически, а Control Plane не способен оперативно реагировать на столь быстрые перемены.
Поэтому во время разработки SDN Sprut мы решили предусмотреть отдельную систему связи BGP Route Reflector, которая работает через BGP и будет заниматься исключительно построением распределенного свитча.

При этом в качестве локальных BGP мы используем GoBGP. Да, ему свойственны проблемы производительности с gRPC в Python, а также нам пришлось фильтровать входящие запросы, но goBGP — единственный Open-Source-демон, имеющий API.
Но в качестве Route Reflector мы используем FRR, поскольку у goBGP проблемы с производительностью на больших объемах.
Примечательно, что подобная реализация дает нам несколько преимуществ:
можно проще интегрироваться с сетевым оборудованием (как с программным, так и с аппаратным);
упрощается SDN, так как для ускорения сходимости не нужно ускорять SDN Control Plane;
получаем дополнительный слой абстракций (SDN «меньше» знает про EVPN) и встроенный в BGP HealthCheck;
можем опираться на наработки и стандарты индустрии — например, RFC 7432: BGP MPLS-Based Ethernet VPN, RFC 8365: Network Virtualization Overlay, RFC 7988: Ingress Replication Tunnels in Multicast VPN, RFC 9135: Integrated Routing and Bridging in Ethernet VPN и другие.
Использование EVPN-connector внутри VK Cloud
Внутри VK Cloud мы применяем EVPN-connector для двух задач:
для организации связности между ВМ;
для интеграции с сетевой фабрикой.
Каждую из них рассмотрим подробно.
Организация связности между ВМ
В первую очередь EVPN-connector используется для организации распределенного свитча в сетях. Причем он поддерживает два основных режима:
L2 distributed switch;
L3 distributed switch.
EVPN-connector as Distributed L2 Switch
В рамках облачной платформы организация L2 представляет собой объединение групп виртуальных машин, запущенных на разных гипервизорах, в L2-домены. Соответственно, с точки зрения EVPN речь идет о создании отдельного пространства второго уровня (L2 domain), где между виртуальными машинами в Type 2 происходит обмен MAC-адресами и в Type 3 поддерживается функционирование широковещательного трафика.

Масштабы использования L2 EVPN в рамках нашего облака довольно велики. Так, объемы достигают:
свыше тысячи гипервизоров (VTEP);
более 10 тыс. сегментов (VNI);
свыше 100 тыс. точек подключения.
Здесь стоит обратить отдельное внимание на то, что наша реализация — не теоретическая разработка, а решение внутренней специфической задачи облака, поэтому у нашего L2 EVPN есть ряд особенностей.
Никакого MAC Learning. В нашем случае информация о MAC клиента статична. Это нужно, чтобы уменьшить влияние клиентов в облаке и исключить проблему «молчащего клиента».
Использование Ingress Replication. Для доставки широковещательного трафика мы применяем механизм Ingress Replication. Его суть проста: исходный широковещательный пакет дублируется и рассылается каждому участнику сегмента, на чьих гипервизорах находятся соответствующие виртуальные машины. Но число копий пакета не может увеличиваться бесконечно, поэтому мы ограничиваем максимальный размер каждого сегмента.
Ну и теперь перейдем к L3-свитчу.
EVPN-connector as Distributed L3 Switch
По сути, в L3 Switch все схоже: те же сегменты и виртуальные сети клиента. Но с точки зрения EVPN передается уже другая информация — префиксы /32 виртуальных машин в Type 5. Соответственно, в такой схеме виртуальная машина ничего не шлет посредством Broadcast, поскольку на ней тоже висит адрес /32.

Но конкретно в нашей реализации есть специфика. Например, могут висеть и другие стандартные адреса — например, /24. При этом виртуальная машина клиента думает, что она находится в стандартном широковещательном сегменте.

Соответственно, нужен Broadcast, но в таком случае он не работает.
Это, в свою очередь, создает определенные сложности, поскольку клиенту в любом случае нужны сетевые функции — например, ARP, DHCP и другие. Поэтому нам пришлось реализовывать обходные пути.
Решение проблемы с ARP оказалось достаточно простым. Мы прямо заставляем EVPN-connector настроить ARP Proxy таким образом, чтобы на все ARP-запросы он возвращал фиксированный MAC-адрес. Клиент, получив ответ, направляет весь последующий трафик именно на этот адрес. Когда пакет достигает своей конечной цели, мы динамически меняем указанный ранее MAC-адрес на реальный MAC-адрес получателя, заранее известный нам из конфига.

Но с DHCP все несколько сложнее, поэтому с ним мы работаем на другом уровне.
Допустим, у нас есть вычислительные узлы (гипервизоры), подключенные к сети. На этих гипервизорах запущены виртуальные машины, подключенные к Open vSwitch. Здесь же мы запускаем агент SDN, который занимается настройкой для Open vSWitch различных сетевых функций, в том числе DHCP и EVPN, таким образом, чтобы получить Service-Chaining.
EVPN является одной из сетевых функций. Фактически наш агент SDN инициирует запуск EVPN-connector, который впоследствии конфигурирует EVPN. Таким образом, для нас EVPN представляет собой лишь одну из составляющих частей общей инфраструктуры.

Благодаря такой реализации у нашего L3 EVPN есть несколько особенностей:
не нужен Broadcast;
нет ограничения на размер сегмента;
предусмотрена поддержка механики VRF.
Интеграция с сетевой фабрикой
Вторая задача, для которой мы применяем EVPN-connector внутри VK Cloud, — интеграция с сетевой фабрикой.
Трафик из облаков нужно каким-то образом выпускать в интернет. Например, это можно реализовать посредством подключения к сетевой фабрике, которая через ядро сети соединена с интернетом.
Обычно это делается следующим образом: запускается отдельная ВМ с SDN, которая посредством встроенного в SDN роутера подключается к сетевой фабрике через VLAN.

И когда узел один, особых проблем не возникает. Но если число VLAN увеличивается и они начинают тянуться между стойками, а то и вовсе между ЦОДами, возникают трудности. Поэтому построение межсетевых стыков на основе VLAN не самое оптимальное решение. Для интеграции с сетевой фабрикой лучше применять EVPN.
Например, можно установить EVPN-connector непосредственно на нужную ноду, подключить его к SDN и настроить связность через EVPN. Причем для построения такой схемы подойдет практически любой SDN, в том числе Open Source.

Возникает резонный вопрос: как конкретно реализовать такую связность? Если среда управляется с помощью SDN, основанного на OpenVSwitch, то все предельно просто: связность настраивается в несколько команд. Однако если используется другое решение, например VMware с собственной системой гипервизоров, то процесс потребует определенных усилий. Тем не менее данная задача вполне решаема.
По такому принципу мы реализовываем интеграцию с сетевой фабрикой через L2 EVPN и L3 EVPN. Остановлюсь на некоторых особенностях.
Интеграция через L2 EVPN
При интеграции через L2 EVPN все довольно просто:
есть облачная часть, которая терминируется нашим софтовым VTEP;
есть физическое оборудование со Switch;
связь между EVPN VTEP и Switch строится по L2 с передачей MAC и BUM.

Но когда нужно построить отказоустойчивую связь с несколькими свитчами, появляются нюансы.
Дело в том, что отказоустойчивость в L2 EVPN строится двумя способами.
Первый способ — MLAG/VPC

В этом случае проблем нет, поскольку для EVPN-connector подобная пара выглядит как одна точка. Поэтому эту технологию мы используем регулярно.
Второй способ — ESI

В этом случае все несколько сложнее, поскольку использование ESI подразумевает наличие дополнительных типов анонсов (например, Type 1, Type 4). Поэтому возможность стыковки с ESI-сегментами требует дополнительной проработки — именно этим мы с командой занимаемся сейчас.
Интеграцию через L2 EVPN мы используем с Q3 2022 года и делаем это довольно активно (100+ сегментов между железом и SDN). С его помощью мы решаем разные задачи: делаем внешние стыки с клиентами, устанавливаем сертифицированные МСЭ, подключаем Bare-Metal-серверы для клиентов.
Интеграция через L3 EVPN
В случае интеграции через L3 EVPN схема во многом похожа, только посредством Type 5. Но здесь мы из коробки заложили, что вся отказоустойчивость делается на ECMP, причем как со стороны сетевого железа, так и со стороны облака.

Но для нас эта технология новая: мы внедрили ее только в Q3 2025 и в данный момент делаем пилотные запуски.
Итоги
Мы проделали довольно большой объем работы, результатом которого стал автономный инструмент для решения разных сетевых задач. Причем наше решение не имеет очевидных аналогов среди Open Source.
Безусловно, построенный EVPN-connector имеет некоторые особенности в реализации стандартов, и во многом это обусловлено тем, что мы создавали компонент под конкретную продуктовую задачу. Но текущая реализация не финал, ведь мы будем развивать EVPN-connector и далее, расширяя возможности компонента и сценарии его применения.
И да, EVPN-connector доступен в Open Source, поэтому сделать свой вклад в его развитие может каждый!