Когда разрабатываешь LMS-продукт, хочется, чтобы пайплайн деплоя был максимально скучным.
Не потому что деплои неважны — наоборот, они слишком важны.
Мы — OpenMirai: стартап, создающий LMS, в которой пользователи могут организовывать собственные площадки и публиковать курсы без лишних усилий. Мы выпускаем обновления часто, но не можем позволить себе ломать учебные процессы, публикацию курсов, платежи и всё то, на что полагаются авторы контента.
Загляните к нам! https://openmirai.com
Поэтому мы построили намеренно «скучный» пайплайн: GitHub pull requests, GitHub Actions, Kubernetes и Argo CD — с разделением на staging и production.
В этой статье рассказываем, как фича проходит путь от машины разработчика до реальных пользователей, и объясняем, почему мы приняли именно такие решения.
Инструменты, которые мы используем
Основной стек деплоя выглядит так:
-
Kubernetes — для запуска сервисов
-
Argo CD — для деплоев в стиле GitOps
-
GitHub Actions — для CI и автоматизации
-
GHCR (GitHub Container Registry) — для хранения контейнерных образов
-
Два окружения: staging и prod
Для рискованных или ранних фич мы также используем фича-флаги (feature flags) через PostHog, но это отдельная тема — поговорим о ней в следующих статьях.
Общий поток
Изменения кода сначала попадают в staging, мы тестируем и прогоняем регрессию внутри команды, а затем продвигаем в production в часы минимальной нагрузки.
Разберём по шагам — что именно происходит и зачем.
Шаг 1: Ветки фич сохраняют чистоту основной ветки
Обычно работу над фичей А мы начинаем от main (иногда от staging, в зависимости от темпа) и ведём разработку в отдельной ветке.
Ветки фич нужны нам не ради «идеальной изоляции», а как удобная единица для:
-
ревью изменений
-
запуска CI
-
привязки обсуждений к коду
-
принятия решения о готовности к релизу
Шаг 2: Ревью PR — наш первый «контрольный рубеж»
Когда фича готова, открываем PR и проводим командное ревью.
Этот этап недооценивают. Именно здесь удаётся поймать много рисков на ранней стадии:
-
непредвиденные побочные эффекты
-
пропущенные миграции
-
граничные случаи в правах доступа
-
ситуации «у меня работает, а у других нет»
-
улучшения тестов и наблюдаемости (observability)
Мы не воспринимаем PR как бюрократию. Для нас это последний спокойный момент перед тем, как изменение попадает в общую среду.
Шаг 3: Merge в staging, а не в production
это мы, когда кто-то рефакторит 💀
После прохождения PR делаем merge в staging.
Это осознанное архитектурное решение: staging — наша интеграционная среда. Именно здесь код встречается с реальностью — настоящими сервисами, зависимостями, конфигами, сетевыми путями.
Если что-то сломается в Kubernetes, пусть это произойдёт в staging — именно для этого он и нужен.
Шаг 4: GitHub Actions собирает и публикует образ
Как только код попадает в staging, GitHub Actions берёт на себя рутину, которую человек делать не должен:
-
сборка контейнерного образа
-
тегирование (мы предпочитаем неизменяемые ссылки, например sha-256)
-
публикация образа в GHCR
В этом и заключается прелесть доставки на основе контейнеров: мы деплоим артефакты, а не «что случайно оказалось на виртуальной машине».
Шаг 5: GitOps с единым репозиторием деплоев
У нас есть отдельный репозиторий для деплоев — внутри команды мы называем его openmirai deploy.
В нём хранятся Kubernetes-манифесты (или конфиги kustomize/helm), и именно он является источником истины о том, что запущено в каждом окружении.
Ключевой момент:
Наш GitHub Action обновляет конфигурацию деплоя, записывая новый SHA образа в соответствующий файл Kubernetes deployment.
То есть вместо того, чтобы «толкать» деплои, мы фиксируем желаемое состояние в виде коммита.
Это даёт нам:
-
каждый деплой виден как git diff
-
откат — это git revert
-
Argo CD просто следует тому, что есть в git
Это также означает, что для staging Argo CD не требует особого вмешательства человека.
Шаг 6: Argo CD автоматически деплоит в staging
Argo CD непрерывно следит за репозиторием деплоев.
Обнаружив изменение — например, новый SHA образа — он приводит кластер в соответствие с ним.
Поток выглядит так:
git commit → синхронизация Argo CD → пересоздание подов → staging обновлён
Именно в этом нам нравится GitOps: деплои превращаются в контролируемое, проверяемое изменение репозитория, а не в ручной ритуал.
Шаг 7: Внутреннее тестирование и регрессия в staging
После того как новая версия запущена в staging, мы проводим внутреннее тестирование:
-
проверка основных сценариев (happy path)
-
регрессионные проверки (места, которые ломаются чаще всего)
-
базовые проверки производительности и всплесков ошибок
-
иногда короткий период «dogfooding» для команды
Если уверенности нет — не продвигаем. Чиним и повторяем.
Если фича ранняя, рискованная или предназначена только для части пользователей, мы выпускаем её под фича-флагом (PostHog): код попадает в prod, но не включается для всех.
Шаг 8: Merge в main только при уверенности
Когда staging выглядит хорошо, делаем merge в main.
Это наш шаг «продвижения кодовой базы».
Мы убедились: если относиться к main как к «тому, что мы считаем готовым к production», это держит команду в одном понимании ситуации. Кроме того, это делает хотфиксы и откаты менее хаотичными.
Шаг 9: Деплои в production запланированы на часы минимальной нагрузки
Деплои в production мы проводим в часы минимальной нагрузки — как правило, с 23:00 до 01:00.
Отчасти это снижает влияние на пользователей, но главное — даёт нам спокойное окно для наблюдения за релизом.
Да, автоматический непрерывный деплой — это круто. Но командам на ранних этапах не всегда нужно «деплоить когда угодно». Иногда им нужно «деплоить безопасно».
Поэтому мы предпочитаем осознанные выпуски в production в предсказуемое время.
Шаг 10: Проверки после деплоя
После деплоя в production мы выполняем постпроверки:
-
ключевые пользовательские сценарии (вход, доступ к курсу, покупка/публикация)
-
дашборды работоспособности сервисов
-
частота ошибок и логи
-
алерты от системы мониторинга
Это скучно, и именно поэтому работает.
Почему этот пайплайн нам подходит
Несколько принципов, на которые мы ориентируемся:
1) Staging — место для сюрпризов
Лучше обнаруживать проблемы внутри команды, чем через сообщения от клиентов.
2) Git — это история деплоев
Каждое изменение — это diff. Откаты просты. Аудит не вызывает трудностей.
3) Автоматизация берёт на себя рутину
Люди принимают решения. Машины собирают артефакты и обновляют манифесты.
4) Релизы в production — осознанные
Мы деплоим часто, но сохраняем чёткий шаг «продвижения» и выкатываем в спокойные часы.
Что мы планируем улучшить
Даже «скучные» пайплайны развиваются. Вот над чем мы активно думаем:
-
более качественные автоматизированные регрессионные проверки
-
канареечная (canary) или прогрессивная доставка для отдельных сервисов
-
лучшая видимость того, «что изменилось» в каждом деплое
-
более тесная связь между фича-флагами и деплоями
И да, фича-флаги заслуживают отдельной статьи — особенно то, как мы используем PostHog, чтобы снижать риски и при этом выпускать фичи раньше.
Заключительные мысли
Пайплайн деплоя — это не просто DevOps-диаграмма. Это продуктовое решение.
Для нас связка GitHub Actions + GHCR + единый репозиторий деплоев + Argo CD даёт понятный, ненервный путь от push до production — без превращения деплоев в «героический подвиг».
Если вы строите мультитенантный продукт, где важна надёжность, настоятельно рекомендую держать свой пайплайн скучным.
Скучное — доезжает.