Мережі датацентру й хмари
Навіщо це
Section titled “Навіщо це”Ви запускаєте два контейнери на різних серверах, і вони бачать одне одного за IP-адресами так, ніби сидять в одному комутаторі. Віртуальну машину переносять на іншу стійку, і вона зберігає адресу та відкриті з’єднання. Запит до одного веб-сервісу породжує сотню внутрішніх запитів між серверами, яких користувач ніколи не побачить. У мережі, спроєктованій для офісу, нічого з цього не працює, а можливим воно стало завдяки ідеям, розібраним у цьому модулі.
Майже всі ці ідеї складаються з уже знайомого: мости й veth
(модуль 4), маршрутизація й ECMP (модуль 7),
NAT (модуль 9), UDP (модуль 11).
Новизна в масштабі й у тому, що цей набір автоматизовано.
Передумови. Комутація й STP (модуль 4), маршрутизація й ECMP (модуль 7), NAT і conntrack (модуль 9), MTU й фрагментація (модуль 6). Про простори імен і контейнери — у модулі 17 курсу «Операційні системи»: віртуалізація й контейнери.
Чому дерево не масштабується
Section titled “Чому дерево не масштабується”Класичну корпоративну мережу будують деревом із трьох шарів. Сервери під’єднані до комутаторів доступу, ті до агрегації, агрегація до ядра. Трафік у такій мережі здебільшого йшов «північ–південь»: від користувача всередину, до сервера й назад, тож вузьке місце було вгорі, біля виходу назовні, і там ставили найпотужніше обладнання.
Датацентр інший. Більша частина трафіку йде «схід–захід»: між серверами всередині будівлі. Запит користувача розходиться на десятки сервісів, розподілене сховище реплікує дані, задача машинного навчання обмінюється градієнтами між сотнями машин. Такий трафік дерево обслуговує погано.
- Перепідписка. Кожен шар угору має менше смуги, ніж сумарно споживають нижні. Сервери під одним комутатором доступу спілкуються швидко, а ті, що на різних гілках, змагаються за вузьку смугу біля ядра.
- Нерівність шляхів. Залежно від розташування, кількість стрибків між двома серверами різна, отже різні затримки. Розробнику доводиться думати, на якій стійці стоїть його сервіс.
- STP. Дерево з резервними зв’язками вимагає, щоб зайві з’єднання були вимкнені, бо інакше виникають петлі (модуль 4). Виходить, що половина дорогих зв’язків простоює, доки щось не зламається.
- Ядро як межа масштабу. Щоб витримати більше, треба купити потужніший, і значно дорожчий, центральний пристрій, а його можливості обмежені.
Spine-leaf
Section titled “Spine-leaf”Вихід запозичено з телефонії, з ідеї комутаційної мережі Клоса (Clos): замість одного потужного центру багато простих комутаторів з’єднують так, щоб вони разом поводилися як один великий.
Сервери підключають лише до leaf-комутаторів (часто один стоїть нагорі стійки, звідси ToR, top of rack). Кожен leaf має зв’язок із кожним spine. Spine між собою не з’єднані й серверів не мають. Що з цього виходить:
- Будь-які два сервери на різних leaf розділяють рівно три пристрої: leaf, spine, leaf. Відстань однакова для всіх пар, тож затримка передбачувана й розміщення серверів не важить.
- Між двома leaf існує стільки незалежних шляхів, скільки spine. Вихід із ладу одного spine прибирає лише одну з N смуг.
- Ємність росте додаванням. Мало смуги — додайте spine, бракує портів для серверів — додайте leaf. Замінювати центр не треба.
Разом із цим відмовляються від STP: зв’язки між leaf і spine працюють на третьому рівні, кожен є маршрутизованим інтерфейсом із власною підмережею, а між пристроями діє динамічна маршрутизація (модуль 8), найчастіше BGP. Петель на третьому рівні немає, бо пакет має TTL. Шляхи ж використовуються одночасно, і цим займається ECMP.
Маршрутизатор має кілька рівноцінних шляхів до одного префікса, і встановлює їх усі (модуль 7). Перед ним стоїть питання, яким шляхом відправити конкретний пакет. Якщо розкидати пакети по черзі, пакети одного TCP-з’єднання приходитимуть у різному порядку, і TCP сприйме це як втрату. Тому шлях обирають за хешем полів пакета: той самий потік завжди йде тим самим шляхом, а різні потоки розподіляються статистично рівномірно.
Яке поле входить у хеш, вирішує налаштування. Якщо лише адреси відправника й отримувача, усі з’єднання між двома серверами потраплять в один шлях. Якщо ще й порти (5-кортеж: адреси, порти, протокол), різні з’єднання розкидаються. У розділі «Як це насправді в Linux» ви побачите обидва випадки.
Слабке місце ECMP у тому, що він працює з потоками, а не з байтами. Два величезні потоки, які випадково хеш поклав на один шлях, зіткнуться, хоча сусідній шлях простоює. Для датацентру з тривалими потоками (копіювання даних, навчання моделей) це реальна проблема, і для неї придумують додаткові прийоми: більше шляхів, розбиття потоку на короткі порції (flowlet), балансування за зайнятістю.
Оверлеї: VXLAN
Section titled “Оверлеї: VXLAN”Третій рівень у фабриці розв’язав проблему масштабу, але дещо зламав. Віртуальна машина, яку переносять на сервер під іншим leaf, опиняється в іншій IP-підмережі. Адреса мала б змінитися, з’єднання обірватися. Крім того, різним клієнтам хмари потрібні власні ізольовані мережі, де вони можуть вільно вибирати адреси, які перетинаються з чужими. VLAN (модуль 5) дає лише 4094 ідентифікатори, а також вимагає тягти рівень 2 крізь усю мережу, тобто повертає петлі й STP.
Розв’язують це оверлеєм (overlay): поверх маршрутизованої фабрики, яку називають підкладкою (underlay), будують віртуальні мережі. Початковий кадр Ethernet віртуальної машини загортають у нову IP-датаграму, звичайним маршрутизованим шляхом доставляють на сервер призначення й там розгортають. Підкладка бачить лише зовнішні заголовки й нічого не знає про віртуальні мережі. Найпоширеніша реалізація — VXLAN (RFC 7348).
Вузол, що загортає й розгортає кадри, називається VTEP (VXLAN Tunnel Endpoint). Це може бути Linux на сервері або leaf-комутатор. Заголовок VXLAN несе 24-бітний ідентифікатор віртуальної мережі VNI (VXLAN Network Identifier): це приблизно шістнадцять мільйонів мереж проти чотирьох тисяч у VLAN. Зовнішня датаграма йде звичайним UDP на порт 4789, тож фабрика маршрутизує її як будь-який інший IP-трафік. До того ж вихідний порт UDP обчислюють за хешем внутрішнього кадру, тож навіть оверлейний трафік між двома VTEP розкидається ECMP по різних шляхах: для фабрики це різні потоки.
Накладні витрати постійні: 14 байтів зовнішнього Ethernet, 20 IPv4, 8 UDP і 8 VXLAN — разом 50 байтів. Тому кадр із MTU 1500 всередині не влізе в підкладку з тим самим MTU 1500, і про це доводиться дбати окремо: або знижувати MTU внутрішніх інтерфейсів (типове 1450), або піднімати MTU підкладки (у датацентрах зазвичай так: jumbo-кадри близько 9000). Це та сама проблема, що й Path MTU Discovery з модуля 6, і на практиці вона так само незручна.
Залишається питання, куди надсилати кадр: VTEP мусить знати, за яким VTEP стоїть чужа MAC-адреса. Найпростіший варіант — навчання за потоком, як у комутатора (модуль 4): невідомий адресат розсилають усім VTEP, відповідь дає відповідність «MAC → VTEP». У великих мережах це дорого, і сучасні фабрики розповсюджують ці відповідності через BGP (розширення EVPN).
Мережа контейнерів
Section titled “Мережа контейнерів”Контейнер має власний простір імен мережі, отже власний стек: інтерфейси, адреси, таблицю маршрутів. Щоб він кудись достукався, цей простір треба з’єднати зі світом.
Міст + veth + NAT — типовий режим Docker. Docker створює на господарі
міст (docker0), для кожного контейнера пару veth: один кінець
у просторі контейнера, інший приєднаний до мосту. Контейнери отримують
адреси з приватної підмережі, а шлюзом служить міст. Щоб вийти в зовнішню
мережу, пакети проходять NAT: правило masquerade підставляє адресу
господаря (модуль 9). Щоб зовні дістатися контейнера,
публікують порт, і це вже DNAT із порту господаря в адресу й порт
контейнера. Жодної магії: усе це ви збираєте нижче за десять рядків.
macvlan обходить міст господаря: контейнер отримує власну MAC-адресу на фізичному інтерфейсі й виглядає в мережі як окрема машина, з адресою з вашої підмережі. Швидко й без NAT, але за замовчуванням сам господар не може зв’язатися з такими контейнерами через той самий інтерфейс, і комутатор на порту має дозволяти кілька MAC-адрес.
Оверлей між господарями. Контейнери з різних машин мусять бачити одне одного. Тут і повертається VXLAN: міст на кожному господарі з’єднується тунелем із мостами інших, і контейнери опиняються в одній віртуальній мережі.
Kubernetes
Section titled “Kubernetes”Kubernetes ставить до мережі жорстку вимогу: кожен под (pod) має власну IP-адресу, і будь-який под може звернутися до будь-якого іншого за цією адресою без NAT, навіть якщо вони на різних вузлах. Вимога зручна для застосунків: порти не треба перепризначати, а адреса, яку под бачить у себе, збігається з тією, що бачать інші.
Виконувати її Kubernetes не вміє сам. Він делегує цю роботу
CNI-плагіну (Container Network Interface). Коли вузол запускає
под, то створює простір імен мережі й викликає плагін: той підключає простір
до мережі (пара veth, адреса з діапазону вузла) і налаштовує маршрути.
Різні плагіни реалізують мережу по-різному. Одні будують оверлей
на VXLAN (Flannel), інші розповсюджують маршрути до подів через BGP
без інкапсуляції (Calico), ще одні реалізують усе на eBPF (Cilium).
Вибір плагіна визначає накладні витрати, видимість і політики безпеки.
Поди недовговічні. Їх замінюють, переносять, масштабують, тож IP-адреса
пода не годиться для клієнтів. Для цього існує Service: стабільна
віртуальна адреса (ClusterIP) і назва в DNS, за якою ховається множина
подів. На кожному вузлі працює kube-proxy: він стежить за набором подів,
що стоять за Service, і записує в ядро правила, які підмінюють адресу
призначення віртуальної адреси на адресу одного зі справжніх подів,
тобто це DNAT із випадковим вибором. Правила зазвичай реалізовано
в iptables або IPVS. Якщо вони відстають від реального набору подів,
частина запитів іде на адреси подів, яких уже немає. Деякі плагіни (Cilium) замінюють
kube-proxy програмою eBPF, яка вирішує те саме без ланцюжка правил.
Шлях пакета між подами на різних вузлах
Section titled “Шлях пакета між подами на різних вузлах”Щоб скласти картину докупи, простежимо, що відбувається, коли под A на вузлі 1 надсилає запит до Service, за яким стоїть под B на вузлі 2.
-
Под A звертається до віртуальної адреси Service. Пакет виходить з простору імен пода через
vethна вузол. -
На вузлі 1 правила
kube-proxy(або програма eBPF) переписують адресу призначення з віртуальної на адресу пода B. Запис про це зберігає conntrack (модуль 9), щоб відповідь повернулася тим самим шляхом. -
Пакет із адресою пода B маршрутизується вузлом. Залежно від CNI він або йде звичайним маршрутом (Calico з BGP), або потрапляє в тунель VXLAN до вузла 2 (Flannel).
-
Вузол 2 доставляє пакет у
vethпода B. Відповідь іде назад, і conntrack на вузлі 1 повертає їй адресу Service, тож под A бачить відповідь саме від тієї адреси, до якої звертався.
Усе це звичайні механізми цього курсу (простір імен, veth, маршрути, NAT,
інколи VXLAN), лише з автоматичним керуванням. Коли щось не працює, діагностика йде тими самими кроками:
де пакет зник, який маршрут чи правило його відкинуло, чи не підмінили
адресу не там, де треба.
У традиційному комутаторі два завдання живуть в одному корпусі: площина керування (control plane) вирішує, як пересилати, за протоколами на кшталт OSPF і BGP, а площина даних (data plane) виконує рішення на швидкості каналу. Кожен пристрій окремо вирішує за себе, і мережа як ціле не має одного місця, де її можна описати.
Програмно-визначена мережа (SDN) ділить ці площини. Керування виносять у контролер, який має повну картину мережі, а пристрої перетворюються на виконавців: контролер записує в їхні таблиці правила, а пристрої пересилають за ними. Найвідоміший протокол такого запису — OpenFlow. На Linux роль програмованого комутатора відіграє Open vSwitch.
Так мережу можна змінювати з програми: контролер розгортає віртуальну мережу клієнта хмари, додає правила безпеки для нового контейнера, переналаштовує шляхи. Але контролер стає ще однією критичною системою, а мережа — програмою, яку можна зламати помилкою. На практиці «чистий» SDN зустрічається рідше, ніж його ідеї: оверлеї, якими керує центральна система, декларативна конфігурація фабрики й програмовані комутатори.
XDP та eBPF у мережі
Section titled “XDP та eBPF у мережі”Кожен пакет, який ядро отримує з мережевої карти, проходить довгий
шлях: виділення sk_buff, обробка netfilter, маршрутизація, сокет. Якщо
треба відкинути мільйони пакетів DDoS за секунду або розкидати
їх між серверами, вартість цього шляху стає основною.
XDP (eXpress Data Path) дозволяє приєднати програму eBPF до драйвера
мережевої карти, і вона бачить пакет ще до виділення sk_buff. Програма
повертає вердикт: пропустити (XDP_PASS), відкинути (XDP_DROP),
повернути з того самого інтерфейсу (XDP_TX) або переспрямувати на
інший (XDP_REDIRECT). Верифікатор доводить, що програма завершиться й не
вийде за межі пам’яті (модуль 18 курсу «Операційні системи»
розповідає про механізм eBPF докладніше). У датацентрах на XDP будують
балансувальники L4 і фільтри DDoS, а плагіни CNI на eBPF вставляють
політики й балансування в ядро замість ланцюжків iptables.
Автоматизація й мережа як код
Section titled “Автоматизація й мережа як код”Фабрику з сотнею leaf і десятком spine вручну не налаштуєш. Мережу описують як дані й код. Бажаний стан записують у файлах (адреси, підмережі, сусіди BGP), шаблони перетворюють його на конфігурації пристроїв, а інструменти (Ansible, Terraform, протоколи NETCONF і gNMI з моделями YANG) застосовують їх. Так мережа отримує те, що давно мають програми: історію змін у Git, рецензування, відтворюваність і відкат.
Надійним цей підхід робить ідемпотентність: повторне застосування тієї самої конфігурації нічого не змінює й зайвого не додає. Так само важить декларативність: ви описуєте, яким має бути результат, а не послідовність команд. Тоді розбіжність між записаним і справжнім станом (drift) можна виявити й усунути автоматично.
Перевіряти зміни на справжній мережі страшно. Тому їх проганяють на моделі:
мережеві операційні системи запускають у контейнерах, а топологію
описують у файлі. Інструмент containerlab робить саме це: у YAML ви
перелічуєте вузли й з’єднання між ними, а він створює контейнери й
з’єднує їх парами veth. Це природний наступний крок після просторів
імен цього курсу. Принцип той самий, але замість голого Linux у вузлі
працює образ справжньої мережевої ОС, з яким можна відтворити фабрику з
цього модуля.
Як це насправді в Linux
Section titled “Як це насправді в Linux”Усе нижче запущено в просторах імен на одній машині. Мережа, що розгортається, вміщається в мегабайти.
VXLAN між двома «серверами»
Section titled “VXLAN між двома «серверами»”Два простори імен (dc-s1, dc-s2) відіграють роль серверів, з’єднаних
підкладкою 192.168.100.0/24. У кожному є віртуальна машина
(dc-vm1, dc-vm2) за мостом, який з’єднаний тунелем VXLAN з VNI 10.
for n in dc-s1 dc-s2 dc-vm1 dc-vm2; do ip netns add $n; ip -n $n link set lo up; doneip link add u1 type veth peer name u2ip link set u1 netns dc-s1; ip link set u2 netns dc-s2ip -n dc-s1 addr add 192.168.100.1/24 dev u1; ip -n dc-s1 link set u1 upip -n dc-s2 addr add 192.168.100.2/24 dev u2; ip -n dc-s2 link set u2 up
for i in 1 2; do ip -n dc-s$i link add vx10 type vxlan id 10 local 192.168.100.$i \ remote 192.168.100.$((3-i)) dstport 4789 ip -n dc-s$i link add br10 type bridge ip -n dc-s$i link set vx10 master br10 ip link add vm$i type veth peer name vmp$i ip link set vm$i netns dc-vm$i; ip link set vmp$i netns dc-s$i ip -n dc-s$i link set vmp$i master br10 ip -n dc-s$i link set vx10 up; ip -n dc-s$i link set br10 up; ip -n dc-s$i link set vmp$i up ip -n dc-vm$i addr add 10.10.10.$i/24 dev vm$i; ip -n dc-vm$i link set vm$i updoneip netns exec dc-vm1 ping -c2 -W1 10.10.10.2PING 10.10.10.2 (10.10.10.2) 56(84) bytes of data.64 bytes from 10.10.10.2: icmp_seq=1 ttl=64 time=0.377 ms64 bytes from 10.10.10.2: icmp_seq=2 ttl=64 time=0.093 msВіртуальні машини в одній підмережі 10.10.10.0/24, але між ними не
Ethernet-кабель, а маршрутизована підкладка. ttl=64 не зменшився: для
ВМ це один L2-сегмент. Що побачила підкладка:
ip netns exec dc-s2 tcpdump -nn -e -v -c 2 -i u2 udp &ip netns exec dc-vm1 ping -c1 10.10.10.2... ethertype IPv4 (0x0800), length 148: (... proto UDP (17), length 134) 192.168.100.1.46964 > 192.168.100.2.4789: VXLAN, flags [I] (0x08), vni 10a6:0c:84:20:3a:54 > 32:7d:06:23:6e:a8, ethertype IPv4 (0x0800), length 98: (... proto ICMP (1), length 84) 10.10.10.1 > 10.10.10.2: ICMP echo request, id 3146, seq 1, length 64Кадр довжиною 148 байтів: внутрішній кадр (98 байтів) плюс 50 байтів
заголовків. Зовнішній рівень: UDP від 192.168.100.1 до 192.168.100.2
на порт 4789 із vni 10. Усередині видно внутрішній Ethernet і ICMP між
адресами ВМ. Порт відправника 46964 обчислено за хешем внутрішнього
потоку, про який ішлося вище.
Обіцяну проблему MTU теж легко побачити. Підкладка має MTU 1500, а внутрішній інтерфейс ВМ теж, тож повний кадр із 50 байтами накладних витрат не пройде:
ip netns exec dc-vm1 ping -c1 -W1 -M do -s 1472 10.10.10.2ip netns exec dc-vm1 ping -c1 -W1 -M do -s 1422 10.10.10.2PING 10.10.10.2 (10.10.10.2) 1472(1500) bytes of data.From 10.10.10.2 icmp_seq=1 Frag needed and DF set (mtu = 1450)PING 10.10.10.2 (10.10.10.2) 1422(1450) bytes of data.1430 bytes from 10.10.10.2: icmp_seq=1 ttl=64 time=0.199 msПакет 1500 байтів не проходить, 1450 проходить: сума цього пакета й накладних витрат (50 байтів) якраз дорівнює MTU підкладки. Відповідь «Frag needed» Linux повертає сам тунельний інтерфейс, від імені віддаленого адресата, щоб TCP зміг підлаштувати розмір сегмента.
Таблиця пересилання моста й тунелю показує, що «MAC → VTEP» вивчено:
ip netns exec dc-s1 bridge fdb show | grep vx1032:7d:06:23:6e:a8 dev vx10 master br1032:7d:06:23:6e:a8 dev vx10 dst 192.168.100.2 self00:00:00:00:00:00 dev vx10 dst 192.168.100.2 self permanentРядок із нульовою MAC-адресою — запис за замовчуванням: усе, що не вивчено (у тому числі широкомовні кадри), відправляється на цей VTEP. Рядок із конкретною MAC вивчено з першого ж кадру, який прийшов.
Прибрати:
for n in dc-s1 dc-s2 dc-vm1 dc-vm2; do ip netns del $n; doneECMP: два spine і хеш
Section titled “ECMP: два spine і хеш”Мінімальна фабрика: два leaf, два spine. Між dc-lf і dc-lf2
два рівноцінні шляхи, по одному через кожен spine. Маршрут на dc-lf
до адреси 10.9.9.9 (петлі на dc-lf2) має два nexthop.
ip -n dc-lf route show 10.9.9.910.9.9.9 nexthop via 10.0.1.2 dev a1 weight 1 nexthop via 10.0.2.2 dev a2 weight 1Надсилаємо сто UDP-потоків з різними вихідними портами (40000–40099) і дивимося лічильники прийнятих пакетів на інтерфейсах spine. Спершу з налаштуванням за замовчуванням:
ip netns exec dc-lf sysctl net.ipv4.fib_multipath_hash_policynet.ipv4.fib_multipath_hash_policy = 0За політики 0 хеш рахується лише за адресами відправника й отримувача. Після ста потоків на spine 1 додалося рівно сто пакетів, на spine 2 нуль: усе пішло одним шляхом. Перемикаємо на 5-кортеж:
ip netns exec dc-lf sysctl -qw net.ipv4.fib_multipath_hash_policy=1Тепер ті самі сто потоків розподілилися приблизно порівну: на spine 1 додалося 57 пакетів, на spine 2 — 44. Рівно порівну хеш не розкладає, бо він статистичний; звідси й слабкість ECMP на великих потоках.
Docker без Docker: міст, veth і NAT
Section titled “Docker без Docker: міст, veth і NAT”Кроки, які робить Docker, відтворюються в чотирьох просторах імен:
господар (dc-host), два «контейнери» і зовнішній світ (dc-out).
ip -n dc-host link add br0 type bridgeip -n dc-host addr add 172.17.0.1/16 dev br0; ip -n dc-host link set br0 upfor i in 1 2; do ip link add hv$i type veth peer name cv$i ip link set hv$i netns dc-host; ip link set cv$i netns dc-c$i ip -n dc-host link set hv$i master br0 up ip -n dc-c$i addr add 172.17.0.$((i+1))/16 dev cv$i; ip -n dc-c$i link set cv$i up ip -n dc-c$i route add default via 172.17.0.1doneip netns exec dc-host sysctl -qw net.ipv4.ip_forward=1# зовнішня ділянка ho (203.0.113.1) <-> oh (203.0.113.99) налаштована так самоip netns exec dc-host nft -f - <<'E'table ip nat { chain post { type nat hook postrouting priority 100; ip saddr 172.17.0.0/16 oifname "ho" masquerade; } chain pre { type nat hook prerouting priority -100; iifname "ho" tcp dport 8080 dnat to 172.17.0.2:80; }}EКонтейнери бачать одне одного через міст, а назовні виходять із
підміненою адресою. На стороні dc-out зазирнемо в tcpdump, коли
dc-c1 пінгує зовнішній світ:
IP 203.0.113.1 > 203.0.113.99: ICMP echo request, id 3988, seq 1, length 64IP 203.0.113.99 > 203.0.113.1: ICMP echo reply, id 3988, seq 1, length 64Зовні видно адресу господаря 203.0.113.1, а не 172.17.0.2. Таблицю
відстеження з’єднань бачить conntrack -L на господарі:
icmp 1 29 src=172.17.0.2 dst=203.0.113.99 type=8 code=0 id=3988 src=203.0.113.99 dst=203.0.113.1 type=0 code=0 id=3988 ...Праворуч зворотний напрям: відповідь повертається на 203.0.113.1, і
ядро за записом повертає її на 172.17.0.2. Опублікований порт
перевіряємо зі стороннього простору:
ip netns exec dc-c1 python3 -m http.server 80 --bind 172.17.0.2 &ip netns exec dc-out curl -s -o /dev/null -w '%{http_code}\n' http://203.0.113.1:8080/200Запит на порт 8080 господаря потрапив до контейнера на порт 80: це й є
-p 8080:80 у Docker. Контейнер бачить запит від зовнішньої адреси, а
не від господаря, бо DNAT міняє лише адресу призначення. Поверніть
усе на місце: зупиніть http.server і видаліть простори імен
(dc-host, dc-c1, dc-c2, dc-out).
Для macvlan достатньо одного рядка на господарі:
ip link add mv0 link eth0 type macvlan mode bridge. Створення такого
інтерфейсу поверх veth у просторі імен працює, а от коректні адреси
й доступність ззовні залежать від вашої фізичної мережі.
Типові помилки розуміння
Section titled “Типові помилки розуміння”Spine-leaf просто швидший за дерево. Швидкість каналів може бути та сама. Різниця в тому, що між будь-якою парою leaf є однакова кількість рівноцінних шляхів і мережа росте додаванням однакових блоків. Швидкий канал у дереві однаково впирається в перепідписку.
ECMP розподіляє навантаження порівну. Він розподіляє потоки, а не байти. Два великі потоки можуть потрапити на один шлях, а інший шлях простоюватиме. Різні політики хешування дають різні результати, як видно з досліду: за хеша лише за адресами всі потоки між двома хостами йшли одним шляхом.
VXLAN шифрує трафік. Інкапсуляція нічого не шифрує. Внутрішній кадр
у підкладці лежить у відкритому вигляді, як видно в tcpdump. Шифрування
додають окремо, наприклад IPsec або WireGuard.
MTU у тунелі лишається 1500. Оверлей додає 50 байтів, отже внутрішній MTU мусить бути меншим або MTU підкладки більшим. Інакше великі пакети губляться, а дрібні працюють, і це важко діагностувати.
Контейнер із портом 8080:80 слухає на 8080. Всередині контейнера
слухається порт 80. Порт 8080 господаря відображається на нього правилом
DNAT, і в самому контейнері 8080 жодного сокета немає.
Service у Kubernetes — це процес, який проксіює трафік. Адреса Service
віртуальна: на жодному інтерфейсі її немає, а пакети до неї переписуються
правилами ядра на адресу одного з подів. Якщо пакет не доходить, то
перевіряють правила iptables або IPVS і маршрути, а не процес.
SDN означає, що мережа більше не потребує протоколів маршрутизації. Часто вона їх лишає, а контролер керує поверх. Фабрики spine-leaf найчастіше працюють на BGP без централізованого контролера взагалі.
Перевір себе
Лабораторна
Section titled “Лабораторна”Окремої лабораторної для цього модуля немає. Практика, яка спирається на
нього, — у вправах розділу «Як це насправді в Linux»: VXLAN між двома
просторами імен, ECMP із двома spine й контейнерна мережа з нуля. Міст і
veth, потрібні для цього, ви вже будували в
B1, NAT — у B2.
Джерела
Section titled “Джерела”- Kurose, Ross, Computer Networking: A Top-Down Approach, розділ про мережі датацентрів
- Peterson, Davie, Computer Networks: A Systems Approach, розділи про оверлеї, SDN й безпеку
- RFC 7348, Virtual eXtensible Local Area Network (VXLAN)
- Al-Fares, Loukissas, Vahdat, A Scalable, Commodity Data Center Network Architecture, SIGCOMM 2008 (приклад мережі на основі fat-tree/Clos)
- Документація Kubernetes: Cluster Networking і Services
- Специфікація CNI
- Документація Docker про мережі
- Документація containerlab
man ip-link(розділиvxlan,macvlan),man bridge,man nft- Документація ядра:
Documentation/networking/vxlan.rst,Documentation/networking/ip-sysctl.rst(fib_multipath_hash_policy)