Зачем VXLAN
Классический [[vlan-and-trunk|VLAN]] - L2-сегмент в одном broadcast domain'е, ограничен:
- 12-битный VLAN ID = 4094 сетей (мало для cloud-provider'а)
- Не пересекает L3 границы (нужно тянуть L2 через дата-центры)
- Spanning-tree convergence медленный
В дата-центре нужно: тысячи изолированных L2-сегментов, поверх любой L3 сети, без stretched-VLAN. VXLAN (Virtual Extensible LAN, RFC 7348) - стандартное решение:
- L2 в L3-туннеле: Ethernet-кадр инкапсулируется в UDP/4789
- 24-битный VNI = 16 777 216 сегментов
- Может ходить через любой роутер - underlay видит обычный UDP
Применяется в: CNI-плагинах (flannel/calico VXLAN-mode), Open vSwitch, EVPN-VXLAN дата-центрах, OpenStack Neutron.
Как пакет летит
VM-A (10.0.0.5) → outer: UDP/4789 → VM-B (10.0.0.6)
│ │
inner Ethernet inner Ethernet
src MAC=A, dst MAC=B encap src MAC=A, dst MAC=B
IP src 10.0.0.5 ──► ┌──────────────┐ ──► decap IP src 10.0.0.5
IP dst 10.0.0.6 │ outer Ether │ IP dst 10.0.0.6
│ outer IP │
│ UDP src=hash │
│ UDP dst=4789 │
│ VXLAN VNI │
│ inner frame │
└──────────────┘
Endpoints, делающие encap/decap, называются VTEP (VXLAN Tunnel EndPoint). Это либо хосты (host-based VTEP, Linux kernel умеет), либо ToR-коммутаторы (hardware VTEP).
Outer UDP source port = хеш inner-полей → нужен для ECMP в underlay (балансировщик видит "разные" UDP-flow-ы).
VXLAN header (8 байт)
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|R|R|R|R|I|R|R|R| Reserved |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| VNI (24 bits) | Reserved |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- I-flag = 1 если VNI valid
- VNI - 24 бита, идентификатор overlay-сети
BUM-трафик: как переслать broadcast в overlay
В обычном L2 broadcast/unknown-unicast/multicast (BUM) идёт всем в сегменте. В VXLAN сегмент распределён по нодам - как доставить ARP-запрос всем VTEP'ам с этим VNI?
Два подхода:
1. Multicast underlay (RFC default)
Каждому VNI назначается underlay multicast group. VTEP'ы подписываются на этот multicast, BUM шлётся туда. Underlay должен поддерживать IP multicast (PIM-SM). На практике в облаках (AWS/GCP/Azure) multicast не работает - этот режим живёт только в on-prem.
2. Head-end replication (HER, "ingress replication")
VTEP знает список всех других VTEP'ов с этим VNI. BUM-фрейм копируется и отправляется юникастом каждому. Дороже по трафику, но не требует multicast в underlay. Дефолт в EVPN-VXLAN, OpenStack, большинстве CNI.
Список remote VTEP'ов задаётся:
- Статически (FDB-записи в Linux:
bridge fdb add ... dst <remote-ip>) - Динамически (EVPN BGP)
EVPN-VXLAN - control plane через BGP
Чистая VXLAN spec - data plane без control plane. EVPN (RFC 7432, + RFC 8365 для VXLAN) добавляет [[bgp|BGP]]:
- Каждый VTEP анонсирует через MP-BGP свои MAC-адреса (Type 2 routes)
- VTEP-обнаружение через Type 3 routes
- Multi-tenant routing (Type 5) - L3 за overlay'ем
Преимущества:
- Нет flood-and-learn (классический Ethernet) - MAC сразу известны
- MAC mobility - VM мигрирует, BGP анонсирует новую locality
- EVPN multihoming - server в двух ToR одновременно
Реализации: Cisco NX-OS, Arista EOS, FRR (Free Range Routing) на Linux, [[cni-plugins|cilium]] cluster mesh.
Linux VXLAN
Создать VXLAN-интерфейс с multicast underlay:
ip link add vxlan100 type vxlan \
id 100 \
dstport 4789 \
group 239.1.1.100 \
dev eth0 \
ttl 16
ip link set vxlan100 up
ip addr add 10.200.0.1/24 dev vxlan100
С head-end replication (no multicast):
ip link add vxlan100 type vxlan id 100 dstport 4789 dev eth0 nolearning
ip link set vxlan100 up
# вручную добавить remote VTEP (адрес другой ноды)
bridge fdb append 00:00:00:00:00:00 dev vxlan100 dst 192.168.1.20
bridge fdb append 00:00:00:00:00:00 dev vxlan100 dst 192.168.1.21
Зеро-MAC = "default" - BUM пойдёт всем перечисленным dst.
Часто VXLAN-интерфейс кладут в [[linux-bridge|bridge]] вместе с [[veth-pair|veth]] от контейнеров - получается distributed L2-сегмент.
VXLAN vs альтернативы
| Технология | L2/L3 | Header overhead | Underlay требует | Multitenancy |
|---|---|---|---|---|
| VLAN | L2 | 4 байта | один L2 | 4K сегментов |
| VXLAN | L2 over L3 | 50 байт | IP unicast | 16M VNI |
| GENEVE | L2 over L3 | 50+ байт (variable TLV) | IP unicast | 16M VNI |
| [[gre-tunnel|GRE]] | L2/L3 over L3 | 24 байта | IP unicast | через GRE keys |
| [[ipsec-ike|IPsec]] | L3 over L3 | 50-80 байт | IP unicast | через SA |
GENEVE - "VXLAN второго поколения", добавляет TLV-extensions. NSX-T, OVN используют GENEVE. По сути взаимозаменяемо.
MTU - всегда боль
Underlay MTU должен быть ≥ overlay MTU + 50 байт overhead (или 14 байт без inner Ethernet, если только L3). На обычной сети 1500:
underlay MTU = 1500
VXLAN overhead = 50
pod/VM MTU = 1450
Если pod шлёт 1500-байтный пакет (стандарт Ethernet) → outer пакет 1550 → дроп где-то на underlay'е, blackhole.
Решения:
- Уменьшить overlay MTU до 1450 (что делает flannel автоматически)
- Включить jumbo frames на underlay (1500 → 9000) → overlay MTU 9000-50
- MSS clamping в [[mtu-and-pmtud|iptables/nftables]] на VTEP
- GSO segmentation в ядре - крупный TCP-сегмент бьётся на несколько ≤ overlay MTU автоматически
Когда что-то пошло не так
- Pod/VM cross-node не пингуется, intra-node ок - VXLAN underlay
блокирован.
tcpdump -ni eth0 udp port 4789на обеих сторонах, проверь firewall между нодами. - MTU blackhole - SSH работает,
apt updateзависает. См. [[mtu-and-pmtud|MTU и PMTUD]]. - MAC flapping - в логе
bridgeсообщения "received packet on vxlanX with own address as source". Часто loop в underlay (ARP-пакет вернулся на тот же VTEP) или неправильная EVPN-конфигурация. bridge fdb showпустой - flood-and-learn не работает (например вnolearningрежиме). Нужны явные FDB-записи или EVPN.- VNI collision между tenant'ами - одинаковый VNI = одна сеть. Используй неперекрывающиеся диапазоны.
- Multicast не работает в облаке (AWS/GCP) - переключайся на head-end replication.
- Performance - VXLAN encap делается в kernel (
vxlanмодуль). Проверьethtool -K eth0 tx-udp_tnl-segmentation onдля NIC offload (большинство modern Intel/Mellanox умеют).