# VXLAN - L2 overlay поверх L3-сети _Сеть: L2 / L3 · LinuxLab Knowledge Base_ **TL;DR:** VXLAN - L2-overlay через UDP/4789. 24-битный VNI = 16M сегментов (vs 4K у VLAN). VTEP делает encap/decap. BUM-трафик идёт через multicast или head-end replication. EVPN-VXLAN - control plane через BGP. Underlay MTU 1550 минимум. ## Зачем 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 `) - Динамически (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. Решения: 1. **Уменьшить overlay MTU до 1450** (что делает flannel автоматически) 2. **Включить jumbo frames на underlay** (1500 → 9000) → overlay MTU 9000-50 3. **MSS clamping** в [[mtu-and-pmtud|iptables/nftables]] на VTEP 4. **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 умеют). ## Команды ```bash ip -d link show vxlan100 ``` Детали VXLAN-интерфейса: VNI, underlay интерфейс, dst port ```bash bridge fdb show dev vxlan100 ``` Forwarding database VXLAN'а - какие MAC через какой remote VTEP ```bash tcpdump -ni eth0 -nn udp port 4789 ``` Перехват VXLAN underlay-трафика - debug encap/decap ```bash ip link add vxlan100 type vxlan id 100 dstport 4789 group 239.1.1.100 dev eth0 ``` Создать VXLAN с multicast underlay group 239.1.1.100, VNI 100 ```bash bridge fdb append 00:00:00:00:00:00 dev vxlan100 dst 192.168.1.20 ``` Head-end replication: добавить remote VTEP для BUM-трафика ```bash ethtool -K eth0 tx-udp_tnl-segmentation on rx-udp_tnl-segmentation on ``` Включить NIC offload для VXLAN tunnels - меньше CPU ```bash ip link set vxlan100 mtu 1450 ``` Зафиксировать overlay MTU 1450 (1500 - 50 overhead) ```bash cat /sys/class/net/vxlan100/brif/* 2>/dev/null ``` Проверить bridge-membership VXLAN-интерфейса ## См. также - [CNI plugins - сеть Kubernetes (calico, cilium, flannel)](/kb/cni-plugins.md) - [VLAN и trunk - 802.1Q](/kb/vlan-and-trunk.md) - [Linux bridge - программный свитч](/kb/linux-bridge.md) - [MTU и Path MTU Discovery (PMTUD)](/kb/mtu-and-pmtud.md) - [UDP - User Datagram Protocol](/kb/udp-basics.md) - [GRE-туннели и IPIP - point-to-point поверх IP](/kb/gre-tunnel.md) - [BGP - Border Gateway Protocol](/kb/bgp.md)