9. VLAN, VXLAN и сегментация сети
«Сети подобны луковице: они состоят из слоев, и когда начинаешь их препарировать — текут слезы».
— Инженерный фольклор сетевых архитекторов
Представьте современный многоквартирный жилой комплекс. Все жильцы пользуются одними и теми же физическими коммуникациями: едиными стояками водоснабжения, общими шахтами электропроводки и общим подъездом. Но никому не придет в голову объединить все квартиры в одну гигантскую общую комнату: между ними возведены прочные железобетонные стены с надежными замками. Каждый жилец чувствует себя в полной изоляции и безопасности.
В компьютерных сетях эта физическая изоляция исторически строилась на втором уровне (L2) с помощью VLAN (Virtual Local Area Network): сетевые пакеты помечались цифровыми бирками-тегами прямо внутри коммутаторов.
Но что делать, если ваша компания — это не один дом, а глобальная распределенная корпорация с сотнями дата-центров по всему миру? Что делать, если виртуальная машина или контейнер с бэкендом на Go, запущенный в ЦОД во Франкфурте, должен общаться с контейнером в Токио так, словно они воткнуты в один и тот же локальный коммутатор за соседней стеной? Протянуть сплошной кабель L2 через континенты невозможно: широковещательные штормы и петли коммутации уничтожат сеть за секунды.
На стыке этих требований родилась концепция оверлейных сетей и протокол VXLAN (Virtual Extensible LAN): технология, упаковывающая целые локальные Ethernet-кадры внутрь стандартных UDP-пакетов маршрутизируемого интернета.
Для Go-разработчика, создающего микросервисы в облаках и Kubernetes, сегментация сети перестает быть абстракцией системных администраторов. Размер полезной нагрузки пакетов (MTU), оверхед туннелирования, поведение пулов соединений в net.Dialer, загадочные обрывы соединений с ошибками TIME_WAIT или message too long — всё это прямое следствие работы оверлеев и сегментации. В этой лекции мы разложим по полочкам механику VLAN и VXLAN и разберем, как сетевой стек Go взаимодействует с виртуализированной инфраструктурой.
VLAN (802.1Q): Аппаратная сегментация на L2
Протокол VLAN (Virtual Local Area Network), стандартизированный комитетом IEEE как 802.1Q, позволяет разделить один физический сетевой коммутатор на несколько независимых логических сегментов — виртуальных широковещательных доменов (Broadcast Domains).
flowchart TD
classDef process fill:#1e293b,stroke:#38bdf8,stroke-width:1px,color:#f8fafc
classDef success fill:#064e3b,stroke:#34d399,stroke-width:1px,color:#f8fafc
classDef error fill:#7f1d1d,stroke:#f87171,stroke-width:1px,color:#f8fafc
classDef warning fill:#78350f,stroke:#fbbf24,stroke-width:1px,color:#f8fafc
classDef entry fill:#1e3a5f,stroke:#38bdf8,stroke-width:2px,color:#f8fafc
classDef aux fill:#334155,stroke:#64748b,stroke-width:1px,color:#f8fafc
classDef system fill:#312e81,stroke:#a78bfa,stroke-width:1px,color:#f8fafc
classDef data fill:#132d29,stroke:#2dd4bf,stroke-width:1px,color:#f8fafc
classDef network fill:#881337,stroke:#fb7185,stroke-width:1px,color:#f8fafc
classDef accent fill:#1e1b4b,stroke:#818cf8,stroke-width:1px,color:#f8fafc
subgraph PhysicalSwitch ["Физический коммутатор L2 (IEEE 802.1Q)"]
Port1["Порт 1 (Access VLAN 10)"]
Port2["Порт 2 (Access VLAN 10)"]
Port3["Порт 3 (Access VLAN 20)"]
Port4["Порт 4 (Trunk: VLAN 10 + 20)"]
end
subgraph ProdNet ["VLAN 10: Production"]
GoApp1["Go Сервер (Prod 1)"]
GoApp2["Go Сервер (Prod 2)"]
end
subgraph DevNet ["VLAN 20: Development"]
GoDev["Go Сервер (Dev Test)"]
end
subgraph Uplink ["Магистральный транк"]
Router["Маршрутизатор L3 / Core Switch"]:::warning
end
GoApp1 --- Port1
GoApp2 --- Port2
GoDev --- Port3
Port4 --- Router
Для бэкенд-инфраструктуры это означает, что на одной физической стойке серверов можно одновременно разместить production-окружение, staging и тестовые контуры dev без физической прокладки отдельных кабелей. Трафик разработчиков физически не может попасть в сеть продакшена на уровне L2, даже если злоумышленник попытается перехватить ARP-запросы или отправить broadcast-пакеты.
Коммутатор различает два основных типа портов:
- Access-порты (немаркированные): Обычные порты, к которым подключаются серверы. Сетевая карта сервера отправляет классический Ethernet-кадр без всяких тегов. Коммутатор при приеме кадра сам навешивает тег нужного VLAN.
- Trunk-порты (магистральные / тегированные): Высокоскоростные порты между коммутаторами или аплинками к серверам виртуализации, по которым передаются кадры сразу многих VLAN с обязательной маркировкой.
Устройство тега
Когда немаркированный Ethernet-кадр попадает в транковый порт, сетевой коммутатор на лету врезает в него дополнительный 4-байтный тег 802.1Q. Тег вставляется строго между адресом источника (Source MAC) и полем типа протокола EtherType:
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| TPID (0x8100) |PCP|D| VID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Тег состоит из двух ключевых полей по 2 байта:
- TPID (Tag Protocol Identifier, 2 байта): Всегда содержит фиксированное значение
0x8100. Для сетевого адаптера это сигнал: «Внимание, этот кадр содержит тег 802.1Q, следующие 2 байта — служебная информация». - TCI (Tag Control Information, 2 байта):
- Priority Code Point (PCP, 3 бита): Приоритет качества обслуживания (QoS / CoS по стандарту IEEE 802.1p). Позволяет приоритезировать чувствительный голосовой (VoIP) или финансовый трафик перед фоновой передачей файлов.
- Drop Eligible Indicator (DEI / CFI, 1 бит): Флаг отбрасывания пакета при перегрузке очередей коммутатора.
- VID (VLAN Identifier, 12 бит): Номер виртуальной сети. Поскольку поле занимает 12 бит, максимальное число значений составляет $2^{12} = 4096$.
Значения0(приоритетный трафик без привязки к VLAN) и4095зарезервированы стандартом. В результате инженерам доступно ровно4094уникальные виртуальные сети.
Влияние на Go-приложения
На первый взгляд кажется, что 4 байта тега VLAN — это сугубо аппаратная деталь коммутаторов. Но для сетевого кода на Go это источник коварных скрытых проблем:
flowchart LR
classDef process fill:#1e293b,stroke:#38bdf8,stroke-width:1px,color:#f8fafc
classDef success fill:#064e3b,stroke:#34d399,stroke-width:1px,color:#f8fafc
classDef error fill:#7f1d1d,stroke:#f87171,stroke-width:1px,color:#f8fafc
classDef warning fill:#78350f,stroke:#fbbf24,stroke-width:1px,color:#f8fafc
classDef entry fill:#1e3a5f,stroke:#38bdf8,stroke-width:2px,color:#f8fafc
classDef aux fill:#334155,stroke:#64748b,stroke-width:1px,color:#f8fafc
classDef system fill:#312e81,stroke:#a78bfa,stroke-width:1px,color:#f8fafc
classDef data fill:#132d29,stroke:#2dd4bf,stroke-width:1px,color:#f8fafc
classDef network fill:#881337,stroke:#fb7185,stroke-width:1px,color:#f8fafc
classDef accent fill:#1e1b4b,stroke:#818cf8,stroke-width:1px,color:#f8fafc
subgraph StandardEth ["Стандартный Ethernet-кадр (MTU = 1500)"]
EthHdr1["Eth Header (14B)"]
Payload1["IP-пакет / Данные Go (до 1500 байт)"]
EthFCS1["FCS (4B)"]
end
subgraph TaggedEth ["Кадр с тегом VLAN 802.1Q"]
EthHdr2["Eth Header (14B)"]
VLAN_Tag["802.1Q Tag (4B)"]
Payload2["IP-пакет (MTU по-прежнему 1500 байт)"]
EthFCS2["FCS (4B)"]
end
1. VLAN-тег и MTU (почему MTU не уменьшается)
Стандартный максимальный размер полезной нагрузки Ethernet-кадра составляет 1500 байт. Добавление 4-байтного заголовка 802.1Q увеличивает общий размер кадра с 1518 до 1522 байт (IEEE 802.3ac), а MTU остаётся равным 1500: на VLAN-подинтерфейсе Linux (ip link add link eth0 name eth0.10 type vlan id 10) вы увидите mtu 1500. Цена тега — не 4 байта MTU, а требование к оборудованию: порты и коммутаторы должны принимать кадры до 1522 байт («Baby Giant Frames»). Если какое-то устройство на пути режет кадры по старому пределу 1518 байт, большие пакеты теряются — это и есть «чёрная дыра», а не «MTU 1496» на хосте.
Что увидит Go-сервис, если отправить UDP-датаграмму больше MTU? Само по себе превышение MTU ошибки message too long не вызывает: ядро фрагментирует IP-пакет (датаграмма 1473–65507 байт при Write уходит успешно). EMSGSIZE (message too long) возникает, если выставлен запрет фрагментации (IP_PMTUDISC_DO/флаг DF) или размер превышает 65 507 байт (для IPv4).
В протоколах TCP и HTTP (net/http) при передаче больших тел ответов с заголовком Content-Length несовпадение MTU приводит к «черным дырам» PMTU Discovery: соединение зависает посреди передачи данных, а клиент бесконечно ждет завершения ответа.
2. Изоляция широковещательных доменов (Broadcast Domains)
VLAN изолирует широковещательный трафик. Это необходимо для локализации штормов ARP, однако может нарушить работу механизмов обнаружения сервисов (mDNS, SSDP, Gossip-протоколы кластеров), если сервисы случайно разнесены по разным VLAN.
В микросервисах на Go со стандартным резолвером net.Resolver рассинхронизация VLAN между нодами приводит к периодическим таймаутам DNS-запросов.
VXLAN: Программная сегментация поверх L3
В начале 2010-х годов с бурным взрывом публичных облаков (AWS, Google Cloud) и технологий контейнеризации ограничения классического VLAN стали непреодолимой стеной:
- Жесткий лимит 4094 сетей: В облаке с десятками тысяч независимых клиентов 4094 идентификаторов катастрофически не хватает.
- Ограничение L2-домена: Классический VLAN не может выйти за пределы одного коммутатора или L2-сегмента. Нельзя прозрачно переместить виртуалку или под Kubernetes из одного дата-центра в другой с сохранением IP.
- Проблема Spanning Tree Protocol (STP): Чтобы избежать петель в L2-сетях, протокол STP принудительно блокирует до 50% физических линий связи, снижая пропускную способность ЦОД.
Инженерным ответом стал протокол VXLAN (Virtual Extensible LAN, RFC 7348). Архитектурный принцип VXLAN гениально прост: инкапсулировать целый L2 Ethernet-кадр внутрь стандартного L3/L4 UDP-пакета (техника MAC-in-UDP)!
flowchart TD
classDef process fill:#1e293b,stroke:#38bdf8,stroke-width:1px,color:#f8fafc
classDef success fill:#064e3b,stroke:#34d399,stroke-width:1px,color:#f8fafc
classDef error fill:#7f1d1d,stroke:#f87171,stroke-width:1px,color:#f8fafc
classDef warning fill:#78350f,stroke:#fbbf24,stroke-width:1px,color:#f8fafc
classDef entry fill:#1e3a5f,stroke:#38bdf8,stroke-width:2px,color:#f8fafc
classDef aux fill:#334155,stroke:#64748b,stroke-width:1px,color:#f8fafc
classDef system fill:#312e81,stroke:#a78bfa,stroke-width:1px,color:#f8fafc
classDef data fill:#132d29,stroke:#2dd4bf,stroke-width:1px,color:#f8fafc
classDef network fill:#881337,stroke:#fb7185,stroke-width:1px,color:#f8fafc
classDef accent fill:#1e1b4b,stroke:#818cf8,stroke-width:1px,color:#f8fafc
subgraph Overlay ["Overlay-сеть (Виртуальный L2 для Go-подов)"]
PodA["Pod A (10.244.1.5)"]
PodB["Pod B (10.244.2.8)"]
PodA <-->|"Иллюзия прямого L2-кабеля (Один широковещательный домен)"| PodB
end
subgraph Underlay ["Underlay-сеть (Физическая L3 IP-магистраль дата-центра)"]
VTEP1["Host 1 VTEP (192.168.10.1)"]
SpineSwitch["Физические маршрутизаторы Spine-Leaf (BGP / OSPF)"]
VTEP2["Host 2 VTEP (192.168.20.1)"]
VTEP1 <-->|"UDP/IP Туннель Port 4789"| SpineSwitch
SpineSwitch <-->|"UDP/IP Туннель Port 4789"| VTEP2
end
PodA -.->|"Внутренний кадр"| VTEP1
PodB -.->|"Внутренний кадр"| VTEP2
Сеть разделяется на два независимых слоя:
- Underlay-сеть (Физическая основа): Стандартная физическая сеть дата-центра с IP-маршрутизацией (Spine-Leaf архитектура на протоколах BGP или OSPF).
- Overlay-сеть (Виртуальный слой): Программно-определяемая виртуальная сеть, в которой живут контейнеры и виртуальные машины.
Узлы, выполняющие упаковку и распаковку пакетов, называются VTEP (VXLAN Tunnel End Point). В Kubernetes роль VTEP обычно выполняет сетевой интерфейс хоста (например, flannel.1), управляемый CNI-плагином.
Устройство VXLAN-пакета
Каждый оригинальный Ethernet-кадр, сгенерированный приложением, оборачивается в многослойную «матрешку» внешних заголовков:
flowchart LR
classDef process fill:#1e293b,stroke:#38bdf8,stroke-width:1px,color:#f8fafc
classDef success fill:#064e3b,stroke:#34d399,stroke-width:1px,color:#f8fafc
classDef error fill:#7f1d1d,stroke:#f87171,stroke-width:1px,color:#f8fafc
classDef warning fill:#78350f,stroke:#fbbf24,stroke-width:1px,color:#f8fafc
classDef entry fill:#1e3a5f,stroke:#38bdf8,stroke-width:2px,color:#f8fafc
classDef aux fill:#334155,stroke:#64748b,stroke-width:1px,color:#f8fafc
classDef system fill:#312e81,stroke:#a78bfa,stroke-width:1px,color:#f8fafc
classDef data fill:#132d29,stroke:#2dd4bf,stroke-width:1px,color:#f8fafc
classDef network fill:#881337,stroke:#fb7185,stroke-width:1px,color:#f8fafc
classDef accent fill:#1e1b4b,stroke:#818cf8,stroke-width:1px,color:#f8fafc
OuterEth["Внешний Ethernet (14B, не входит в оверхед MTU)"]:::process --> OuterIP["Внешний IP (20B)"]
OuterIP --> OuterUDP["Внешний UDP: Port 4789 (8B)"]
OuterUDP --> VXLAN_Hdr["VXLAN Header: VNI (8B)"]
VXLAN_Hdr --> InnerEth["Внутренний Ethernet-кадр пода: заголовок 14B + Payload"]
- VXLAN Header (8 байт): Содержит служебные флаги и главное поле — VNI (VXLAN Network Identifier) разрядностью 24 бита!
В отличие от жалких 4094 сетей в VLAN, 24 бита VNI дают $2^{24} = 16\,777\,216$ уникальных виртуальных сетей! Этого с избытком хватает для изоляции миллионов клиентов любого глобального облака. - Outer UDP Header (8 байт): Порт назначения по стандарту IANA (RFC 7348) равен
4789; если при создании VXLAN-интерфейса в Linux не указатьdstport, ядро использует собственное нестандартное значение по умолчанию8472(его же по умолчанию берут и некоторые оверлеи, например flannel). Исходный порт выбирается как хэш от внутренних заголовков пакета. - Outer IP Header (20 байт для IPv4 / 40 байт для IPv6): Реальные IP-адреса хостов-отправителей и получателей туннеля (VTEP).
- Inner Ethernet Header (14 байт): VXLAN переносит целый внутренний Ethernet-кадр пода, и его 14-байтный заголовок тоже вычитается из MTU underlay. Внешний Ethernet-заголовок (MAC-адреса серверов и шлюзов underlay) в оверхед MTU не входит: MTU считается по IP-пакету.
Итоговый суммарный оверхед туннелирования (8 VXLAN + 8 UDP + 20 IP + 14 внутренний Ethernet):
$$\mathbf{8 + 8 + 20 + 14 = 50 \text{ байт}}$$
Почему UDP, а не TCP или ESP?
Почему создатели VXLAN выбрали в качестве транспорта именно легковесный протокол UDP, а не защищенный IPsec ESP или надежный TCP?
- Беспрепятственный проход через NAT (NAT Traversal): UDP-пакеты прозрачно проходят через любые бытовые и промышленные маршрутизаторы с трансляцией адресов (8. NAT, PAT и почему приватные сети работают через один IP). В отличие от протоколов вроде GRE (IP-протокол 47) или IPsec ESP (протокол 50), требующих сложной настройки conntrack, UDP поддерживается любым сетевым оборудованием мира.
- Балансировка нагрузки через ECMP (Middlebox Compatibility): В современных ЦОД коммутаторы распределяют трафик по параллельным путям с помощью ECMP. Коммутатор хэширует 5 полей заголовка (5-tuple). Генерация псевдослучайного Source Port в UDP-заголовке VXLAN позволяет физическим коммутаторам идеально равномерно балансировать трафик разных виртуальных подов по всем 100-гигабитным линкам фабрики!
- Аппаратная акселерация (Hardware Offloading): Современные сетевые адаптеры Intel, Mellanox и Broadcom аппаратно распознают заголовки VXLAN. Сетевая карта сама распаковывает туннель и вычисляет контрольные суммы (UDP Checksum Offload), снижая накладные расходы процессора хоста до ничтожных
~0.5%на поток данных.
Сегментация в экосистеме Go и контейнеризации
В современных облачных средах Kubernetes сегментация и оверлеи реализуются через плагины стандарта CNI (Container Network Interface) — Calico, Cilium, Flannel.
flowchart TD
classDef process fill:#1e293b,stroke:#38bdf8,stroke-width:1px,color:#f8fafc
classDef success fill:#064e3b,stroke:#34d399,stroke-width:1px,color:#f8fafc
classDef error fill:#7f1d1d,stroke:#f87171,stroke-width:1px,color:#f8fafc
classDef warning fill:#78350f,stroke:#fbbf24,stroke-width:1px,color:#f8fafc
classDef entry fill:#1e3a5f,stroke:#38bdf8,stroke-width:2px,color:#f8fafc
classDef aux fill:#334155,stroke:#64748b,stroke-width:1px,color:#f8fafc
classDef system fill:#312e81,stroke:#a78bfa,stroke-width:1px,color:#f8fafc
classDef data fill:#132d29,stroke:#2dd4bf,stroke-width:1px,color:#f8fafc
classDef network fill:#881337,stroke:#fb7185,stroke-width:1px,color:#f8fafc
classDef accent fill:#1e1b4b,stroke:#818cf8,stroke-width:1px,color:#f8fafc
GoApp["Go Приложение: net.Dial('tcp', 'service:8080')"]:::network --> NetResolver["net.Resolver (CoreDNS)"]
NetResolver --> Syscall["socket() + connect()"]
Syscall --> VethPair["Интерфейс veth (Пространство имен пода)"]
VethPair --> HostRouting["Таблица маршрутов хоста (ip route)"]
HostRouting --> TunnelDev["Туннельный интерфейс flannel.1 / cilium_vxlan"]
TunnelDev --> Netfilter["Инкапсуляция VXLAN (Ядро / eBPF)"]
Netfilter --> PhysNIC["Физическая сетевая карта eth0 (Кадр MTU 9000)"]
Как Go видит эту сеть
Когда ваше приложение на Go выполняет сетевой запрос:
conn, err := net.Dial("tcp", "service:8080")
- Резолвинг адреса: Рантайм Go через внутренний механизм
net.Resolverобращается к кластерному DNS-серверу (CoreDNS). - Создание сокета: Структура
net.Dialerвызывает системные вызовы ядраsocket(AF_INET, SOCK_STREAM, IPPROTO_TCP)иconnect(). - Маршрутизация ядра: Ядро Linux сверяется с таблицей маршрутизации
ip routeсетевого пространства имен пода. Пакет выходит через виртуальную паруvethна физический хост. - Туннелирование: На хосте маршрут указывает на интерфейс
flannel.1или виртуальный адаптер Cilium. Ядро операционной системы (в подсистеме Softnet или через программы eBPF) перехватывает пакет, навешивает заголовки VXLAN с нужным номером VNI и отправляет UDP-датаграмму через физическую картуeth0.
Диагностика MTU и сетевых интерфейсов в Go
Следующий законченный пример демонстрирует, как сервис на Go может программно инспектировать локальные сетевые интерфейсы, выявлять заниженные значения MTU (характерные для туннелей VXLAN) и безопасно обрабатывать сетевые ошибки с таймаутами:
package main
import (
"context"
"errors"
"fmt"
"log"
"net"
"net/http"
"time"
)
// Проверка значений MTU сетевых адаптеров хоста
func auditInterfaceMTU() {
// Функция net.Interfaces обращается к ядру Linux через системный протокол netlink
ifaces, err := net.Interfaces()
if err != nil {
log.Printf("Ошибка вызова net.Interfaces: %v", err)
return
}
fmt.Println("=== Аудит сетевых интерфейсов и параметров MTU ===")
for _, iface := range ifaces {
status := "Стандартный MTU"
if iface.MTU < 1500 && iface.MTU > 0 {
status = "⚠️ Заниженный MTU (Вероятно, оверлей VXLAN или Docker bridge!)"
} else if iface.MTU >= 9000 {
status = "🚀 Jumbo Frames (Дата-центр / High-Performance)"
}
fmt.Printf("Интерфейс: %-12s | MTU: %-5d | Статус: %s\n",
iface.Name, iface.MTU, status)
}
}
// Пример надежного выполнения запроса через клиент net/http.Client в изолированных сетях
func queryInternalService(ctx context.Context, targetURL string) error {
// Обязательно настраиваем тайм-ауты в net.Dialer для предотвращения утечки горутин
dialer := &net.Dialer{
Timeout: 3 * time.Second,
KeepAlive: 30 * time.Second,
}
// Транспорт создаётся один раз и переиспользуется; в реальном сервисе его
// выносят из функции. Proxy нужно задать явно: у нулевого Transport он nil,
// в отличие от http.DefaultTransport.
transport := &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: dialer.DialContext,
TLSHandshakeTimeout: 3 * time.Second,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
}
client := &http.Client{
Transport: transport,
Timeout: 5 * time.Second,
}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, targetURL, nil)
if err != nil {
return fmt.Errorf("ошибка создания запроса: %w", err)
}
resp, err := client.Do(req)
if err != nil {
// Анализ типа сетевой ошибки уровня ядра
var netErr net.Error
var opErr *net.OpError
if errors.As(err, &opErr) {
log.Printf("[СЕТЕВОЙ СБОЙ L4] Ошибка операции %s для адреса %s: %v",
opErr.Op, opErr.Addr, opErr.Err)
}
if errors.As(err, &netErr) && netErr.Timeout() {
return fmt.Errorf("таймаут обращения к сервису (возможна изоляция NetworkPolicy): %w", err)
}
return fmt.Errorf("сетевой сбой доставки пакета: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode >= 500 {
return fmt.Errorf("сервис вернул ошибку сервера: статус %d", resp.StatusCode)
}
fmt.Printf("[УСПЕХ] Запрос к %s выполнен успешно! Код ответа: %d\n", targetURL, resp.StatusCode)
return nil
}
func main() {
auditInterfaceMTU()
ctx, cancel := context.WithTimeout(context.Background(), 6*time.Second)
defer cancel()
fmt.Println("\n=== Тестовое обращение к внутреннему эндпоинту ===")
_ = queryInternalService(ctx, "http://127.0.0.1:8080/healthz")
}
Итог
Сегментация сети — это фундамент информационной безопасности, мультитенантности и масштабируемости современных облачных инфраструктур:
- VLAN (802.1Q): Классическая аппаратная изоляция на втором уровне (L2). Добавляет 4-байтный тег с кодом
0x8100, разделяя свитч максимум на 4094 сети. Максимальный размер кадра растёт с 1518 до 1522 байт; MTU (1500) не меняется. - VXLAN (RFC 7348): Современный стандарт облачных оверлеев (MAC-in-UDP). Расширяет пространство изоляции до 16 миллионов сетей за счет 24-битного идентификатора VNI.
- Оверхед туннелей: VXLAN добавляет ровно 50 байт к каждому пакету (
8 + 8 + 20 + 14 = 50 байт). В продакшене это требует обязательного включения Jumbo Frames (MTU 9000) для предотвращения фрагментации и «чёрных дыр» PMTU (ошибкаmessage too longвозникает при запрете фрагментации DF). - Транспорт UDP (порт 4789 / 8472): Гарантирует бесшовный проход через NAT, поддержку аппаратного offload на сетевых картах и балансировку ECMP на физических фабриках ЦОД.
- Роль Go-разработчика: Пакет
netабстрагирует детали туннелирования, но понимание реального MTU, механики CNI-интерфейсов (veth,flannel.1) и сокетных опций критично для исключения зависаний при высокой нагрузке.
Мы завершили фундаментальное погружение в основы физических, канальных и сетевых уровней (Блок 1, лекции 1–9). Мы проследили путь байта от кремниевых транзисторов сетевой карты через Ethernet-кадры, ARP/NDP, IP-адреса, таблицы маршрутизации, NAT-трансляторы и виртуальные туннели VXLAN.
Теперь наступает время подняться на транспортный уровень (L4) — уровень, на котором живет надежность, контроль очередей и гарантия целостности данных. В следующей лекции мы откроем Блок 2 и до винтика разберем самый важный протокол современного интернета: 10. TCP. Устройство, гарантии и жизненный цикл соединения.