Два напрямки трафіку, одна коробка
Привітання
Більшість діаграм архітектури показують трафік, що йде в одну сторону: клієнт зверху, сервер внизу, стрілка вниз. Реальність має на увазі, що трафік йде в обидві сторони.
Вхідний (Ingress): сторонні клієнти досягають ваші послуги через цей шлях. Інвертований проксі на межі вашої мережі завершує TLS, маршрутизує запити та виконує політику доступу.
Виїзний (Egress): ваші послуги досягають сторонніх послуг через цей шлях. Закликання процесора платежів, отримання вебхука, відправка запиту до партнера. Часто через прямий проксі або NAT-шляху з дозволеним списком.
Багато архітектур починаються з однієї коробки, яка обробляє обидва. Це працює, доки не настає день, коли це не працює. Файлове режим є субтильним, з'являється лише після того, як достатньо внутрішніх послуг існують, та вчить важливу урок про розділення забот.
Після закінчення цієї лекції ви зрозумієте:
- Чому вход та вихід представляють фундаментально різні трафіки з різними осями масштабування та різними режимами невдачі
- Hairpin NAT та чому проксі, яке намагається зв'язатися з собою, зазнає невдачі
- Архітектурна відкид: одна коробка стає двома, та що кожна з них потім виключно володіє
- Збереження безпеки: кожна сторона може закрити доступ до своїх справжніх дозволених партнерів
- Як ідентифікувати, коли ваша проектна коробка перейшла поріг, де розділення необхідне
Чому напрямки вимагають різних інструментів
Два різних навантажень на одній мережевій межі
Характеристики вхідного трафіку:
- Ініціюється сторонніми особами (інтернет у цілому)
- Об'єм зростає в пропорції з базою користувачів
- Завершення TLS, маршрутизація запиту, обмеження швидкості на джерело
- Забезпечення глибокої оборони: DDoS, зловживання, скрапінг
- Публічний IP повинен приймати з'єднання від будь-хто
Характеристики виїзного трафіку:
- Ініціюється вашими власними послугами (знайдений невеликий набір клієнтів)
- Об'єм зростає в пропорції з моделями звернення послуги до послуги та зовнішніх API
- Дозволення IP-адрес для доступу до джерела на віддалених кінцевих точках (у вас є одна фіксована вихідна IP, з якою партнери довіряють)
- Забезпечення глибокої оборони: витік даних, компрометовані внутрішні служби, що викликають вихід
- Повинні відхиляти підключення від інших, ніж власні служби
Ключова асиметрія: входження приймає трафік з усього світу; вихід приймає трафік лише від власних служб. Путовки їх на одну та саму машину означає, що ця машина повинна бути одночасно доступною з усього світу (для входження) та доступною лише від власних служб (для вихід). Правила файрволу, які задовольняють один, працюють проти іншого.
Розвиток шляху: дрібний проект може приховувати як входження, так і вихід позаду однієї IP та одного інструменту, тому що об'єм невеликий та партнерська IP-allowlist коротка. З ростом проекту збільшується протидія між двома ролями, а одного дня специфічна помилка (hairpin NAT) змушує розділитися.
The Bug That Forces the Split
Стерилізована історія відключення
Зображайте реальну архітектурну гілку, яка виникає в продуктивних флотиллях. Назви нижче змінені; форма ідентична тому, що команди зіштовхуються в дикому середовищі.
Організація працює на одній проксі-машині 203.0.113.5. Вона обробляє входження (порт 443 для користувачів) та вихід (порт 1080 SOCKS5 для внутрішніх служб, які викликають вихід). Внутрішні служби знаходяться у приватних підсетях та відправляють всі вихідні трафіки через SOCKS5 проксі на 203.0.113.5:1080.
Одна з служб, розміщених позаду 203.0.113.5, - api.example.com. Публічний DNS відображає api.example.com на 203.0.113.5.
Тепер інша внутрішня служба має зв'язатися з api.example.com. Її вихідна дорога:
1. Внутрішня служба відображає api.example.com → 203.0.113.5
2. Внутрішня служба відправляє запит через SOCKS5 вихідний проксі на 203.0.113.5:1080
3. Проксі намагається відкрити підключення від себе до 203.0.113.5:443
4. Відхилено підключення. Пакет повинен вийти та знову увійти в той самий NAT, що більшість мережевих стеків відхиляє. Проксі не може підключитися до себе через свою публічну IP.
Цей є волосинний NAT: пакет, який виходить з NAT та повинен знову увійти в той самий NAT, щоб досягти свого призначення. Без особливої підтримки волосинного шару в роутинговому рівні, пакет падає.
Чому це з'являється пізно
На ранніх етапах життя проекту кожна внутрішня служба either розмовляла з іншими внутрішніми службами за приватною назвою (internal-api.local) або не викликала свої власні організації публічні служби. Маршрут волосин просто не існував.
Тоді нова функція потребувала служби A, щоб дзвонити api.example.com (публічний хост). Маршрут волосин активувався. Відмова підключення. Вихід з ладу.
Рішення вирішило симптом (змушувати розв'язувач давати приватний IP api.example.com замість публічного). Коренева причина: одна коробка виконувала занадто багато робіт.
Архітектурний Вилук
Один Бокс Стає Двома
Чисте рішення: розділити проксі на дві машини.
Ingress server (публічний IP 203.0.113.5):
- Caddy / обернений проксі на портах 80, 443
- Публічні записи DNS вказують сюди
- Господар api.example.com, app.example.com, etc.
Egress server (інший публічний IP 203.0.113.99):
- SOCKS5 / прямий проксі на порту 1080
- Фільтр блокує входні з'єднання лише до внутрішніх підсетей IP
- Внутрішні служби відправляють всі вихідні через цю адресу
Що це купує:
1. Hairsin вирішено. Внутрішня служба, яка дзвонить api.example.com, відправляється вихідним через 203.0.113.99 (egress), який потім зв'язується звичайно з 203.0.113.5 (ingress, інший IP). Цикл NAT зникає тому, що дві IPs живуть на різних машинах.
2. Ізоляція безпеки. Фільтр egress-сервера може закрити доступ до невеликого набору внутрішніх IP. Фільтр ingress-сервера залишається відкритим для світу. Два окремих набори правил, кожен з яких виражає одну роль чисто.
3. Ізольоване збільшення масштабу. Об'єм ingress збільшується з користувачами; об'єм egress збільшується з внутрішньосервовою діяльністю. Змінювати один без торкання до іншого.
4. Ізольована невдача. Неправильно налаштований egress більше не порушує публічний сайт. DDoS проти публічного сайту більше не змушує egress-бандпут.
5. Чище розуміння моделі. Кожен пристрій має одну функцію. Інженери думають про питання входу без думки про вихід, та навпаки.
Два напрямки, дві рішення про розміщення
Незалежне збільшення
До розділення, збільшення в будь-якому напрямку стискало ту саму машину. Після розділення кожен напрямок має власне забезпечення.
Розміщення входу: збільшується з користувачами. Вирішення про потужність живуть у публічному рівні (більше зворотніх проксі-репліки, більш великі ВМ, CDN передній план). Бюджет потужності обчислюється проти трафіку користувачів на піку.
Розміщення виходу: збільшується з внутрішніх служінь до зовнішніх API-зв'язків. Часто домінує передача webhook, звернення до обробників платежів або витягів з третіх сторін. Бюджет потужності обчислюється проти патернів внутрішніх зв'язків.
Ізоляція провалів: DDoS проти публічного входу більше не їсть потужність виходу (ті звернення до обробників платежів проходять як би). Провал проксі-виходу більше не призводить до падіння публічного сайту (користувачі продовжують досягати сайту; тільки внутрішні вихідні зв'язки зриваються).
Різні СЛІ: доступність входу має значення для користувачів (видиме падіння сайту); доступність виходу має значення для операторів (темряви фонові провали, які можуть тривати довше для виявлення). Кожен бік може нести свій СЛІ.
Вільні проксі-вихідні сервери
Коли роль вихідного сервера є власною машиною, наступний очевидний крок - запустити кілька вихідних машин позаду балансатора завантаження для забезпечення HA. Кожен новий внутрішній служіння вказує на назву вихідного (яка відображає пул балансування завантаження) а не на одну IP.
Те ж навички, як у решти розподілених систем: коли рівень стає безстандартним та має власну роль, він збільшується дешево.
Новий партнерський інтеграція
Ваша організація використовує розділення ingress / egress як задано. Проксі-вихідний сервер має фіксовану публічну IP-адресу (203.0.113.99), яку ви дозволили трьом існуючим партнерським API (обробнику платежів, SMS-шлюзу, постачальнику електронної пошти).
Команда продукту хоче додати четверту інтеграцію: систему передачі вебhook, яка дзвонить до кінцевих точок клієнтів по всьому світу. Оцінка об'єму: 10 000 дзвінків на хвилину, з піковими значеннями до 30 000.
Організація меж мережі для зростаючої служби
Синтез
Ви вивчили, чому ingress та egress вимагають різних інструментів, хриплову NAT-шину, яка змушує розділити реальні флоти, та як незалежне масштабування, ізоляція безпеки та ізоляція збоїв накопичуються, коли розділена архітектура стає реальністю.
Застосуйте всі чотири.
Середня за розміром компанія SaaS працює над трьома піддоменами продукту (app, api, admin) для своїх користувачів, а також чотирма вихідними інтеграціями (Stripe, Twilio, SendGrid, система вебхук для клієнтів). Усі вони зараз знаходяться позаду однієї машини-проксі з одним публічним IP. Вони почали отримувати повідомлення про періодичні хриплові невдачі, коли внутрішні служби намагаються звернутися до api.example.com. Вони хочуть розробити постійне вирішення.
Куди йде наступний курс
Куди йде наступний курс
Тепер ви побачили одну з чистих рефактів розділення занять у розподілених системах: одна коробка стає двома, кожна з яких має чітку роль, та система отримує переваги масштабування, безпеки та ізоляції збоїв під час переходу.
Наступний урок (cs_distsys_failure_modes_and_blast_radius) розширить аргументацію щодо ізоляції збоїв. Ви прочитаєте саниновану DNS-SERVFAIL постмортем, визначите паттерн каскадного збою та напишете безпрецедентні заходи, які будуть спрямовані на системи замість людей.
Додаткова лекція: geometry_of_ingress_egress_separation перетворює розбивку на двоїстий граф та вивчає вершини розрізу, поділи мережі та те, що теорія графів каже вам про кордон мережі.
Добре зроблено. Надалі.