Сети для самых маленьких. Часть 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.
Серия «Сети для самых маленьких»
- Модели OSI и TCP/IP — зачем сетевой стек разбит на уровни и как данные обрастают заголовками по пути пакета.
- Ethernet — кадр по байтам, MAC-адреса и как коммутатор решает, в какой порт отправить кадр.
- Wi-Fi — чем радио отличается от кабеля, как клиент подключается к точке доступа и как защищается эфир.
- PPPoE — как провайдер заворачивает сессию абонента в Ethernet и откуда берётся MTU 1492.
- IPv4: адреса, маски и подсети — как читать адрес и маску, делить сеть на подсети и решать, нужен ли шлюз.
- IPv4: заголовок, маршрутизация и NAT — как роутер выбирает маршрут для пакета и как вся квартира выходит в интернет с одного адреса.
- ARP — как по IP-адресу соседа узнать его MAC-адрес и почему соседа так легко подменить.
- ICMP — служебные сообщения IP, как на самом деле работают ping и traceroute и что ломается, когда их режут.
- UDP — восемь байт заголовка, порты и почему отправка без соединения иногда лучше.
- TCP — как из ненадёжного IP получается надёжный поток байтов и почему потеря пакета режет скорость.
- DHCPv4 — как машина без адреса получает адрес, маску, шлюз и DNS четырьмя сообщениями.
- DNS — как имя превращается в адрес: дерево зон, рекурсивные серверы, записи и кеширование.
- IPv6: адреса и заголовок — как записываются 128-битные адреса, какие они бывают и чем заголовок IPv6 отличается от IPv4.
- ICMPv6 и Neighbor Discovery — как в IPv6 без ARP и широковещания находят соседей и роутер.
- SLAAC — как хост собирает себе адрес IPv6 из объявления роутера без всякого сервера.
- DHCPv6 — зачем DHCP, если есть SLAAC, и как провайдер выдаёт домашнему роутеру целый блок сетей.
- VLAN — как один коммутатор и один кабель несут несколько независимых сетей.
- VXLAN (эта статья) — как растянуть сеть Ethernet через роутеры, завернув кадры в UDP.
Оставить комментарий могут только зарегистрированные пользователи.
Войдите на сайт или зарегистрируйтесь, чтобы оставить комментарий.