Сети для самых маленьких. Часть 18: VXLAN

VLAN из прошлой части режет один коммутатор на много сетей. Но у него два ограничения, которые в дата-центре становятся стенами. Первое — номеров всего 4094, а облачный провайдер хочет изолированную сеть каждому клиенту, и клиентов у него сотни тысяч. Второе важнее: VLAN — это L2, и она заканчивается там, где начинается роутер. Виртуальная машина, переезжающая с сервера в одной стойке на сервер в другой, хочет сохранить IP-адрес и остаться в «своей» сети, а между стойками — маршрутизаторы. Растягивать L2 через весь дата-центр на VLAN и STP значит получить один огромный домен широковещания с одним деревом STP, и это не работает уже на нескольких сотнях коммутаторов.

VXLAN, Virtual eXtensible LAN, RFC 7348, решает обе задачи одним приёмом из первой части — протокол внутри протокола: кадр Ethernet заворачивается в UDP-датаграмму и едет через любую IP-сеть, как обычный пакет. Для хостов внутри это L2-сегмент, для сети снаружи — UDP-трафик между серверами.


Overlay и underlay

Два слова, без которых о VXLAN не говорят:

  • Underlay — физическая IP-сеть: коммутаторы, роутеры, маршруты между серверами. Ей всё равно, что она несёт.
  • Overlay — виртуальная сеть поверх неё: кадры виртуальных машин или контейнеров, которые думают, что подключены к общему коммутатору.

Точка, где одно превращается в другое, — VTEP (VXLAN Tunnel Endpoint): устройство или программа с адресом в underlay, которая берёт кадр из overlay, заворачивает его и отправляет другому VTEP, а полученное разворачивает и отдаёт в overlay. VTEP бывает в коммутаторе (аппаратный) и в ядре Linux, гипервизоре или Open vSwitch (программный). В облаке VTEP — каждый сервер виртуализации.

   VM-A 10.100.0.1                                                     VM-B 10.100.0.2
   MAC aa:…:01                                                         MAC bb:…:02
        │  overlay (VNI 100)                                      overlay  │
   ┌────┴──────────┐                                            ┌──────────┴────┐
   │ сервер 1      │                                            │ сервер 2      │
   │ VTEP          │                                            │ VTEP          │
   │ 198.51.100.2  │                                            │ 203.0.113.5   │
   └────┬──────────┘                                            └──────────┬────┘
        │  underlay: обычные IP-пакеты UDP 4789                            │
        └──────────── роутеры, сколько угодно хопов ───────────────────────┘

Пакет

Кадр от VM-A к VM-B в underlay выглядит так:

 ┌───────────┬───────────┬──────────┬──────────┬───────────────────────────────┐
 │ Ethernet  │ IP        │ UDP      │ VXLAN    │ исходный кадр Ethernet        │
 │ внешний   │ внешний   │ dst 4789 │ 8 байт   │ aa:…:01 → bb:…:02, IP, TCP, … │
 │ 14        │ 20        │ 8        │          │ (без FCS)                     │
 └───────────┴───────────┴──────────┴──────────┴───────────────────────────────┘
   MAC и IP VTEP-ов, src port = хеш от внутреннего кадра
  • Внешний IP — адреса VTEP-ов: 198.51.100.2 → 203.0.113.5. Underlay маршрутизирует по ним и о внутреннем кадре не знает.
  • Внешний UDP: порт назначения 4789 (зарегистрированный для VXLAN; Linux исторически использовал 8472, и это первое, что проверяют при «не работает между двумя реализациями»). Порт отправителя — хеш от адресов и портов внутреннего кадра. Это сделано нарочно: роутеры underlay балансируют трафик между равноценными путями по хешу от адресов и портов (мы встречали это в восьмой части, когда traceroute «прыгал» между путями), и если бы порт был постоянным, весь туннель между двумя VTEP шёл бы одним путём. С переменным портом разные потоки внутри туннеля раскладываются по разным линкам.
  • Заголовок VXLAN, 8 байт:
 ┌────────┬────────────────────┬────────────────────────┬────────┐
 │ флаги  │ зарезервировано    │ VNI                    │ резерв │
 │ 8 бит  │ 24 бита            │ 24 бита                │ 8 бит  │
 │ I = 1  │                    │ номер сети, 16 млн     │        │
 └────────┴────────────────────┴────────────────────────┴────────┘

Флаг I говорит, что VNI действителен, остальные нули. VNI (VXLAN Network Identifier) — аналог VID из VLAN, но 24 бита: 16 миллионов сетей вместо 4094.

  • Внутренний кадр — как был, с MAC-адресами виртуальных машин; только FCS отброшен, его посчитает внешний Ethernet.

Арифметика: 14 + 20 + 8 + 8 = 50 байт накладных расходов на IPv4 (70 на IPv6). Внутренний кадр с 1500 байтами данных становится внешним пакетом на 1550, и в underlay с MTU 1500 он не влезет. Два выхода: поднять MTU underlay до 1550 или jumbo 9000 (правильный, если underlay ваш), или опустить MTU overlay-интерфейсов до 1450 (единственный, если underlay чужой). Забыть про это — классика: ping ходит, большие передачи виснут, та самая чёрная дыра из восьмой части, только внутри туннеля.

В tcpdump на underlay-интерфейсе видно обе матрёшки сразу:

$ sudo tcpdump -i eth0 -n udp port 4789
IP 198.51.100.2.49152 > 203.0.113.5.4789: VXLAN, flags [I] (0x08), vni 100
ARP, Request who-has 10.100.0.2 tell 10.100.0.1, length 28
IP 203.0.113.5.52201 > 198.51.100.2.4789: VXLAN, flags [I] (0x08), vni 100
ARP, Reply 10.100.0.2 is-at bb:bb:bb:bb:bb:02, length 28
IP 198.51.100.2.49152 > 203.0.113.5.4789: VXLAN, flags [I] (0x08), vni 100
IP 10.100.0.1 > 10.100.0.2: ICMP echo request, id 1, seq 1, length 64

ARP из седьмой части, целиком, внутри UDP: для виртуальных машин это обычный сегмент Ethernet.


Как VTEP узнаёт, куда слать

Коммутатор во второй части учил таблицу «MAC → порт» по адресам отправителей. VTEP делает то же самое, только «порт» для него — адрес удалённого VTEP: получив кадр из туннеля, он запоминает «внутренний MAC bb:…:02 живёт за VTEP 203.0.113.5». Для известного unicast всё просто: завернуть и отправить тому VTEP.

Проблема — BUM-трафик: broadcast, unknown unicast, multicast. Коммутатор флудил его во все порты. Какие «порты» у VTEP? Все остальные VTEP с тем же VNI, а их может быть сотни, и они не в одном сегменте. Три способа:

Multicast в underlay. Каждому VNI сопоставляется групповой адрес, например 239.1.1.100; все VTEP с этим VNI подписываются на группу, и BUM-кадры заворачиваются в пакет на групповой адрес. Underlay доставляет его всем подписчикам, если умеет маршрутизировать multicast: для этого в нём должен работать протокол вроде PIM, которым роутеры строят дерево доставки от отправителя к подписчикам. В своём дата-центре это возможно, в чужом облаке — нет. Так VXLAN задуман в RFC.

Head-end replication. VTEP держит список остальных VTEP своего VNI и BUM-кадр отправляет каждому отдельно unicast-ом. Underlay не нужен multicast, зато при ста VTEP каждый ARP-запрос превращается в сто пакетов. Список задаётся руками или контроллером.

Оба способа вместе с обучением по кадрам называют flood-and-learn: VTEP узнаёт расположение MAC-адресов, глядя на трафик, как коммутатор. Для десятка VTEP годится, для тысячи — нет.

Control plane: EVPN. Вместо обучения по трафику VTEP-ы сообщают друг другу таблицы через протокол маршрутизации. Используется BGP — протокол, которым провайдеры обмениваются маршрутами (у меня о нём отдельная серия), — с расширением EVPN: каждый VTEP анонсирует «у меня в VNI 100 есть MAC aa:…:01 с IP 10.100.0.1» и «я участвую в VNI 100». Остальные получают это до того, как кадр вообще появился. Следствия: unknown unicast исчезает (все MAC известны заранее), а на ARP-запросы VTEP может отвечать сам из таблицы EVPN, не выпуская их в туннели (ARP suppression). Так устроены фабрики современных дата-центров, и в них underlay — чистый L3 между коммутаторами (spine-leaf: каждый leaf-коммутатор соединён с каждым spine, между ними только маршрутизация), а L2 существует только внутри VXLAN на границе.

Статические записи. Четвёртый вариант, без флуда и без BGP: внешняя программа, которая и так знает, где какая машина (оркестратор), прописывает VTEP-ам таблицы напрямую. Так работает Kubernetes.


Где это используется

  • Облака. Каждому клиенту — свои VNI; его машины на любых серверах видят друг друга в «своей» L2-сети, а соседей по серверу — нет. Миллионы сетей, адреса клиентов пересекаются (у всех 10.0.0.0/24), и это не проблема: они в разных VNI.
  • Дата-центры с фабрикой на EVPN: L2-сеть растягивается на все стойки без STP между коммутаторами, VM переезжает куда угодно с тем же адресом.
  • Kubernetes. Поды на разных узлах должны видеть друг друга по IP, а узлы могут стоять в сетях, где нельзя просто добавить маршруты. Сетевые плагины (Flannel в режиме vxlan, Calico в режиме VXLAN) заводят на каждом узле VTEP, назначают узлу подсеть подов и прописывают статические записи «подсеть узла B → VTEP B» из данных API-сервера. Ни флуда, ни BGP: оркестратор всё знает. Трафик под-под на разных узлах — это VXLAN между узлами на порту 4789 (или 8472 у Flannel), и его видно в tcpdump на узле. Docker Swarm делает то же для overlay-сетей.
  • Растягивание L2 между площадками для миграции VM. Технически возможно, практически опасно: домен широковещания с задержкой в 20 мс и одним шлюзом на две площадки — это и широковещательные штормы через WAN, и трафик, который ходит на другую площадку, чтобы вернуться на свою. Делают, но с оговорками.

Пара соседей по цеху, чтобы не путать: Geneve — преемник VXLAN с расширяемым заголовком (порт 6081), на нём работают OVN и NSX-T, идея та же; GRE — более старая инкапсуляция прямо в IP (протокол 47) без UDP, а значит, без энтропии для балансировки и с проблемами на NAT; VLAN — тег в кадре внутри одного L2, VXLAN — кадр в UDP через L3.


Чего в VXLAN нет

  • Шифрования и аутентификации. Внутренний кадр едет открытым, а VNI — просто число в заголовке: кто имеет доступ к underlay, тот может читать чужие сети и вбрасывать в них кадры с любым VNI. Изоляция держится на том, что underlay — закрытая сеть дата-центра. Через интернет VXLAN заворачивают в IPsec (следующая часть) или другой шифрованный туннель.
  • Защиты от того, что это всё ещё L2. Большой домен широковещания остаётся большим: ARP-штормы, петли внутри overlay, MAC flapping — всё из второй части, только теперь через роутеры.
  • Автоматического MTU. Overlay не знает, что он overlay.

И практическое: контрольная сумма внешнего UDP может быть нулевой (RFC разрешает для IPv4), многие сетевые карты считают и проверяют VXLAN аппаратно (offload), а файрволы underlay должны пропускать UDP 4789 между VTEP.


VXLAN между двумя Linux-хостами

Два сервера с адресами в underlay 198.51.100.2 и 203.0.113.5, между ними обычная маршрутизация. Точка-точка, без флуда — удалённый VTEP задан явно:

# сервер 1
$ sudo ip link add vxlan100 type vxlan id 100 local 198.51.100.2 remote 203.0.113.5 dstport 4789
$ sudo ip link set vxlan100 mtu 1450 up
$ sudo ip addr add 10.100.0.1/24 dev vxlan100

# сервер 2
$ sudo ip link add vxlan100 type vxlan id 100 local 203.0.113.5 remote 198.51.100.2 dstport 4789
$ sudo ip link set vxlan100 mtu 1450 up
$ sudo ip addr add 10.100.0.2/24 dev vxlan100

$ ping 10.100.0.2

vxlan100 — обычный Ethernet-интерфейс с MAC-адресом, ARP и всем остальным; просто его «кабель» — туннель. Если вместо адресов на нём поднять мост и подключить виртуальные машины, получится общий L2-сегмент для VM на двух серверах.

Несколько VTEP с head-end replication: remote не задаётся, а список соседей — в таблице FDB моста, записью с нулевым MAC «для флуда»:

$ sudo ip link add vxlan100 type vxlan id 100 local 198.51.100.2 dstport 4789
$ sudo bridge fdb append 00:00:00:00:00:00 dev vxlan100 dst 203.0.113.5
$ sudo bridge fdb append 00:00:00:00:00:00 dev vxlan100 dst 203.0.113.6

Теперь BUM уходит обоим, а unicast — туда, где MAC был выучен. Выученные записи видны в той же таблице с адресом VTEP вместо порта:

$ bridge fdb show dev vxlan100
00:00:00:00:00:00 dst 203.0.113.5 self permanent
00:00:00:00:00:00 dst 203.0.113.6 self permanent
bb:bb:bb:bb:bb:02 dst 203.0.113.5 self

Multicast-вариант — group 239.1.1.100 dev eth0 вместо remote; статический, как в Kubernetes, — nolearning при создании и bridge fdb add <mac> dev vxlan100 dst <vtep> на каждую машину.

Параметры интерфейса целиком: ip -d link show vxlan100 покажет id, local, remote или group, порт, learning/nolearning, udpcsum.


Что запомнить

  • VXLAN заворачивает кадр Ethernet в UDP (порт 4789) с 8-байтовым заголовком и 24-битным VNI: 16 миллионов L2-сетей поверх любой IP-сети. Overlay — виртуальные сети, underlay — физическая, VTEP — граница.
  • Накладные расходы 50 байт: MTU overlay 1450 или underlay 1550+. Порт отправителя — хеш для балансировки в underlay.
  • VTEP учит «MAC → адрес VTEP» по трафику; BUM-трафик — через multicast в underlay или head-end replication (flood-and-learn), либо таблицы приходят из control plane: EVPN на BGP в дата-центрах, статические записи от оркестратора в Kubernetes и Docker.
  • Шифрования нет: изоляция держится на закрытом underlay, через интернет — внутри IPsec. Overlay остаётся L2 со всеми его болезнями, только больше.
  • Linux: ip link add … type vxlan id 100 … dstport 4789, таблица — bridge fdb show dev vxlan100, захват — tcpdump udp port 4789 показывает обе матрёшки.

Дальше — IPsec и IKEv2: как шифровать пакеты на сетевом уровне, чтобы приложения об этом не знали. ESP и его режимы, Security Association и SPI, политики и селекторы, и четыре обмена IKEv2, которые договариваются о ключах, проверяют стороны и переживают NAT.


Серия «Сети для самых маленьких»

  1. Модели OSI и TCP/IP — зачем сетевой стек разбит на уровни и как данные обрастают заголовками по пути пакета.
  2. Ethernet — кадр по байтам, MAC-адреса и как коммутатор решает, в какой порт отправить кадр.
  3. Wi-Fi — чем радио отличается от кабеля, как клиент подключается к точке доступа и как защищается эфир.
  4. PPPoE — как провайдер заворачивает сессию абонента в Ethernet и откуда берётся MTU 1492.
  5. IPv4: адреса, маски и подсети — как читать адрес и маску, делить сеть на подсети и решать, нужен ли шлюз.
  6. IPv4: заголовок, маршрутизация и NAT — как роутер выбирает маршрут для пакета и как вся квартира выходит в интернет с одного адреса.
  7. ARP — как по IP-адресу соседа узнать его MAC-адрес и почему соседа так легко подменить.
  8. ICMP — служебные сообщения IP, как на самом деле работают ping и traceroute и что ломается, когда их режут.
  9. UDP — восемь байт заголовка, порты и почему отправка без соединения иногда лучше.
  10. TCP — как из ненадёжного IP получается надёжный поток байтов и почему потеря пакета режет скорость.
  11. DHCPv4 — как машина без адреса получает адрес, маску, шлюз и DNS четырьмя сообщениями.
  12. DNS — как имя превращается в адрес: дерево зон, рекурсивные серверы, записи и кеширование.
  13. IPv6: адреса и заголовок — как записываются 128-битные адреса, какие они бывают и чем заголовок IPv6 отличается от IPv4.
  14. ICMPv6 и Neighbor Discovery — как в IPv6 без ARP и широковещания находят соседей и роутер.
  15. SLAAC — как хост собирает себе адрес IPv6 из объявления роутера без всякого сервера.
  16. DHCPv6 — зачем DHCP, если есть SLAAC, и как провайдер выдаёт домашнему роутеру целый блок сетей.
  17. VLAN — как один коммутатор и один кабель несут несколько независимых сетей.
  18. VXLAN (эта статья) — как растянуть сеть Ethernet через роутеры, завернув кадры в UDP.

Оставить комментарий могут только зарегистрированные пользователи.

Войдите на сайт или зарегистрируйтесь, чтобы оставить комментарий.