🚀
Kafka, Docker, K8s & CI/CD
для QA
Полное руководство: от теории до практики и собеседований
Нажмите → или Пробел для начала
Григорий Звягинцев
QA Engineer
- Специализируюсь на автоматизации и интеграциях
- Люблю разбирать архитектуру "по винтикам"
- Автор базы знаний "my_zametki"
📋
План полета
🔹 Brokers: Kafka vs RabbitMQ
🔹 Docker: Контейнеры
🔹 K8s: Оркестрация
🔹 CI/CD: Автоматизация
👶 Junior QA
Хочет выйти за рамки "кнопки"
🔄 Switchers
Переход из ручного в авто/DevOps
🎯 Interview Preppers
Систематизация знаний для технических собеседований
Эволюция
Что это даст?
- Понимание Message-Driven архитектуры
- Умение читать и писать сообщения в Kafka
- Навык работы с Docker Compose
- Базовое понимание оркестрации в K8s и пайплайнов
📬
Брокеры Сообщений
Зачем они нужны и как они спасают микросервисы
Архитектура
🏰
Монолит
Всё в одном процессе.
- Тяжело масштабировать
- Ошибка валит всё
- Долгий деплой
🏙️
Микросервисы
Много маленьких сервисов.
- Сложная коммуникация
- Нужна надежная сеть
- Как передать данные?
Синхронно vs Асинхронно
Зачем они нужны?
Синхронно (HTTP)
Service A ➡️ Service B
Если B упал, A тоже висит. Жесткая сцепка.
Асинхронно (Broker)
Service A ➡️ 📬 ➡️ Service B
Service A положил письмо и пошел дальше. Service B прочитает, когда сможет.
Брокер — это посредник 📬
🏭 ➡️ 📬
Broker ➡️ 🏘️
Принимает от отправителей, хранит и отдает получателям.
Задачи:
- ✓ Маршрутизация данных
- ✓ Буферизация (сглаживание пиков)
- ✓ Развязывание сервисов (Decoupling)
- ✓ Гарантия доставки
Типологии
Hub & Spoke
Центральный сервер управляет всем. Все сообщения через единый узел.
Message Bus
Распределенная шина. "Умные" эндпоинты и "глупая" труба. Масштабируемо.
Зачем это QA? 🤔
- Проверка интеграции: Дошло ли сообщение от A к B?
- Валидация данных: JSON Schema, типы данных.
- Негативные сценарии: "Битое" сообщение, потеря связи.
- Нагрузка: Забить очередь и проверить разгребание завала.
🐰
RabbitMQ
"Умный брокер, глупый потребитель"
- Тип: Очередь (Queue)
- Логика: Smart Server, Dumb Client
- Механика: Push (Сам проталкивает)
- Главное: Сообщение удаляется после обработки (Ack).
🚀
Apache Kafka
"Глупый брокер, умный потребитель"
- Модель: Распределенный лог\журнал (Log)
- Логика: Dumb Server, Smart Client
- Доставка: Pull (Клиент сам читает, что ему нужно).
- Жизнь: Хранится (Retention policy)
- Главное: Сообщения хранятся на диске (Retention) и не удаляются при чтении.
Примеры из жизни: Кто для чего?
🐰 RabbitMQ (Задачи)
Кейс: Регистрация на сайте
- Отправить Email подтверждения
- Сгенерировать PDF отчет
Нужно просто выполнить задачу 1 раз. Очередь задач.
🚀 Kafka (Потоки)
Кейс: Uber / Netflix
- Сбор GPS координат всех такси (100к в сек)
- Сбор логов просмотров фильмов
Нужна бешеная скорость и история событий. Потоковая обработка.
Сравнение
| Критерий |
🐰 RabbitMQ |
🚀 Apache Kafka |
| Тип |
Очередь |
Журнал (Log) |
| Доставка |
Push |
Pull |
| Хранение |
Удаляет после Ack |
Хранит (Retention) |
| Масштаб |
Вертикальное |
Горизонтальное |
Глобальная схема Kafka 🗺️
Producer 🏭
1. Публикует (Push)
Всегда дописывает в конец (Append Only)
➡️
Topic "Orders" 📂
Partition 0 📄 [0, 1, 2...]
Partition 1 📄 [0, 1, 2...]
Partition 2 📄 [0, 1, 2...]
➡️
Consumer Group 👥
App A (Instance 1) 🏗️
App A (Instance 2) 🏗️
2. Читают (Pull)
Параллельная обработка без конфликтов
Анатомия: Topic & Partition 📂
Topic — это папка. Partition — это файл внутри папки.
Topic "Orders" 📂
Данные (Offset) пишутся
последовательно
Что такое "Логи" в Kafka?
❌ Это НЕ текстовые логи (`error.log`)
✅ Log = Партиция на диске (Append Only)
- 💾 Суть: Это физическое "тело" партиции.
- 📂 Где лежат: Сегменты на диске.
/tmp/kafka-logs или
/var/lib/kafka/data
- ⏳ Retention: Время жизни (TTL).
Дефолт: 168 часов (7 дней).
- ⚙️ Настройка:
log.retention.hours
Как чекать?
- CLI:
kafka-console-consumer
- UI: Kafdrop, Kafka UI, AKHQ
- Смотрим offset (отставание) и payload.
Про дисковое пространство
Kafka Flow: Жизнь сообщения 🔄
1. App (Producer)
🏭
POST /orders
{
"id": 101,
"item": "Laptop"
}
Send(JSON)
➡️
2. Broker
📬
[0] id:99
[1] id:100
[2] id:101 (New)
Append to Log
➡️
3. Consumer
🐢
Processing...
✅ Commit Offset 2
Read & Ack
📝 Логи (как это выглядит в консоли)
[INFO] Producer: Sending message key=101 value={"item":"Laptop"} to topic 'orders'
[INFO] Consumer: Received record offset=2 key=101 value={"item":"Laptop"}
[DEBUG] Consumer: Processing order 101... Success. Committing offset.
Анатомия: Offset 🔖
Offset — это просто "закладка" в книге (партиции).
Topic "Orders" / Partition 0
⬆️ Current Offset (2)
Брокер запомнил: 0 и 1 уже обработаны.
Если сервис упадет, он вернется и начнет с 2.
(Гарантия "At least once")
Когда забыл Offset...
Способы доставки (Semantics)
At-most-once
🔥 Fire & Forget
Может потеряться. Дубликатов нет.
At-least-once
🛡️ Стандарт
Гарантируем доставку. Но могут быть дубликаты (нужна
идемпотентность).
Exactly-once
🦄 Идеал
Сложно (Транзакции). Каждое сообщение строго 1 раз.
Consumer Groups (Масштабирование) 👥
⚠️ Золотое правило
1 Партиция = Максимум 1 Консьюмер (в рамках одной группы).
- ✅ Параллелизм: Читаем партиции одновременно.
- ❌ Лимит: Нельзя добавить консьюмеров больше, чем партиций.
⬇️ ⬇️
👥
Group "Analytics" (3 Consumers)
😋
Con 1
😋
Con 2
😴
Con 3
(Idle)
Репликация (High Availability) 🛡️
- 👑 Leader:
Только он обрабатывает Запись и Чтение.
- 🐑 Follower:
Пассивно копирует данные у Лидера (фоновая
синхронизация).
- 🔥 Failover (Отказоустойчивость):
Лидер упал? → Один из Фолловеров моментально выбирается новым
Лидером.
Broker 1 (Server)
👑 P-0 (Leader)
➡️
Broker 2 (Server)
🐑 P-0 (Replica)
Broker 3 (Server)
🐑 P-0 (Replica)
Control Plane: Мозг Кластера 🧠
Зачем нужно? Хранение метаданных (где чья партиция) и выборы Лидера (Consensus).
- 📍 Метаданные: Кто лидер? Где лежат партиции?
- 🗳️ Консенсус: Выбор главного (Leader Election).
- 👮 Health Check: Кто жив, а кто умер?
🗺️ 🗳️ 👮
Эволюция: Zookeeper vs KRaft 🔄
🐘 Zookeeper (Legacy)
⬇️ ⬆️
Kafka Brokers
(Dumb Storage)
- ❌ Внешняя зависимость
- ❌ Двойные метаданные
🚤 KRaft (Future)
Kafka Cluster
👑 Controller (Internal)
- ✅ All-in-One: Единый процесс.
- ✅ Скорость: Миллионы партиций.
Kafka 4.0 без ZK!
Log Compaction (Уплотнение) 📚
🧐 В чем суть?
Kafka удаляет старые значения для ключа,
оставляя последнее.
"Мне не важна история, важен текущий статус."
Где нужно:
- 👤 Профили пользователей.
- ⚙️ Конфигурации сервисов.
- 💰 Текущие цены товаров.
📋 До Compaction
K: 101 | Val: "Alex"
K: 101 | Val: "Alexander"
K: 101 | Val: "Sasha"
⬇️
⚠️ Для обычных логов (Traffic, Clicks) это не подходит!
"Kafka — это распределенный, отказоустойчивый журнал событий."
🐳
Docker
Контейнеры, Слои и Сборка
📦
Контейнеризация
Способ упаковки приложения вместе с его окружением (библиотеки, конфиги). Гарантирует,
что код работает одинаково и у разработчика, и в тестировании, и на проде.
VM 🆚 Container
🐢 Virtual Machine
Полная изоляция (OS + Libs + App)
App A
Libs /
Bins
Guest OS (Heavy) 🏋️
Hypervisor
Infrastructure
Boot: Minutes ⏳
🐇 Container
Изоляция процессов (Shared
Kernel)
Docker Engine
Host OS Kernel (Shared) 🤝
Infrastructure
Boot:
Milliseconds ⚡
Image vs Container 💿📦
💿 Image (Образ)
Неизменяемый файл (Snapshot).
- 🔒 Read-Only: Нельзя менять.
- 🏗️ Build time: Результат сборки.
- 📐 Аналогия: Чертеж дома / Класс.
➡️
docker run
📦 Container
Запущенный процесс.
- 📝 Read-Write: Можно писать файлы.
- 🏃 Run time: Живая система.
- 🏠 Аналогия: Дом / Объект.
⚡ Суть: Из одного Образа можно
запустить сотни Контейнеров.
Ожидание vs Реальность
Dockerfile & Image 🏗️
Dockerfile — это инструкция (рецепт) для повара 👨🍳.
Image (Образ) — это готовое блюдо 🥘 (упакованный код + ОС).
Container — это когда блюдо едят 🍽️ (запущенный процесс).
# 1. Берем готовый Образ (Base Image)
FROM python:3.9-slim # <-- Linux + Python внутри
# 2. Создаем папку внутри образа
WORKDIR /app
# 3. Копируем файлы (Ингредиенты)
COPY . . # <-- Из нашего ПК в Образ
# 4. Устанавливаем либы (Готовка)
RUN pip install flask # <-- Работает при BUILD
# 5. Команда старта (Подача)
CMD ["python", "app.py"] # <-- Работает при RUN
Docker Layers (Слои) 🥪
Layer 1: Base OS (Ubuntu/Alpine) 🔒
Layer 2: Deps (pip install) �
Layer 3: App Code (copy . .) 🔒
Writable Layer (Container) 📝
Новые файлы, логи, изменения БД
🔒 Read-Only (Image)
Нижние слои (Образ) нельзя менять. Это как
кирпичи фундамента.
📝 Writable Layer
Когда контейнер запускается, Docker кладет сверху тонкий
прозрачный лист для записи.
* Все изменения (создание файлов) пишутся СЮДА.
* Если контейнер удалить — этот слой исчезнет!
Вопрос: А если приложение пишет в память (RAM)?
Ответ: RAM — это оперативная память CPU, она не тут. Слои — это только про
Файловую Систему (Диск).
Что такое YAML? (.yml) 📄
"Yet Another Markup Language"
Формат для конфигов. Популярен из-за читаемости.
- ✅ Отступы (пробелы) вместо скобок
- ✅ Где: K8s, Docker Compose, GitLab CI
person:
name: Grigory
role: QA
skills:
- Docker
- Kafka
Docker Registry 🏪
Хранилище образов (где живут Image).
🌍 Public
Docker Hub
Официальные образы (Python, Kafka, Postgres). Открыты всем.
🔐 Private
Nexus / GitLab Registry
Внутренние образы компании. Нужен логин/пароль.
⬆️ docker push (Загрузить)
⬇️ docker pull (Скачать)
Docker Compose 🐙
Дирижер для локальной разработки (Multi-Container).
version: '3.8'
services:
kafka: # 📦 Контейнер 1
image: bitnami/kafka
ports:
- "9092:9092"
app: # 📦 Контейнер 2
build: .
depends_on:
- kafka # 🔗 Связь
Вместо 10 команд запуска — одна:
docker-compose up -d
⚠️ Запускать из папки с файлом .yml (и Dockerfile)
Когда запустил Compose
Cheat Sheet 📝
👀
docker ps
Кто живой? (Процессы)
💿
docker images
Список образов
📜
docker logs
Must Have для QA
🚀
docker run
Создать и запустить
🛑
docker stop
Остановить контейнер
🧹
docker system prune
Очистка мусора
Зачем Docker QA?
- Воспроизводимость: "It works on my machine" — в прошлом.
- Изоляция: Тесты не мешают друг другу.
- Скорость: Развернуть стенд за секунды.
Docker Swarm? 🤔
Это "родной" инструмент кластеризации от Docker.
Позволяет объединить несколько Docker-хостов в один виртуальный.
Swarm vs Kubernetes
- 🟢 Swarm: Простой, встроен в Docker, легко поднять.
- 🔴 Минус: Меньше возможностей, проиграл войну популярности.
- 🔵 K8s: Стандарт индустрии. Сложнее, но мощнее.
☸️
Kubernetes (K8s)
Оркестрация: Управляем флотом контейнеров.
Дирижер оркестра 🎻
🎻
Дирижер (K8s)
Управляет, когда вступать, громкостью и темпом.
🎺🥁🎸
Оркестр (Containers)
Каждый инструмент (контейнер) делает свою работу, но вместе —
симфония.
"Kubernetes makes containers dance."
Learning Curve
Docker 🆚 Kubernetes
🐳 Docker
🧱
Кирпич
- Запуск 1 приложения
- Ручное управление
- "Я создал контейнер"
☸️ Kubernetes
🏙️
Небоскреб
- Управление тысячами
- Авто-масштабирование
- "Я построил систему"
Архитектура Кластера 🏗️
🧠
Control Plane
(Master Node)
- API Server: Вход 🚪
- Scheduler: Планировщик 📅
- Etcd: Память 💾
Управляет рабочими ⬇️
Deep Dive: Worker Node 🐴
🖥️ Node (Сервер)
Железный сервер или виртуальная машина (VM).
- Kubelet (Daemon): "Капитан". Получает приказы от Control Plane.
- Kube-proxy (Daemon): "Связной". Отвечает за сеть (IP, iptables).
- Container Runtime (Daemon): Docker/containerd. Крутит контейнеры.
🏭
"Здесь делается работа"
Deep Dive: Control Plane 🧠
🚪 API Server
Входная дверь. Принимает REST запросы (kubectl). Только он общается с
Etcd.
💾 Etcd
Память кластера. Хранит конфигурацию (Deployment, Service, NS).
(Критично важно!).
📅 Scheduler
Планировщик. Решает, на какую ноду отправить новый
Под (смотрит на CPU/RAM).
🤖 Controller
Завхоз. Читает записи в Etcd и заставляет их исполняться (создает
поды).
Pod (Под) 🥚
Минимальная единица K8s.
Это оболочка для контейнера. K8s не запускает контейнеры напрямую, он запускает Поды.
- 💀 Смертны: Если умрет, K8s создаст новый (с новым IP).
- 🏠 Общий дом: Контейнеры в одном Поде делят IP и диски.
📦
1 Pod = 1 Container
(Обычно так)
Deployment 🚀 (Менеджер)
Гарант стабильности. (Запись в Etcd)
🔄 Desired State
Deployment постоянно сверяет:
- Надо: 3 штуки
- Есть: 2 штуки
- Действие: Создать +1
✅ Pod 1 (Running)
✅ Pod 2 (Running)
🆕 Pod
3 (Starting...)
Service 🌐 (Связист)
Проблема: Поды умирают, их IP меняются.
Решение: (Запись в Etcd)
Service дает постоянный IP.
⚙️ Механика:
Демон
Kube-proxy (на каждой ноде) следит за этой записью и обновляет правила
маршрутизации (iptables).
⚠️ Это НЕ API Server. Это "внутренний роутер" для
приложений.
➡️
Service (LB)
10.96.0.1
🎯 Sel: app=web
Сетевая магия
Namespaces 🏷️ (Пространства)
Виртуальные "папки" для изоляции проектов. (Запись в Etcd)
📁
Namespace: DEV
Для разработчиков. Можно ломать.
🛡️
Namespace: PROD
Священная земля. Доступ ограничен.
Production Architecture (HA) 🏰
☁️ External Load Balancer
Вход для пользователей (HTTPS)
⬇️
Control Plane VIP
🧠 Master 1
🧠 Master 2
🧠 Master 3
⬇️
🐴 Worker 1
🐴 Worker 2
🐴 Worker 3
Если один Master умрет, кластер продолжит
жить. API доступен по Virtual IP.
Big Picture: Как всё связано? 🌍
🚀 Kafka Cluster
📬
Broker 1
📬
Broker 2
📬
Broker 3
Приложение живет "в матрешке" и ходит в Кафку
по сети.
Инструменты 🛠️
Как мы управляем всем этим?
⌨️
kubectl
Консольная утилита. База. Must have.
👁️
Lens / k9s
Удобные GUI. Видно логи, графики.
🕸️
Dashboard
Веб-интерфейс (официальный).
Инструменты и хаос
K8s Debugging: Практика 🕵️♂️
1. Живы ли мы?
$ kubectl get pods
NAME STATUS
R
app-web-x8z Running 0
app-db-9qa Error 5
job-cleaner Comple.. 0
Смотри на STATUS и
RESTARTS.
2. Залезть внутрь (Tunnel)
$ kubectl port-forward pod/db 5432:5432
Прокидываем порт, чтобы подключиться к БД с
ноутбука.
Любимый статус
K8s Cheat Sheet 📝
| Команда |
Описание |
Когда нужно? |
kubectl get pods |
Список подов и статусы |
"Жив ли пациент?" |
kubectl get pods -w |
Смотреть в реальном времени (Watch) |
При деплое / рестарте |
kubectl logs <pod> |
Читать логи приложения |
Ищем "Exception" или ошибки 🔥 |
kubectl describe pod |
Подробное досье (Events) |
Если статус Error /
Crash |
kubectl port-forward |
Проброс порта (Туннель) |
Подключиться к БД/Kafka |
🔄
CI/CD
Автоматизация пути от кода до продакшена.
CI/CD ♾️
CI (Integration)
- Слияние кода
- Build
- Unit Tests
CD (Delivery)
- Деплой на Stage
- E2E Tests
- Деплой на Prod
Роль QA в CI/CD 🛡️
⬅️ Shift Left
Тестируем требования и дизайн до написания кода.
🚧 Quality Gates
Тесты упали = ⛔ Стоп машина. Билд не пройдет дальше.
💨 Smoke Tests
Быстрая проверка после деплоя (жив ли пациент?).
🤖 E2E Tests
Полная имитация пользователя (Selenium/Playwright).
Когда тесты упали...
Процесс: Shift Left & Isolation 🔄
💻
1. Local (Dev+QA)
- Работа в Feature Branch
- Docker-compose (App + DB)
- Пишем тесты сразу
➡️
⚙️
2. CI (Pull Request)
- Isolation Testing
- Build App ➡️ Run Tests
- Тесты упали = ⛔ Block Merge
➡️
🚀
3. Environment
- Deploy to Dev/Stage
- Smoke / Integration
- Регрессия перед релизом
Баги ловятся на этапе PR, а не на продакшене!
🛡️
Инструменты 🧰
🏆 Популярные
🤵
Jenkins
Старый, добрый, мощный.
🦊
GitLab CI
Все в одном (код +
пайплайн).
🚀 Modern / GitOps
▶️
GitHub Actions
Просто и рядом с
кодом.
Где бегут тесты? (GitLab CI)
Типичный сценарий:
💻 git push
GitLab Runner
Сервер, выполняющий Jobs
Docker Executor
🐳 Test
Container
Pytest / Playwright
📊 Allure Report
* Джобы выполняются в изолированных
Docker-контейнерах, которые умирают после тестов.
🛠️
Практика
Собираем всё вместе
Наш Проект: Архитектура 🏗️
Order API
Kafka
Consumers (x3)
Postgres
Order Consumers: 2 активных, 1 резервный
Data Flow
Postman → API → 🚀 Kafka → Consumer → 🐘 DB
- HTTP POST -> Order API (5000)
- JSON event -> Kafka topic "order-events"
- Consumer читает сообщение
- Consumer пишет данные в PostgreSQL
Тулсет (Docker only)
Docker Compose
Основа
Kafka UI / AKHQ
Визуализация
Postman
Отправка
PgAdmin
Проверка БД
Тест 1: Happy Path 😄
📮
1. POST запрос на API (Postman)
⬇️
📨
2. Сообщение в Kafka UI
⬇️
Тест 2: Идемпотентность (Дубль)
🔴 Действие
Отправляем тот же event_id повторно.
🟢 Ожидание
- Consumer видит дубль.
- В базу ничего не пишется.
- В логах:
WARN: Duplicate event.
Тест 3: Партиционирование
Ключ партиционирования = barCode.
Гарантия хронологического порядка для товара.
Тест 3b: Разные ключи
Разные Barcode = Round Robin.
Балансировка нагрузки между партициями.
Тест 4: Отказоустойчивость 🔥
-
🚀
1. Запускаем нагрузку (посылаем запросы)
-
💀
2. Убиваем Консюмера (
docker stop consumer-2)
-
📈
3. Смотрим Lag (кратковременный рост)
-
⚖️
4. Kafka делает Rebalance
-
✅
5. Резервный консюмер подхватывает работу, Lag -> 0
Consumer Lag 🐢
Большой лаг = Консюмер не справляется с потоком.
Что тестируем? (Checklist)
Функциональное
- Позитивное (Доставка)
- Негативное (Битая схема)
- Идемпотентность (Дубли)
Нефункциональное
- Хаос (Убийство консюмера)
- Производительность (Лаг)
- Целостность (Проверка БД)
Итого 📝
- Kafka: Кровеносная система
- Docker: Упаковка
- K8s: ОС для дата-центра
- CI/CD: Конвейер
- QA: Гарант качества
👏
Спасибо за внимание!
Вопросы?
"Quality is not an act, it is a habit."
Финиш!