Введение в VxLAN

yu4fmbkxmc-t88dnskg_qedupcc.png

Сегодня мы поговорим об очередной интересной технологии — VxLAN — что это за зверь и с чем его едят, да и вообще нужен ли он вам. Мое знакомство с данной технологией началось с изучения гипервизоров — я постоянно натыкался на термин VxLAN, но что это и как работает не знал. В один прекрасный день я решил все-таки прочитать, что это за зверь. Прочитав пару-тройку статей, я усвоил для себя основные аспекты работы технологии и облегченно выдохнул, прочитав, что данная технология — удел гипервизоров и к транспорту имеет косвенное отношение (хотя, как оказалось позже отношение VxLAN к транспорту имеет самое, что ни на есть прямое). После чего про технологию благополучно забыл и вернулся я к ней снова только через год, когда начал погружаться в EVPN — большинство статей и мануалов были именно о симбиозе EVPN и VxLAN. Литературы по данной технологии много, особенно если вы владеете английским. Я же попробую в данной статье рассказать об основах работы данной технологии и показать на практике — как это настраивается и работает. Но начнем с MPLS…

Для меня, как инженера, который эксплуатирует сеть IP/MPLS самым важным в данной технологии являются ее возможности по организации виртуальных сетей 2-го и 3-го уровня (L2CKT, VPLS, L3VPN, 6PE и т д). Всякие трафик инжиниринги и фастрероуты, хотя и дают инженеру очень большие возможности в части управления трафиком и увеличивают количество 9-ок после запятой (теоретически — практически же все приводит к усложнению архитектуры сети и как следствие к увеличению срока решения аварий), но по сути не являются самоцелью развертывания IP/MPLS сети. Стал бы mpls такой популярной технологией и стандартом де-факто для больших, да и для небольших провайдеров, если бы не умел делать VPN-ы? Естественно нет. Ну согласитесь вряд ли вы стали бы перекраивать свою сеть ради внедрения трафик инжиниринга.

IP/MPLS сети как правило строятся на высокопроизводительных маршрутизаторах, например, Juniper MX или Cisco ASR9K/99 (во всяком случае ядро IP/MPLS сети). Для датацентра же такое оборудование как правило не типично, и обычно, если в датацентре установлены маршрутизаторы такого уровня, то они выполняют роль каких-нибудь PE-шек или бордеров, через которые организуются DCI-и или аплинки. Дело по большей степени в стоимости оборудования — стоимость одного порта на коммутаторе на много ниже чем стоимость аналогичного порта на маршрутизаторе (со схожими показателями пропускной способности, плотности портов на слот и т д). В датацентрах обычно установлены высокопроизводительные неблокируемые или частично неблокируемые коммутаторы имеющие высокую плотность портов емкостью 1/10/40/100G (в зависимости от типа оборудования ToR/EoR/Spine/Leaf), например, Cisco Nexus, весьма недурные изделия Аристы или Джунипера.

Но тот же Cisco Nexus 9K не пригоден для использования в MPLS домене, так как просто не имеет поддержки протоколов распредления меток, или, например, Juniper QFX, который MPLS вроде и поддерживает, но все-таки имеет ограничения, например, по размеру fib. То есть по сути запустить MPLS в датацентре, построенном на Juniper QFX теоретически возможно, но практически это будет не самое лучшее решение — в какой-то момент вы упретесь в возможности данного оборудования (причем этот момент наступит очень скоро).

С другой стороны, в датацентрах очень много систем, которые хотят иметь одновременно и L2 связность и георезерв. Как обеспечить L2 связность между серверами, расположенными в разных частях сети, не имея MPLS? В общем то, если покопаться, то существуют несколько различных вариантов решения данной проблемы. Мы же, как нетрудно догадаться из названия статьи, поговорим о специально заточенной под данные нужды технологии — VxLAN, которая позволяет строить географически растянутые L2 сети поверх обычной IP сети и на сегодняшний день является стандартом де-факто для датацентров.

Любой сервис, организуемый поверх IP/MPLS сети является туннелированием в том или ином виде — в любом случае мы что то через что то туннелируем. К примеру, возьмем простой L3VPN между точкой А и В. В самом простом варианте, без всяких опций C или Detour/Bypass тоннелей, мы имеем стек из двух меток — нижняя, сервисная метка и верхняя, транспортная. Естественно, что бы какой-то сервис между точками А и Б поместить в тоннель, нам нужен непосредственно сам end-to-end тоннель между этими самыми точками А и В. В качестве такого тоннеля в IP/MPLS выступает LDP/RSVP-TE LSP. Далее нам никто не запрещает внутрь этого транспортного тоннеля поместить еще один тоннель, который предназначен для форвардинга клиентского трафика.

В итоге мы получаем тоннель, который туннелируется через другой тоннель. То есть в конечном счете получается, что одна сеть (сеть клиента) строится поверх другой сети (сети провайдера). Сеть провайдера называется underlay сетью. По сути это фундамент для построения наложенных сетей — VPN-ов. Развёрнутые поверх underlay сети клиентские сети являются overlay сетями и строятся по какой то из существующих overlay-ых технологии — например все тот же L3VPN. То есть в VPLS/L2CKT/L3VPN и т д используется IP/MPLS сеть как underlay и тот же MPLS как overlay.

Но как быть, если у нас нет MPLS, а нам нужен L2VPN (если быть точнее то VPLS)? Как я и сказал раннее — существуют различные технологии, которые позволяют это сделать, мы же остановимся VxLAN. Данная технология, совместно с UDP, может организовать виртуальную L2 multipoint сеть (по сути аналог VPLS) без использования MPLS меток поверх какой-либо IP сети (может работать и поверх IP/MPLS сети — далее вы увидите, что технологии важна только IP связность). Сразу возникает куча вопросов, например, что выполняет роль тоннеля в underlay или что используется как сервисная метка в overlay? На эти и некоторые другие вопросы мы ответим дальше.

Итак, VxLAN это виртуальная расширенная частная сеть (Virtual eXtensible Local Area Network). В литературе вы можете встретить и другое название MAC-in-UDP. Это все тот же VxLAN, причем второе название намного лучше описывает суть технологии. Как вы догадались, VxLAN это технология, которая позволяет обычные ethernet кадры упаковывать в UDP сегменты и транспортировать их в таком виде по IP сети. Думаю, пока что мало что понятно, поэтому давайте подробнее.

В сети IP/MPLS маршрутизаторы, как правило, имеют какое-то определенное назначение — ну к примеру PE, P или ASBR. Маршрутизаторы уровня PE являются мультисервисными узлами агрегации. Говоря простым языком — это узлы, к которым подключены клиентские сервисы — именно на этих узлах берут свое начало и заканчиваются L2/3VPN-ы, VPLS-ы и другие VPN-сервисы, реализуемые поверх IP/MPLS сети (коммутаторы последней мили и всякие опции A/B/C мы сейчас не рассматриваем). Вторым важным элементом IP/MPLS сети являются маршрутизаторы уровня Р — по сути просто молотилки трафика (особенно если у вас Free Core), которые даже не догадываются, что они участвуют в организации каких либо VPN сервисов.

В технологии VxLAN тоже есть такие узлы, только называются они несколько иначе, хотя выполняют по сути те же самые функции. Аналогом PE маршрутизатора является VTEP — Vitual Tunnel End Point. Именно VTEP является узлом агрегации сервисов, причем VTEP-ом может быть не только ToR/EoR/Leaf коммутатор или PE маршрутизатор, но и обычный сервер, при наличии на нем необходимого софта (к примеру, VMWare это умеет). Как и в IP/MPLS, на VTEP начинаются и заканчиваются VxLAN тоннели. Аналогом маршрутизатора уровня Р являются маршрутизаторы/коммутаторы, которые не терминируют клиентов и просто форвардят IP трафик — данные коммутаторы как правило даже не знают о существовании в сети VxLAN тоннелей (если на них не вынесли, например, шлюзы).

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

VLAN — это технология, предназначенная для сегментации сети на втором уровне. Как мы все знаем, стандартный коммутатор производит форвардинг фреймов на основании имеющейся (построенной им самим в процессе работы) таблицы форвардинга, в которой учитывается не только mac адрес назначения фрейма, но и его влан тег. Если провести аналогию VLAN с VRF, то каждый влан проще всего рассматривать как отдельную вириальную сущность — то есть виртуальный коммутатор. Давая команду vlan 100 на Cisco, мы создаем виртуальный коммутатор с влан тегом 100. У каждого созданного нами виртуального коммутатора есть какой-то набор интерфейсов (разрешая влан на каком-то интерфейсе мы добавляем порт в определенный виртуальный коммутатор), а также таблица соответствия mac адресов и портов (ее мы смотрим командой show mac-address-table dynamic vlan 100).

Теоретически мы можем представить, что когда в какой-то порт коммутатора прилетает фрейм с влан тегом, то решение о дальнейшей отправке фрейма принимается на основании таблицы mac адресов соответствующего вириального коммутатора. Если получен фрейм с тегом 100, то соответственно приниматься решение о форвардинге данного фрейма будет на основании mac таблицы виртуального коммутатора с тегом 100.

Классический коммутатор при получении какого-то фрейма (нам не важно какой это фрейм — бродкатный или юникастный) флудит его во все свои порты. Если же у коммутатора есть причина не флудить пакет в какой-то порт или группу портов — он этого делать не будет: если коммутатор точно знает, неважно откуда, что mac назначения не находится за определенным портом или же что данный фрейм отправлять в определенный порт или порты не надо (ну, например, включен igmp-snooping), то и флудить фрейм в этот порт (или порты) коммутатор не будет. Логично, что при получении какого-то фрейма у коммутатора есть как минимум причина не флудить этот фрейм обратно в порт, из которого он пришел — это банальное правило расщепления горизонта. Если коммутатор точно знает, что mac адрес назначения живет за определенным портом — фрейм будет отправлен только в один конкретный порт. Исходя из вышесказанного, логически коммутатор можно представить в таком виде:
lby5lc4ye48hmwpio_ccloevtvu.png
Как видим из картинки, получается, что фрейм, пришедший с влан тегом 100 попадает в вириальный коммутатор 100 и логично, что теперь он не может просто так попасть в другой вириальный коммутатор — то есть в другой влан, ну, например, 200, так как между виртуальными коммутаторами нет прямой связности. Когда же мы создаем роутинговый интерфейс, мы создаем интерфейс, через который виртуальный коммутатор может общаться с остальными виртуальными коммутаторами, у которых тоже есть роутинговый интерфейс — то есть производить роутинг пакетов между вланами.

На схеме показано, что у виртуальных коммутаторов VLAN-100 и VLAN-200 есть роутинговые интерфейсы, через которые данные виртуальные коммутаторы могу общаться. В тоже время у виртуального коммутатора VLAN-N не сконфигурен L3 интерфейс — то есть данный виртуальный коммутатор не имеет возможности общаться с другими виртуальными коммутаторами (в нашем случае с VLAN-100 и VLAN-200). Номер влана в классической L2 сети является глобальным — если у нас есть L2 домен из, например, 10-ти коммутаторов, то номера вланов являются глобальными для всего домена.

Но надо понимать, что это всего лишь упрошенная логическая модель коммутатора для понимания принципа его работы. И хотя влан можно представить, как виртуальный коммутатор, он в реальности же таковым не является. То есть у нас нет отдельной таблицы коммутации для влана 100 или для влана 200. Естественно мы можем посмотреть, какие маки мы изучили в каком-то определенном влане (причем вы можете увидеть, что один и тот же мак может быть в разных вланах), но это не говорит о том, что под данный влан на оборудовании выделена отдельная таблица. Коммутатор имеет одну единую таблицу форвардинга вне зависимости от количества сконфигуренных на нем вланов. Просто, когда происходит флудинг полученного фрейма, коммутатор знает, что данный фрейм отправлять в определенные порты не надо. Например, если порт eth1/1 является аксессным портом во влане 200, а порт eth1/2 является транковым портом, но на нем влан 100 не разрешен, то коммутатор (имеется ввиду физический) в эти порты фрейм с тегом 100 флудить не будет, так как точно знает, что за данными портами нет хостов в 100-м влане. Физически это происходит именно так, а вот логически проще представить, что данные порты не принадлежат виртуальному коммутатору с вланом 100 и поэтому в них фрейм просто не может быть отправлен.

Примечание: Не стоит пытаться применить данную концепцию к бридж-доменам на современных маршрутизаторах — это по сути другой мир со своими законами, в котором номер влана по сути имеет значение только на линке. Все описанное соответствует имеено классическому коммутатору, который не поддерживает расширенное пространство вланов. Про бридж-домены я писал отдельную статью (применительно к JunOS). Если кому-то интересно, то могу сделать аналогичную статью для IOX-XR.


То есть мы имеем следующее: у нас есть виртуальный коммутатор, определяемый каким-то vlan тегом и имеющий какой-то набор портов. Точно такая же концепция лежит в основе VxLAN. Только в VxLAN роль влан-тега играет VxLAN Network Identifier (иногда его называют и Virtual Network Identifier) или сокращённо VNI. В отличии от vlan-тега, длинна которого 10 бит (то есть в одном L2 домене может быть максимум 4096 вланов), VNI имеет длину 24 бита — то есть может принимать 16 777 214 уникальных значений. Как и vlan тег, VNI является уникальным для всего VxLAN домена. То есть если хост А живет за VTEP-ом А, а хост В за VTEP-ом В, то на обоих VTEP-ах эти хосты должны быть за интерфейсом, который относится к одному и тому же VNI, иначе L2 связности между хостами А и В не будет. Все аналогично VLAN — ведь если на одном коммутаторе хост будет во влане 100, а на соседнем другой хост во влане 200 — то L2 связности между данными хостами не будет.

Примечание: очень важно понять, что в отличии от MPLS метки, которая уникальна только в пределах одного узла, идентификатор VNI имеет глобальное значение для всего VxLAN домена. Поэтому посчитать, чего будет больше L2 сетей при использовании VxLAN или VPLS (с MPLS) очень сложно. Абсолютное значение естественно и указывает в пользу VxLAN. Но если в VPLS вы можете использовать одну и ту же метку для разных клиентов (например, если VPLS домен 1 на PE 1 будет использовать метку 299001, это не значит, что VPLS домен 2 на PE 2 не может использовать ту же самую метку 299001). А вот при использовании VxLAN такой номер не пройдёт. Если использовать один и тот же VNI и на PE1 и на PE2, то тогда клиент, подключенный к PE1, сможет общаться с клиентом, подключенным к PE2.


Как я написал ранее — при создании влана мы по сути создаем виртуальный свич и далее добавляем в него какие то порты и роутинговый интерфейс (при необходимости). Но какие порты мы добавляем? Обязательно ли нам использовать физические порты? Или можно воспользоваться виртуальными? Вспомним, например, такой протокол как GRE. При создании GRE тоннеля создаётся логический интерфейс — например gre-0/0/0 в JunOS. Точно так же и при создании VxLAN тоннеля — на коммутаторе появляется туннельный интерфейс, например, vtep.xxx в JunOS. Данный интерфейс, как мы увидим далее является транковым и способен переносить как тегированные, так и не тегированные фреймы. Если у вас есть возможность залезать на какую-нибудь коробку и посмотреть таблицу мак адресов в VPLS, то вы увидите, что часть маков будет видна не через физический порт, а логический lsi интерфейс (на примере JunOS). Lsi-интерфейс и есть не что иное, как тоннель (псевдопровод в терминах VPLS) до какого либо PE маршрутизатора. Чем хуже VxLAN тоннель? В VxLAN использует такой же принцип — только сигнализация тоннелей другая.

В итоге получается, что коммутатор использует имеющиеся у него VxLAN тоннели как транковые порты, в которые, так же как и в реальный порт, флудятся пакеты и через него изучает маки. То есть если у нас несколько удаленных VTEP-ов, то логическая схема свича будет теперь иметь такой вид:
4rjzbrq3vjcukjlne3k9n5dtnfw.png
Но как я говорил в начале, если у порта есть причина не флудить полученный кадр в какой-либо порт или группу портов — то он не будет этого делать. По умолчанию фрейм не отправляется только в порт, из которого он прилетел — это простое правило расщепления горизонта. В VxLAN данное правило тоже работает, только есть некоторые нюансы.

Предположим, что фрейм получен через физический порт. В таком сценарии все нормально — коммутатор просто флудит пакет во все порты (ну кроме порта, откуда получен фрейм). Но что, если фрейм получен через VxLAN тоннель? Так как между всеми VTEP-ми создается полносвязанная топология из VxLAN тоннелей, то логично, что полученный из тоннеля фрейм не надо снова флудить в другие VxLAN тоннели, так как остальные VTEP-ы уже получили этот фрейм — в этом же и есть суть полносвязной топологии.

Но как понять, при каких обстоятельствах в какие порты надо флудить фрейм, а в какие не надо? Для этого порты, которые являются VxLAN тоннелями, объединены в виртуальную группу (назовем ее split horizon group) и если фрейм получен из какого-то порта, являющегося членом данной группы, то в остальные порты, входящие в данную группу, фрейм флудиться не будет. Естественно, оборудование позволяет вам изменить это поведение, например, для hub-and-spoke топологии. Но просто так это делать не стоит — широковещательный шторм «веселая» штука.

Подытожим первую часть нашей статьи: VxLAN является расширенным аналогом VLAN — то есть является виртуальной L2 сетью. Виртуальные L2 сети разделены между собой и трафик между этими сетями коммутироваться не может — для этого нужна маршрутизация. Подобно VLAN, VxLAN имеет аналог VLAN тега, который служит идентификатором виртуальной L2 сети — VxALN Network Identifier (VNI). Длинна VNI равна 24 битам, что позволяет использовать более 16 миллионов виртуальных L2 сетей в одном домене. Как и VLAN тег, VNI является глобально уникальным для всего L2 (VxLAN) домена. Изучение mac адресов производится методом flood-and-learn — коммутатор флудит фрейм во все порты (в какие порты не флудится и почему мы разобрали ранее) и по source mac адресу заполняет таблицу форвардинга. Далее мы поговорим о том, как происходит поиск удаленных VTEP-ов и сигнализация тоннелей.

Итак, как я написал в начале статьи — vpn это туннелирование чего-то через что-то. В IP/MPLS как underlay используется IP/MPLS сеть, и тот же MPLS как overlay. Это не единственные технологии, которые позволяют через себя что-то туннелировать. Вернемся снова к протоколу GRE. Это overlay-я технология, которая создает виртуальный p2p линк между точками А и В. Данный протокол инкапсулирует оригинальный IP пакет в новый IP пакет, вставляя между этими заголовками свой собственный GRE заголовок.

VxLAN все несколько сложнее, но этому есть объяснение. Как и в GRE, к оригинальный ethernet кадру добавляется VxLAN заголовок. Данный заголовок имеет длину 8 байт и кроме флагов и зарезервированных полей несет в себе описанный ранее VNI. То есть, как вы понимаете данный заголовок необходим, что бы на удаленной стороне коммутатор смог определить, к какому VNI данный пакет относится — то есть выполняет по сути роль VLAN тега. Что дальше? Логично было бы как и в GRE упаковать оригинальный фрейм с VxLAN заголовком в IP пакет. Но тут возникает проблема. В заголовке протокола IP есть поле protocol, как не трудно догадаться, отвечает данное поле за то, какой вышестоящий протокол упакован в данный IP пакет. GRE заголовок является протоколом номер 47, а вот VxLAN номера не имеет. То есть по сути упаковать VxLAN напрямую в IP можно, но это вызовет сложности при обработке пакета как на транзитных узлах, так и на узле назначения. Поэтому VxLAN пакет, как например и GTP, предварительно упаковывается в UDP, в котором поля protocol нет. И теперь нам ничего не мешает упаковать полученный UDP сегмент в IP пакет. Под VxLAN специально был выделен UDP порт 4789.

Возникает вопрос — почему UDP? Почему не TCP, он же надежнее, имеет адские таймауты для сессий и т д. Дело в том, что TCP проектировался под совсем другие нужны и его задача — гарантированная доставка данных приложений — отсюда и механизмы подтверждения получения пакета удаленной стороной и управление скоростью передачи. Проблема хорошо будет заметна, когда клиент тоже будет использовать TCP. В итоге мы получим TCP поверх TCP — уже звучит не очень. Теперь представьте, что пакеты теряются, и как вы понимаете, теряться они будут и в рамках underlay сессии VTEP-A<<>>VTEP-B и в рамках overlay сессии SERVER-A<<>>SERVER-B. А когда у нас теряются пакеты в TCP, то закономерно возникают ретрансмиты — так как нет подтверждения получения. В итоге возникнут ретрансмиты и в underlay сессии и в overlay сессии. То есть получается, что underlay TCP сессия начнет гонять помимо своих ретрансмит пакетов, еще и ретрансмиты overlay TCP сессии. В итоге в таком сценарии мы погрязнем в ретрансмитах, что неизбежно приведет к потере скорости и в итоге получим вместо плюсов — одни минусы. К тому же еще одним не менее важным фактором в пользу UDP является тот факт, что UDP не устанавливает сессию, когда TCP — это всегда p2p сессия и она не может быть p2mp —, а вот зачем нам это, мы узнаем чуть позже.

Сам VxLAN заголовок имеет следующий вид:
lzvwquv46camhcktasziytgmexo.png
По сути нам интересно тут только поле VNI.

Как я и написал выше, далее нам ничего не мешает упаковать UDP сегмент в IP отправить… Но отправить куда? Не на деревню дедушке ж. VxLAN тоннели строятся между лупбеками коммутаторов, поэтому сорс адрес будет собственный лупбек коммутатора. А вот как узнать лупбеки удаленных коммутаторов, выполняющих роль VTEP? То есть нам нужен механизм поиска соседей.

Механизм поиска соседей может быть автоматическим или ручным (если ручной можно вообще назвать поиском соседей). VxLAN имеет несколько режимов работы. Рассмотрим их по порядку.

Static (Unicast) VxLAN

Самый простой вариант — это статичное указание удаленных VTEP. Этот режим схож с VPLS Martini. Все сводится к тому, что в конфигурации VNI надо статически задать адреса всех удаленных VTEP, которые терминируют клиентов в указанном VNI. В таком сценарии VTEP будет указывать в IP заголовке как адреса назначения — адреса указанных вручную VTEP. Естественно, если VTEP-ов будет больше двух, то точек назначения пакета при флуде будет уже как минимум две. Указать в IP заголовке нескольких получателей не получится, поэтому самым простым решением будет репликация VxLAN пакета на исходящем VTEP и отправка их юникастом на удаленные VTEP-ы, указанные в конфигурации. Получив данный пакет, удаленный VTEP его декапсулирует, определяет какому VNI данный пакет относится и далее рассылает его во все порты в данном VNI (точнее действует так, как было описано ранее в разборе работы коммутатора). Помимо этого, так как мы все в курсе, что mac адреса изучаются коммутаторами на основании поля source mac, то после декапсуляции VxLAN пакета VTEP ассоциирует mac адрес, указанный как исходящий в оригинальном ethernet заголовке с тоннелем до VTEP, от которого данный пакет получен. Как и было написано ранее — VxLAN тоннель коммутатор воспринимает как простой транковый порт.

Минусы данного подхода очевидны — это увеличенная нагрузка на сеть, так как BUM трафик реплицируется на исходящем VTEP и юникастом рассылается всем указанным в конфигурации нейборам, плюс к этому при добавлении или удалении VTEP придется править конфиги на всех остальных VTEP-ах и руками удалить или добавить нейбора (нейборов). В век автоматизации как-то странно использовать статическое указание нейборов. Но все равно данный подход имеет право на жизнь, например openvswitch умеет работать только со статически заданным нейбором, во всяком случае на данный момент (поправьте если не прав).

Для работы данного режима необходимо только наличие связности между лупбеками всех VTEP. В практической части мы познакомимся с конфигурацией и работой VxLAN в данном режиме.

Multicast VxLAN

Данный режим работы, в отличии от предыдущего, умеет находить удаленные VTEP-ы автоматически, а репликация бродкаста происходит на underlay, а не на исходящем VTEP. И репликация и поиск удаленных VTEP-ов происходит с помошью мультикаста. Теперь нам не надо вручную указывать всех нейборов, а вместо этого указать какую-то мультикаст группу, которая будет ассоциирована с конкретным VNI (или несколькими VNI). После того, как группа будет привязана к VNI, коммутатор (точнее VTEP, так как им может быть и простой сервер) начинает слушать данную группу. Но что нам это дает? Логично, что точно так же поступят и остальные VTEP-ы (если конечно вы правильно укажите соответствие VNI-multicast группа) — они станут слушать указанную вами группу. И если послать какой пакет на адрес этой группы, то его получат все VTEP-ы. Этот функционал и позволяет нам реплицировать пакеты и искать удалённые VTEP-ы.

В итоге все работает просто и банально — VTEP формирует VxLAN пакет, указывая себя источником (свой лупбек в IP заголовке), а адрес назначения устанавливает равный адресу сконфигуренной для данного VNI мультикаст группы — то есть получается, что VTEP теперь еще становится и сорсом для данной группы. Далее работает обычный и всеми нами любимый мультикаст. Так как все остальные VTEP слушают данную группу, то все они получают VxLAN пакет. Ну, а далее все тоже самое, что и раннее — декапсуляция оригинального фрейма, изучение мака (так как сорсом для данной группы VTEP указывает себя, то удаленным VTEP-ам не составляет труда ассоциировать mac с тоннелем до исходящего VTEP) и флудинг.

Теперь снова вернемся к инкапсуляции VxLAN в UDP и вопросу — почему же UDP? Как вы поняли у нас получилась p2mp соединение — один источник и несколько получателей. TCP не умеет устанавливать p2mp сессии, в отличии от UDP, который сессию вообще не устанавливает.

Как правило бест-практикс считается использование bidir-PIM, что более чем логично, так как VTEP одновременно является и получателем и источником мультикаст группы (или нескольких групп в зависимости от вашего конфига). Естественно тут так же работает правило расщепления горизонта — пакет, полученный через VxLAN тоннель не будет отправлен обратно в VxLAN тоннель.

В сравнении с первым вариантом в данном сценарии BUM трафик реплицируется на underlay и естественно будет занимать меньше полосы пропускания. К тому же теперь нейборов задавать руками нет необходимости. Для работы данного режима необходимо наличие связности до удаленных VTEP по IP и поддержка мультикаста. Если у вас что-то не взлетело (как вы понимаете ломаться тут особо, то и нечему) — то для начала проверьте, а верно ли вы сконфигурили связку VNI-мультикаст группа. Как все это конфигурируется мы разберем на практическом примере.

EVPN/VxLAN

Третий вариант, он же самый интересный и масштабируемый — это использование EVPN как control plane для VxLAN. Если кто-то не знает, что же такое EVPN, то советую почитать мою предыдущую статью, хотя она и относится к концепции MPLS/EVPN, основные принципы работы справедливы и для VxLAN/EVPN. Сегодня глубоко раскапывать EVPN/VxLAN я не буду — ограничимся основными моментами.

Как я написал выше, основа EVPN — это великий и могучий (или многострадальный) протокол BGP, который и позволяет производить изучение маков между VTEP-ами и поиск соседей. Так как этот зверь может таскать любые маршруты, и даже передавать link-state информацию (до чего дошел прогресс), то что ему стоит перенести информацию о mac адресах? Под EVPN выделено отдельное сабсемество адресов в семействе l2vpn (AFI 25). Это позволило превратить mac адрес в аналог роутингового адреса и передавать его в BGP анонсах — то есть так же, как это делается в L3VPN. При использовании EVPN/MPLS в BGP NLRI передавался сам mac адрес (естественно не забываем про RT/RD/next-hop и т д) и MPLS метка. Сейчас нам метка ни к чему — у нас нет MPLS. А она нам и не нужна, потому что у нас есть VNI! Вопрос только в том, как вместо метки в BGP сообщении закодировать VNI.

EVPN NLRI под метку не случайно отведено 3 байта — то есть 24 бита, это идеально подходит для указания VNI. Поэтому вместо метки в BGP анонсе логично занял место метки идентификатор VNI. Единственная проблема, которую надо решить — как коммутатор, который получит данный EVPN маршрут должен узнать, что в поле MPLS Label закодирован именно VNI, а не MPLS метка? Ведь по умолчанию там метка и коммутатор будет полностью прав, восприняв значение этого поля как метку. Снимая дамп в Wireshark вы будете видеть не VNI, а MPLS метку (при кодировании метки последние 4 бита не используются, поэтому Wireshark считает что в поле закодирована метка 6, а не VNI 100):
y504yxiodotkxnhldsmjhp3ebho.png
Чтобы побороть данную проблему используется специальное расширенное комьюнити, которое указывает, что данный маршрут необходимо использовать именно для vxlan инкапсуляции:
q6pasfzcnifwvnjztcjyuhyftfk.png
И если мы сейчас поле, отведенное под метку переведем в десятичную систему, то получим наш VNI:
0i1jq546zyo5xt5agklvvzrcb20.png
Остальные принципы работы примерно такие же — те же 5-ть типов маршрутов (если честно, то маршрутов на данный момент уже 8 типов, но часть их них еще в статусе драфта). По-умолчанию, если у вас в ядре нет мультикаста, то будет работать репликация на исходящем узле (исходящем VTEP), как это мы рассмотрели в первом варианте. Но при наличии мультикаста репликация будет производится не на исходящем узле, а где-то дальше (на RP как правило, либо в других точка, если есть более короткие пути до источника чем через RP).

Отдельно хотелось бы сказать про изучение маков. Какие плюсы у EVPN? Как правило везде пишут в первых строках фразу следующего содержания — EVPN переносит изучение мак адресов с data plane на control plane. Звучит очень гордо и прогрессивно, но давайте подумаем, а так ли это на самом деле? Во-первых, изучение маков на участке Клиент-VTEP происходит, как правило, на data-plane. Далее, что происходит, когда коммутатор получает фрейм? Правильно, он его флудит во все порты, кроме тех, за которыми клиента точно нет (по мнению коммутатора).

Концепция EVPN подразумевает следующее поведение — когда какой то из удаленных VTEP-ов изучил mac адрес через data plane, он формирует BGP сообщение, в котором указывает данный мак и рассылает его своим пирам. Все остальные VTEP-ы, приняв это BGP сообщение инсталлируют полученный mac в таблицы форвардинга. Что это нам дает? А то, что теперь у коммутатора есть причина отправить фрейм только в один порт, а не во все, так как он точно знает, где живет mac назначения. А вот то, что узнал он это через control plane — нам абсолютно не важно.

Но все же меняется ли что нибудь в модели поведения коммутатора и если да, то на сколько велик масштаб изменений? Да, коммутатор, получив какой-то фрейм и изучив mac адрес, формирует BGP сообщение с указанием данного мака и рассылает его своим пирам — то есть рассказывает всем, что за мной такой то mac. Но если коммутатор еще не знает где живет mac адрес назначения, то он логично все так же флудит полученный фрейм во все порты. То есть изучение маков методом flood-and-learn никуда не делось, более того даже при наличии EVPN изучение маков все так же работает методом флуда, но просто теперь изученные через data-plane маки передаются между коммутаторами через control plane. В итоге EVPN позволяет существенно сократить объем флуда при при изучении маков, но никак не избавиться от него полностью.

Что еще хорошего дает нам EVPN? Технология позволяет нам упростить жизнь сетевого инженера, так как предоставляет функционал автоматического поиска соседей.

Еще одной очень важно функцией EVPN является мультихоминг, как Single-Active, так и All-Active (причем один сервер может смотреть в два и более коммутатора в отличии от MC-LAG). Мультихоминг может быть организован или пропириетарными средствами вендора (MLAG -Arista, vPC — Cisco Nexus), или стандартными средствами EVPN. Первый случай нам сейчас не интересен — давайте обсудим зашитый в EVPN механизм мультихоминга. В принципе все сводится к тому, как избавиться от L2 петли (при All-Active, в Single-Active это не нужно) — алиасинг и ускорение сходимости при отказе собственно уже красивый и функциональный обвес. Как вы уже знаете, для этого в сегменте выбирается DF — это узел, который имеет право отправлять BUM трафик в сторону клиента. Все остальные узлы просто дропают BUM трафик, предназначенный клиенту. Но проблема будет тогда, когда клиент отправит бродкатный фрейм в сторону non-DF узла и тот его перешлет в сторону DF. Логично, что далее DF вернет фрейм клиенту, что приведет к петле.

В EVPN/MPLS эта проблема решена простым добавлением ESI метки в стек — если в стеке есть такая метка, то DF не станет отправлять трафик обратно в сегмент, из которого трафик получен. Но в VxLAN нет меток. Че делать? Механизм защиты от петель тут несколько изменен.

Как и в EVPN/MPLS интерфейсы, которые смотрят в один и тот же сегмент должны иметь один и тот же идентификатор — ESI. После обмена маршрутами типа 4, узлы находят своих партнеров по ESI (в отличии от MC-LAG их может быть больше двух) и выбирают DF, который будет слать широковещательный трафик в сегмент. Так как у нас нет меток, но мы знаем адреса соседей по ESI, то при получении широковещательного фрейма, коммутатор сначала смотрит, с какого сорс адреса прилетел пакет (то есть из какого туннеля). Если паке

© Habrahabr.ru