Модуль 1.5: Від моноліту до мікросервісів
Складність:
[ШВИДКО]- Архітектурні концепціїЧас на виконання: 30-35 хвилин
Пререквізити: Модуль 3 (Що таке Kubernetes?)
Що ви зможете зробити
Розділ «Що ви зможете зробити»Після вивчення цього модуля ви зможете:
- Порівняти монолітну та мікросервісну архітектури з конкретними компромісами для кожної
- Пояснити, як функції Kubernetes (Services, Deployments, масштабування) відповідають потребам мікросервісів
- Визначити, коли моноліт є правильним вибором (не все має бути мікросервісами)
- Описати виклики, які приносять мікросервіси (складність мережі, розподілене налагодження, узгодженість даних)
Чому це важливо
Розділ «Чому це важливо»У 2001 році компанія Amazon вперлася у стіну масштабування. Їхній масивний монолітний додаток на C++ та Perl під назвою «Obidos» став настільки складним, що прості оновлення функцій вимагали тижнів координації, а розгортання регулярно призводило до збоїв у роботі сайту. Ця криза спровокувала знаменитий мандат Джеффа Безоса щодо API 2002 року, який змусив усі команди відкривати свої дані лише через суворі мережеві інтерфейси. Цей болісний перехід до того, що ми зараз називаємо мікросервісами, врятував швидкість їхньої розробки та, зрештою, дав початок AWS.
Kubernetes був спеціально створений для вирішення саме тих операційних жахів, з якими зіткнулися такі компанії, як Amazon і Google, запускаючи тисячі розподілених сервісів. Розуміння еволюції від монолітів до мікросервісів допоможе вам:
- Точно знати, чому існують функції Kubernetes (наприклад, Services, Ingress та Probes) для вирішення проблем розподілених систем.
- Приймати кращі архітектурні рішення залежно від розміру команди та зрілості продукту.
- Розуміти, коли моноліт є правильним вибором (заощаджуючи тисячі годин непотрібних інженерних витрат).
- Розмовляти мовою сучасної архітектури програмного забезпечення.
Моноліт
Розділ «Моноліт»Що таке моноліт?
Розділ «Що таке моноліт?»Монолітний додаток — це єдина одиниця розгортання, що містить усю функціональність:
┌─────────────────────────────────────────────────────────────┐│ МОНОЛІТНИЙ ДОДАТОК │├─────────────────────────────────────────────────────────────┤│ ││ ┌─────────────────────────────────────────────────────┐ ││ │ MyApp.jar (або .exe) │ ││ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ ││ │ │ Модуль │ │ Модуль │ │ Модуль │ │ Модуль │ │ ││ │ │ Користу-│ │ Продук- │ │ Замов- │ │ Плате- │ │ ││ │ │ вачів │ │ тів │ │ лень │ │ жів │ │ ││ │ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │ ││ │ │ │ │ │ │ ││ │ └───────────┴───────────┴───────────┘ │ ││ │ │ │ ││ │ ┌────────┴────────┐ │ ││ │ │ База даних │ │ ││ │ │ (спільна) │ │ ││ │ └─────────────────┘ │ ││ └─────────────────────────────────────────────────────┘ ││ ││ Розгортання: Однією одиницею ││ Масштабування: Все або нічого ││ База даних: Спільна для всіх модулів ││ │└─────────────────────────────────────────────────────────────┘Переваги моноліту
Розділ «Переваги моноліту»✅ Простий у розробці на початкових етапах✅ Легко тестувати (один додаток)✅ Просте розгортання (один артефакт)✅ Легко налагоджувати (один процес)✅ Відсутність мережевих затримок між компонентами✅ ACID-транзакції реалізуються простоВиклики моноліту (при масштабуванні)
Розділ «Виклики моноліту (при масштабуванні)»❌ Зміни вимагають повного перерозгортання❌ Довгі цикли збірки та тестування❌ Масштабування означає масштабування всього відразу❌ Вибір технологій впливає на весь додаток❌ Одна помилка може призвести до збою всього додатка❌ Координація команд стає важкою❌ Кодова база стає некерованоюМікросервісний підхід
Розділ «Мікросервісний підхід»Що таке мікросервіси?
Розділ «Що таке мікросервіси?»Мікросервіси розбивають додаток на малі незалежні сервіси:
┌─────────────────────────────────────────────────────────────┐│ МІКРОСЕРВІСНА АРХІТЕКТУРА │├─────────────────────────────────────────────────────────────┤│ ││ ┌───────────┐ ┌───────────┐ ┌───────────┐ ││ │ Сервіс │ │ Сервіс │ │ Сервіс │ ││ │ Користу- │ │ Продук- │ │ Замов- │ ││ │ вачів │ │ тів │ │ лень │ ││ │ ┌─────┐ │ │ ┌─────┐ │ │ ┌─────┐ │ ││ │ │ БД │ │ │ │ БД │ │ │ │ БД │ │ ││ │ └─────┘ │ │ └─────┘ │ │ └─────┘ │ ││ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ ││ │ │ │ ││ └───────────────┼───────────────┘ ││ │ ││ ┌───────┴───────┐ ││ │ API Gateway │ ││ └───────────────┘ ││ │ ││ Клієнти ││ ││ Розгортання: Кожен сервіс незалежно ││ Масштабування: Для кожного сервісу за потребою ││ База даних: Кожен сервіс володіє своїми даними ││ │└─────────────────────────────────────────────────────────────┘Переваги мікросервісів
Розділ «Переваги мікросервісів»✅ Незалежне розгортання✅ Масштабування окремих сервісів✅ Різноманітність технологій (правильний інструмент для завдання)✅ Ізоляція збоїв (падіння одного сервісу ≠ падіння всього)✅ Автономія команд✅ Менші, фокусовані кодові базиВиклики мікросервісів
Розділ «Виклики мікросервісів»❌ Складність мережі❌ Відмови в розподілених системах❌ Проблеми з узгодженістю даних❌ Тестування стає складнішим❌ Операційна складність❌ Налагодження між сервісами❌ Потреба у надійній інфраструктуріЗупиніться та подумайте: Стартап із 5 осіб створює свій перший продукт. Чи варто їм використовувати мікросервіси з першого дня? Врахуйте: у них обмежена кількість інженерів, вони все ще з’ясовують, чим насправді є їхній продукт, і кожен новий сервіс означає більше інфраструктури для керування. Читайте далі, щоб дізнатися, чому відповідь може вас здивувати.
Коли і що обирати
Розділ «Коли і що обирати»Моноліт часто кращий, коли:
Розділ «Моноліт часто кращий, коли:»✅ Мала команда (< 10 розробників)✅ Новий продукт/фаза стартапу✅ Проста доменна область✅ Стислі терміни✅ Невідомі вимоги✅ Одинарна ціль розгортанняМікросервіси мають сенс, коли:
Розділ «Мікросервіси мають сенс, коли:»✅ Велика кількість команд✅ Потреба в незалежному масштабуванні✅ Різні технологічні вимоги для кожного компонента✅ Високі вимоги до доступності✅ Потреба в частих релізах✅ Чіткі межі доменівРеальність
Розділ «Реальність»┌─────────────────────────────────────────────────────────────┐│ ТИПОВИЙ ШЛЯХ │├─────────────────────────────────────────────────────────────┤│ ││ Етап 1: Початок з моноліту ││ ├── Швидка розробка ││ ├── Прості операції ││ └── Вивчення домену ││ ││ Етап 2: Зростання (все ще моноліт) ││ ├── Команда росте ││ ├── Функції накопичуються ││ └── З'являються «больові точки» ││ ││ Етап 3: Стратегічна декомпозиція ││ ├── Виділення сервісів там, де це необхідно ││ ├── Чіткі межі ││ └── Поступова міграція ││ ││ НЕ ВАРТО: Починати з мікросервісів для нового продукту ││ НЕ ВАРТО: Робити декомпозицію без чітких меж ││ НЕ ВАРТО: Використовувати мікросервіси для малих команд ││ │└─────────────────────────────────────────────────────────────┘Зупиніться та подумайте: Кожна функція Kubernetes, яку ви вивчатимете, відповідає на виклик мікросервісів. Deployments забезпечують незалежне масштабування. Services відповідають за виявлення сервісів (service discovery). ConfigMaps керують конфігурацією кожного сервісу. Network Policies забезпечують безпеку між сервісами. Kubernetes не був розроблений для монолітів — він був створений для вирішення саме цих проблем розподілених систем.
Як Kubernetes допомагає мікросервісам
Розділ «Як Kubernetes допомагає мікросервісам»Kubernetes вирішує операційні виклики мікросервісів:
| Виклик | Рішення Kubernetes |
|---|---|
| Виявлення сервісів (Service discovery) | Services, DNS |
| Балансування навантаження | Services, Ingress |
| Масштабування | Deployments, HPA |
| Конфігурація | ConfigMaps, Secrets |
| Моніторинг стану (Health monitoring) | Probes |
| Оновлення без простоїв (Rolling updates) | Deployments |
| Відмовостійкість | ReplicaSets, самовідновлення |
| Керування ресурсами | Requests/Limits |
Без Kubernetes:├── Ручна реєстрація сервісів├── Кастомна конфігурація балансувальників навантаження├── Розгортання за допомогою скриптів├── Надія на те, що речі перезапустяться після збою└── Конфігураційні файли всюди
З Kubernetes:├── Автоматичне виявлення сервісів├── Вбудоване балансування навантаження├── Декларативні розгортання├── Самовідновлення за замовчуванням└── Централізована конфігураціяШаблони мікросервісів
Розділ «Шаблони мікросервісів»API Gateway
Розділ «API Gateway» ┌───────────────┐ │ API Gateway │ └───────┬───────┘ ┌───────────────┼───────────────┐ ▼ ▼ ▼ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ Сервіс │ │ Сервіс │ │ Сервіс │ │ A │ │ B │ │ C │ └─────────┘ └─────────┘ └─────────┘
Призначення:- Єдина точка входу- Автентифікація/Авторизація- Обмеження частоти запитів (Rate limiting)- Маршрутизація запитів
У K8s: Ingress Controller або спеціалізований gatewayService Mesh
Розділ «Service Mesh» ┌─────────────────────────────────────────┐ │ Service Mesh │ │ ┌────────┐ ┌────────┐ │ │ │Svc A │◄──────►│Svc B │ │ │ │┌─────┐ │ │┌─────┐ │ │ │ ││Proxy│ │ ││Proxy│ │ │ │ │└─────┘ │ │└─────┘ │ │ │ └────────┘ └────────┘ │ └─────────────────────────────────────────┘
Призначення:- Керування трафіком- Безпека (mTLS)- Спостережуваність (Observability)
Приклади: Istio, LinkerdШаблон Sidecar
Розділ «Шаблон Sidecar» ┌─────────────────────────────────────────┐ │ Pod │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ Основний │ │ Sidecar │ │ │ │ додаток │◄►│ (Proxy) │ │ │ └─────────────┘ └─────────────┘ │ └─────────────────────────────────────────┘
Призначення:- Додавання функціональності без зміни коду додатка- Логування, моніторинг, безпека
K8s: Pod з декількома контейнерамиВізуалізація: Шаблони взаємодії
Розділ «Візуалізація: Шаблони взаємодії»┌─────────────────────────────────────────────────────────────┐│ ВЗАЄМОДІЯ МІКРОСЕРВІСІВ │├─────────────────────────────────────────────────────────────┤│ ││ СИНХРОННА (Запит/Відповідь) ││ ┌─────────┐ HTTP/gRPC ┌─────────┐ ││ │Сервіс A │─────────────►│Сервіс B │ ││ └─────────┘◄─────────────└─────────┘ ││ Відповідь ││ Використання: Коли потрібна негайна відповідь ││ Ризик: Тісний зв'язок, каскадні збої ││ ││ АСИНХРОННА (Події/Повідомлення) ││ ┌─────────┐ Подія ┌─────────┐ ┌─────────┐ ││ │Сервіс A │────────────►│ Черга │──►│Сервіс B │ ││ └─────────┘ └─────────┘ └─────────┘ ││ Використання: Роз'єднані системи, кінцева узгодженість ││ Перевага: Слабкий зв'язок, стійкість ││ │└─────────────────────────────────────────────────────────────┘Чи знали ви?
Розділ «Чи знали ви?»- Мандат Amazon 2002 року: Джефф Безос зобов’язав усі команди спілкуватися виключно через API, закінчивши наказ словами: «Кожен, хто цього не зробить, буде звільнений». Це вимушене роз’єднання заклало основу для сучасних мікросервісів та AWS.
- Розворот Segment: У 2018 році платформа даних клієнтів Segment гучно мігрувала від мікросервісів назад до моноліту. Операційні витрати на підтримку сотень репозиторіїв та керування чергами між сервісами знищили швидкість їхньої розробки. Міграція назад заощадила їм сотні інженерних годин на місяць.
- Хаос Netflix: Netflix використовує понад 1000+ мікросервісів. Щоб забезпечити надійність у такій складній системі, вони винайшли «Chaos Monkey» — інструмент, який випадковим чином «вбиває» сервіси в продуктивному середовищі, щоб переконатися, що загальна архітектура деградує витончено, а не повністю виходить із ладу.
- «Правило двох піц»: Організаційне правило Amazon стверджує, що команди мають бути достатньо малими, щоб їх можна було нагодувати двома піцами (6-10 осіб). Це ідеально узгоджується з межами мікросервісів — одна невелика команда автономно володіє, створює та запускає один сервіс.
Типові помилки
Розділ «Типові помилки»| Помилка | Реальність |
|---|---|
| «Мікросервіси завжди кращі» | Вони додають величезну операційну складність. Часто це катастрофічний вибір для стартапів або малих команд, які шукають відповідність продукту ринку. |
| «Моноліти не масштабуються» | Масштабуються! Shopify обробляє величезний глобальний трафік електронної комерції за допомогою монолітного додатка на Ruby on Rails. Stack Overflow працює на мінімальній монолітній архітектурі. |
| «Мікросервіси виправляють поганий код» | Насправді вони його посилюють. Розподілений поганий код через мережеві межі нескінченно важче налагоджувати, відстежувати та виправляти, ніж поганий код у межах одного монолітного процесу. |
| «Менше = мікро» | Суть не в розмірі, а в обмеженому контексті (bounded context). Сервіс має бути рівно такого розміру, якого вимагає його домен. Розподіл сервісів суто за кількістю рядків коду створює тісно пов’язані мережі з надмірним трафіком. |
| «Вам потрібен service mesh з першого дня» | Service meshes (як Istio) додають величезне когнітивне та операційне навантаження. Почніть з базової мережі Kubernetes і впроваджуйте mesh лише тоді, коли цього вимагатиме розширена спостережуваність або суворі мандати mTLS. |
| «Мікросервіси означають лише REST API» | Багато високонавантажених мікросервісів спілкуються через асинхронні брокери подій (Kafka, RabbitMQ) або високопродуктивні бінарні RPC (gRPC), а не лише через стандартні HTTP REST-виклики. |
| «Мікросервіси = використання Kubernetes» | Ви можете чудово запускати контейнеризований моноліт на Kubernetes («величний моноліт»). Kubernetes — це оркестрація інфраструктури, а не архітектурний наглядач. |
| «Кожному мікросервісу потрібна власна база даних» | Хоча шаблон «база даних на сервіс» забезпечує абсолютне роз’єднання, він робить розподілені транзакції неймовірно складними. Прагматичні команди іноді починають з логічно розділених схем в межах однієї спільної бази даних. |
Контрольні запитання
Розділ «Контрольні запитання»-
Сценарій: Ваш інженерний відділ виріс з 10 до 150 розробників. Щоразу, коли команда хоче випустити невелике виправлення помилки, вона повинна чекати тижневого релізного циклу, координувати дії з 14 іншими командами та запускати 6-годинний набір тестів. Чому міграція на мікросервіси вирішила б це конкретне організаційне вузьке місце?
Відповідь
Основною перевагою в цьому сценарії є незалежне розгортання та автономія життєвого циклу. Роз'єднавши монолітну кодову базу на мікросервіси, кожна команда зможе володіти, тестувати та розгортати свій конкретний сервіс, не чекаючи інших. Якщо команда «Платежів» виправляє помилку, вона розгортає лише сервіс «Платежів», зменшуючи радіус ураження та оминаючи масивний 6-годинний набір інтеграційних тестів. Ця автономія відновлює швидкість розробки в міру масштабування організації. -
Сценарій: Стартап із 4 осіб щойно отримав посівне фінансування для створення революційного маркетплейсу іграшок для домашніх тварин на базі ШІ. У них є 3 місяці, щоб запустити MVP і перевірити відповідність продукту ринку, але межі їхнього домену все ще дуже нестабільні. Чому ця команда має явно обрати моноліт замість мікросервісів?
Відповідь
У цьому сценарії стартапу моноліт є кращим, оскільки головною метою є швидка ітерація та пошук відповідності продукту ринку, а не масове масштабування. Мікросервіси вводять «податок на розподілену систему», вимагаючи складних конвеєрів CI/CD, контрактів API та налагодження мережі, що виснажило б обмежені інженерні години малої команди. Крім того, оскільки межі їхнього домену все ще змінюються, спроба визначити межі мікросервісів зараз призведе до створення тісно пов'язаних сервісів з надмірним трафіком, які буде неймовірно боляче рефакторити пізніше. -
Сценарій: Ви успішно розділили свій моноліт на 20 мікросервісів. Однак тепер ви боретеся з операційними жахами: сервіси постійно змінюють IP-адреси під час перезапуску, один збійний сервіс викликає каскадні падіння, і вам доводиться вручну оновлювати правила балансувальника навантаження під час кожного розгортання. Як Kubernetes за своєю суттю вирішує ці конкретні операційні виклики?
Відповідь
Kubernetes діє як автоматизована операційна система для ваших розподілених мікросервісів. Він вирішує проблему зміни IP-адрес за допомогою вбудованого механізму Service discovery та внутрішнього DNS, дозволяючи сервісам знаходити один одного за стабільними іменами, а не крихкими IP. Він запобігає каскадним збоям, забезпечуючи перевірки стану (Probes) та автоматичні перезапуски (самовідновлення), гарантуючи швидку заміну несправних екземплярів. Нарешті, його об'єкти Ingress та Service автоматично та динамічно оновлюють правила балансування навантаження щоразу, коли відбувається розгортання, усуваючи необхідність ручного налаштування інфраструктури. -
Сценарій: Ваша команда з комплаєнсу безпеки вимагає, щоб увесь трафік між вашими 50 внутрішніми мікросервісами був зашифрований за допомогою взаємного TLS (mTLS). Крім того, ваша команда SRE повинна впровадити автоматичні повторні спроби для невдалих мережевих запитів. Оновлення коду додатка в усіх 50 сервісах (написаних на Node, Python та Go) займе місяці. Який архітектурний шаблон вирішує це без зміни коду додатка і як?
Відповідь
Правильним архітектурним підходом тут є впровадження Service Mesh з використанням шаблону sidecar. Service mesh впроваджує легкий контейнер-проксі (sidecar) поруч із кожним контейнером додатка в Pod, перехоплюючи весь вхідний і вихідний мережевий трафік. Оскільки проксі повністю бере на себе мережевий рівень, він може прозоро забезпечувати шифрування mTLS, впроваджувати логіку повторних спроб і збирати телеметричні дані, при цьому код додатка навіть не знатиме про його існування. Це дозволяє платформа-командам миттєво розгортати глобальні політики безпеки та надійності в поліглотних мікросервісах. -
Сценарій: Ви розробляєте архітектуру нового процесу оформлення замовлення в інтернет-магазині. Наразі, коли користувач натискає «Купити», сервіс замовлень (Order Service) робить синхронний HTTP-виклик до сервісу інвентаризації (Inventory Service), щоб зарезервувати товар. Під час святкового розпродажу з високим трафіком Inventory Service перевантажується і відповідає протягом 30 секунд. Оскільки Order Service чекає на цю відповідь, весь процес оформлення замовлення завершується за тайм-аутом, і користувач отримує помилку. Який шаблон взаємодії вам слід прийняти, щоб запобігти цьому, і чому?
Відповідь
Вам слід прийняти асинхронний шаблон взаємодії, керований подіями, використовуючи брокер повідомлень або чергу подій. Замість того, щоб чекати прямої HTTP-відповіді, Order Service має опублікувати подію «Order Placed» у чергу і негайно повернути користувачеві повідомлення про успіх («Ми обробляємо ваше замовлення»). Inventory Service зможе потім опрацювати цю подію у власному темпі, не блокуючи процес оформлення замовлення для користувача. Це роз'єднує системи, забезпечуючи величезну відмовостійкість і запобігаючи каскадним збоям у всьому додатку через локальні затримки. -
Сценарій: У вашій компанії є старий масивний монолітний додаток, що працює на фізичних серверах (bare-metal). Бізнес хоче модернізуватися і перейти в хмару. Молодший архітектор пропонує контейнеризувати весь цей масивний моноліт як єдиний образ Docker і запустити його всередині Pod в Kubernetes. Чи є це валідним варіантом використання Kubernetes, чи Kubernetes суворо вимагає мікросервісів?
Відповідь
Контейнеризація та запуск моноліту на Kubernetes є цілком валідним і дуже поширеним перехідним шаблоном, який часто називають «величним монолітом» (majestic monolith). Kubernetes — це оркестратор інфраструктури, а не суворий архітектурний наглядач, що означає, що він чудово справляється з керуванням будь-яким контейнеризованим робочим навантаженням. Запускаючи моноліт на Kubernetes, команда негайно отримує стандартизоване розгортання, автоматичні перевірки стану, самовідновлення та простіше керування конфігурацією. Це створює стабільну, модернізовану основу, з якої вони зможуть пізніше безпечно та поступово «відкушувати» частини моноліту в окремі сервіси.
Вправа для роздумів
Розділ «Вправа для роздумів»Цей модуль охоплює архітектурні концепції, для яких немає вправ у CLI. Натомість виконайте наступний аналіз:
- Проаналізуйте минулий проект: Подумайте про додаток, який ви використовували або створювали. Визначте, був це моноліт чи мікросервіси, виходячи з частоти розгортання, структури команди та шаблонів масштабування.
- Спроектуйте розділення інтернет-магазину: Для гіпотетичного сайту електронної комерції перелічіть 5 окремих сервісів, які ви б виділили з моноліту (наприклад, Users, Inventory). Визначте, який із них потребуватиме найбільшого незалежного масштабування під час миттєвого розпродажу.
- Дайте пораду стартапу: Уявіть стартап із 3 осіб, який створює новий продукт і хоче використовувати мікросервіси, «щоб бути сучасними». Сформулюйте аргумент із 2 речень, рекомендуючи їм почати з моноліту, згадуючи про «податок на розподілену систему».
- Дослідіть невдачу в індустрії: Знайдіть інформацію про «міграцію Segment з мікросервісів на моноліт» і прочитайте, чому вони гучно відмовилися від мікросервісної архітектури, щоб відновити швидкість розробки.
Ці питання готують вас до прийняття архітектурних рішень у кар’єрі, а не просто до здачі іспитів.
Підсумок
Розділ «Підсумок»Моноліти:
- Єдина одиниця розгортання
- Простіші в розробці та експлуатації на початковому етапі
- Все масштабується разом
- Виклики з’являються разом із зростанням
Мікросервіси:
- Незалежні сервіси
- Масштабуються та розгортаються окремо
- Гнучкість у виборі технологій
- Операційна складність
Ключові інсайти:
- Починайте з простого (часто це моноліт)
- Розділяйте, коли з’являються «больові точки»
- Kubernetes уможливлює шаблони мікросервісів
- Архітектура має відповідати потребам команди та продукту
Трек завершено!
Розділ «Трек завершено!»Ви завершили трек пререквізитів Cloud Native 101. Тепер ви розумієте:
- Що таке контейнери і чому вони важливі
- Основи Docker для створення та запуску контейнерів
- Що таке Kubernetes і чому він існує
- Ландшафт екосистеми cloud native
- Компроміси між монолітом та мікросервісами
Наступні кроки:
- Основи Kubernetes — Практика з вашим першим кластером
- Навчальна програма CKA — Почніть підготовку до сертифікації
- Навчальна програма CKAD — Шлях до сертифікації розробника