Микросервисы на практике: Docker + Swarm + Nginx вместо монолита
Первый клиент попросил разбить монолит на сервисы. Взяли Docker Swarm и Nginx как API gateway. Главный вызов оказался не в технике, а в том, кто за что отвечает.
Микросервисная архитектура становится доминирующим паттерном для новых проектов в 2015 году
В этом году тема микросервисов стала чем-то средним между реальной инженерной практикой и модным словом на конференциях. Мы слышали её от клиентов регулярно, но до реального запроса «помогите разбить наш монолит» дошло только этой осенью. Дошло - и мы взялись.
Что было у клиента
PHP-монолит, которому лет шесть. Несколько сотен тысяч строк. Всё в одном репозитории: веб-интерфейс, API для мобильного приложения, фоновая обработка очередей, генерация отчётов, интеграции с внешними системами. Деплой - scp и перезапуск Apache. Любое изменение в модуле отчётов может случайно сломать API, и всё это обнаруживается уже после деплоя.
Запрос клиента был честный: не «мы хотим микросервисы потому что так правильно», а «мы больше не можем деплоить без страха». Это понятная инженерная боль, с которой можно работать.
Какой стек выбрали и почему
Kubernetes мы к этому моменту уже смотрели - и в тестах, и в свежем опыте с overlay-сетями в Swarm. Вывод был такой: для этого проекта Kubernetes избыточен. Команда у клиента небольшая, инфраструктурной экспертизы мало, а K8s требует выделенного внимания на поддержку самого кластера - etcd, scheduler, controller-manager, сеть. Это отдельный проект внутри проекта.
Взяли Docker Swarm - с тем самым опытом, который у нас был с сентября. Поверх - Nginx как API gateway: он принимает запросы снаружи и роутит к нужному сервису по префиксу URL. Схема выглядит примерно так:
Клиент (браузер / мобилка)
|
Nginx <-- API gateway, SSL termination
/ | \
/ | \
svc-api svc-reports svc-worker
(Swarm) (Swarm) (Swarm)
Простая конфигурация Nginx:
location /api/ {
proxy_pass http://svc-api:8080/;
}
location /reports/ {
proxy_pass http://svc-reports:8080/;
}
Каждый сервис - отдельный Docker-образ, отдельный репозиторий, отдельный CI-пайплайн. Деплоим через docker-compose pull && docker-compose up -d - только тот сервис, который изменился.
Технически всё завелось. Дальше началось интересное
Технических проблем было ожно и они решались. Shared база данных - главная из них: монолит работал с одной PostgreSQL, и дать каждому сервису свою схему можно было только поэтапно. Мы начали с логического разделения: сначала разные схемы в одной БД, с договорённостью что сервисы не ходят в чужие таблицы напрямую. Это костыль, но управляемый.
Настоящая проблема оказалась организационной. Монолит - он один, и понятно кто за него отвечает: вся команда разработки. Когда появились три сервиса - возник вопрос, который никто заранее не обсудил: кто владеет каждым сервисом?
На практике это выглядело так:
- Баг в svc-reports. Разработчик, который его дорабатывал, ушёл в отпуск. Кто правит? Непонятно.
- Нужно изменить контракт API между svc-api и svc-reports. Кто принимает решение? Обе стороны говорят «мне так неудобно», и обе правы.
- Кто следит за тем, что svc-worker не упал? «Это инфраструктура» - говорит разработка. «Это приложение» - говорим мы.
Без ответа на эти вопросы микросервисная архитектура создаёт не меньше боли, чем монолит, а больше - только распределённой.
Мы в итоге помогли клиенту написать простую матрицу ответственности: у каждого сервиса есть владелец (конкретный человек или пара), он же участвует в ревью всех изменений в этом сервисе, он же дежурит по нему. Звучит как очевидная практика - но до явного разговора это висело в воздухе.
Что получилось к декабрю
Три сервиса работают в Swarm, остальная часть монолита пока живёт как есть. Деплой стал независимым - можно выкатить только API без риска задеть очереди. Nginx справляется как gateway без каких-то специальных инструментов.
Kubernetes в этом сценарии был бы лишним. Swarm с текущей командой - управляемо. Может, через несколько месяцев появится потребность в чём-то что Swarm не умеет - посмотрим. Пока справляемся.
Если вас ждёт похожая задача - интеграция и разбивка монолита на части - технически это решаемо за обозримое время. Организационную часть стоит проработать до старта, а не после.
- Docker 1.9 + overlay-сети: перевели первое приложение на Swarm-кластер · 6 ноября 2015
- Docker Swarm 1.0: нативная кластеризация без сторонних костылей · 4 сентября 2015