Модуль 34

RabbitMQ у Kubernetes (огляд)

Ось урок, створений у стилі CS50: енергійний, зрозумілий, з акцентом на розумінні суті, а не простому зазубрюванні команд.


🎓 Тема: RabbitMQ у Kubernetes (Огляд)

Привіт, друзі! 👋

Сьогодні ми поговоримо про те, як поєднати дві надпотужні технології. З одного боку, у нас є Kubernetes (наш оркестратор, капітан корабля контейнерів), а з іншого — RabbitMQ (наш поштовий відділ, брокер повідомлень).

Але навіщо нам запихати Кролика (RabbitMQ) у Контейнер (K8s)? Чи не простіше запустити його на звичайному сервері? Давайте розбиратися.


1. 🔥 Вступ: Проблема та мотивація

Уявіть, що ви будуєте «Uber для доставки піци». У вас є мікросервіс, який приймає замовлення (Order Service), і мікросервіс, який відправляє замовлення на кухню (Kitchen Service).

Ось настає вечір п'ятниці. Тисячі голодних людей натискають кнопку "Замовити". Ваш Order Service працює в Kubernetes, він масштабується — створюються десятки нових подів, щоб прийняти трафік. Все круто!

Але... Kitchen Service (кухня) не гумова. Вона не може обробити 1000 піц за секунду. Якщо ми будемо слати замовлення напряму (HTTP REST), кухня «впаде», сервер зависне, і замовлення загубляться. Клієнти злі, бізнес втрачає гроші.

❓ Питання до вас: Що робити, якщо потік води (замовлень) занадто сильний для труби (кухні)? Відповідь: Потрібен буфер. Резервуар.

Ось тут на сцену виходить RabbitMQ. Він стає посередником. Він каже: "Гей, Order Service, кидай замовлення мені, я їх збережу. А ти, Kitchen Service, забирай їх у своєму темпі, по одній піці за раз".

Чому саме в Kubernetes? Тому що ми хочемо, щоб наш "резервуар" теж був надійним. Якщо один сервер з RabbitMQ згорить, ми хочемо, щоб Kubernetes автоматично підняв інший, і жодне замовлення не зникло. Ми хочемо автоматизації і виживання.


2. 🧠 Теоретична база (без нудьги)

Давайте заглянемо під капот, але без зайвих дротів.

Щоб запустити RabbitMQ у K8s, нам треба зрозуміти одну фундаментальну відмінність.

  • Stateless (Веб-сервер): Йому байдуже, хто він. Якщо один под помер, ми піднімаємо новий. Вони як клони штурмовиків — взаємозамінні.
  • Stateful (RabbitMQ, Бази даних): Це як джедаї. Кожен має ім'я та пам'ять. RabbitMQ зберігає повідомлення на диску. Якщо ми вб'ємо под з RabbitMQ і піднімемо новий, він повинен "згадати", хто він, і підключитися до тих самих даних на диску.

🔑 Ключові поняття:

  1. StatefulSet (не Deployment!): У K8s для звичайних програм ми використовуємо Deployment. Але для RabbitMQ ми використовуємо StatefulSet.

    • Чому? Це гарантує стабільні імена (наприклад, rabbitmq-0, rabbitmq-1) і те, що після перезавантаження под rabbitmq-0 знову підключиться до свого старого жорсткого диска.
  2. Persistent Volume (PV) & Claim (PVC): Це "жорсткий диск", який живе окремо від пода. Коли под помирає, диск залишається. Новий под приходить і каже: "Це мій диск, віддайте".

  3. Headless Service: Спеціальний тип сервісу в K8s, який дозволяє звертатися до конкретного пода (rabbitmq-0), а не до випадкового. Це важливо для кластеризації RabbitMQ, щоб ноди могли знайти одна одну.

  4. RabbitMQ Cluster Operator (Сучасний підхід): Раніше ми писали сотні рядків YAML-файлів вручну. Зараз розумні люди написали програму (Operator), яка живе у вашому кластері K8s. Ви кажете їй: "Хочу кластер RabbitMQ з 3 нод", і вона сама створює StatefulSet, сервіси, конфіги та секрети. > Запам'ятайте: У 2024+ році для складних систем (як RabbitMQ/Kafka/Postgres) у K8s ми майже завжди використовуємо Operators.


3. 🧪 Приклади (від ідеї до реалізації)

Приклад 1: "Дідівський спосіб" (Лише для розуміння)

Якби ми робили це вручну через StatefulSet, це виглядало б страшно. Ми б налаштовували змінні оточення, монтували томи, налаштовували Erlang Cookie (секретний ключ для спілкування нод).

Студент: "Це звучить як біль". Викладач: "Саме так! Тому ми так робити не будемо. Ми підемо шляхом розумного розробника."

Приклад 2: Використання RabbitMQ Cluster Operator

Спочатку ми встановлюємо Оператора (це як найняти спеціального адміністратора RabbitMQ у свій кластер).

А потім, щоб створити цілий кластер RabbitMQ, ми пишемо лише ось такий маленький маніфест:

apiVersion: rabbitmq.com/v1beta1
kind: RabbitmqCluster
metadata:
  name: my-production-rabbit
spec:
  replicas: 3
  resources:
    requests:
      cpu: 250m
      memory: 1Gi
  persistence:
    storageClassName: standard
    storage: 10Gi

❓ Що ви очікуєте, коли застосуєте цей файл? (Пауза для роздумів)

Що відбувається насправді: Оператор бачить цей файл і починає магію: 1. Створює 3 Поди (RabbitMQ ноди). 2. Налаштовує Кластеризацію (вони знають одна про одну). 3. Створює Service, щоб ваші додатки могли підключатися. 4. Створює Secret з логіном і паролем за замовчуванням.

Це економить вам тиждень роботи й купу нервів!


4. 🛠 Практична частина

Час забруднити руки! Якщо у вас є minikube або будь-який K8s кластер, спробуйте це.

Завдання 1: Встановлення Оператора Знайдіть офіційну інструкцію RabbitMQ Cluster Operator і встановіть його однією командою (kubectl apply -f ...). Переконайтеся, що под оператора запустився.

Завдання 2: Запуск Кролика Створіть файл rabbit.yaml із прикладу вище (Приклад 2) і зробіть kubectl apply -f rabbit.yaml. * Спостерігайте: kubectl get pods -w. Ви маєте побачити, як поди піднімаються один за одним: my-production-rabbit-server-0, потім -1, потім -2.

Завдання 3: "Хаос-інжиніринг" (Chaos Monkey) Видаліть одну з нод: kubectl delete pod my-production-rabbit-server-0. * Подивіться, що станеться. Чи створить K8s новий под з тим самим ім'ям? (Спойлер: Так). Чи збережуться дані?

Завдання 4: Отримання доступу RabbitMQ створив Secret з паролем. Знайдіть його: kubectl get secret my-production-rabbit-default-user -o jsonpath='{.data.password}' | base64 --decode. Зробіть port-forward до панелі управління (Management UI) і спробуйте залогінитися.

Завдання 5: А що, якщо... (Кейс) У вас закінчилося місце на диску (PVC). Под впав. Що ви будете робити? * Підказка: Просто збільшити розмір у YAML файлі може бути недостатньо, залежно від вашого хмарного провайдера. Подумайте, як розширити Persistent Volume.


5. 💡 Мислення як у розробника

Як відрізнити новачка від профі при роботі з RabbitMQ в K8s?

🚫 Помилка новачка: Використовує Deployment замість StatefulSet або RabbitmqCluster. * Результат: При перезавантаженні RabbitMQ втрачає всі повідомлення і "забуває", хто він такий. Кластер розвалюється.

🚫 Помилка новачка №2: Не налаштовує ліміти ресурсів (resources). * Результат: RabbitMQ — жадібний звір. Він може з'їсти всю оперативну пам'ять на ноді, і Kubernetes "вб'є" його (OOMKilled).

🧠 Як думає профі: 1. Observability (Спостережуваність): Профі знає, що черги можуть забитися. Він одразу підключає Prometheus і Grafana, щоб бачити графік "Кількість повідомлень у черзі". Якщо графік росте вгору — це сигнал тривоги (аларм). 2. Anti-Affinity: Профі налаштує K8s так, щоб поди RabbitMQ не жили на одному фізичному сервері. Якщо один сервер згорить, ми втратимо тільки 1/3 кластера, а не все одразу. 3. Зберігання: Він використовує швидкі SSD диски для PV, бо RabbitMQ чутливий до швидкості запису на диск.


6. 🧩 Підсумок

Отже, що ми сьогодні зробили? Ми не просто "поставили софт". Ми створили надійну, стійку до збоїв систему доставки повідомлень усередині нашого кластера.

Тепер ви вмієте: 1. Розуміти різницю між Deployment та StatefulSet. 2. Використовувати Operator pattern для розгортання складних систем. 3. Масштабувати інфраструктуру повідомлень.

🚀 Тизер наступного уроку: Добре, RabbitMQ працює. Але як зробити так, щоб наш Python-код автоматично підключався до нього, не прописуючи паролі прямо в коді? На наступному уроці поговоримо про Kubernetes Secrets та ConfigMaps, і як правильно ін'єктувати (inject) конфігурації в додатки.

Це буде круто. До зустрічі! 💻