Независимые пайплайны CI/CD: где ломается общая сборка
Пока сервисов пять, общая сборка выглядит удобно: один файл конфигурации, один набор проверок, один артефакт на выходе. На тридцати сервисах та же схема становится узким местом конвейера — правка в одном модуле запускает полную пересборку и ставит в очередь релизы команд, которые ничего не меняли.
Причина обычно в отсутствии графа зависимостей. Триггер срабатывает на любой коммит, кэш зависимостей общий и инвалидируется целиком, а блокирующие проверки — линтеры, тесты, проверка уязвимостей — прогоняются по всему репозиторию, хотя изменился один сервис. Общий тег образа усугубляет картину: пересобирать приходится и соседей, которые от правки не зависят.
Дальше включается эффект очереди. Время сборки растёт линейно от числа сервисов, а не от объёма изменения, поэтому ожидание свободных исполнителей становится главной статьёй простоя. Команды начинают копить правки в один крупный релиз, откат затрагивает сразу несколько сервисов, а обратная связь по качеству приходит через часы вместо минут.
Разбираем, как это закрывается независимыми пайплайнами CI/CD: у каждого сервиса свой набор триггеров, изолированный кэш, собственный артефакт и понятная зона ответственности за результат.
Что даёт разделение сборки: скорость, изоляция, предсказуемость
Когда сборка одна на все сервисы, любое изменение в общей библиотеке тянет пересборку всего дерева. Время растёт линейно от числа сервисов, а очередь на общих сборочных агентах становится узким местом: разработчик ждёт результата дольше, чем пишет код. Независимые конвейеры разрывают эту связь — сервис собирается и проверяется только тогда, когда менялся его код или его зависимости.
Изоляция отказов — эффект, который замечают раньше всего. Ошибка в тестах одного сервиса больше не блокирует выпуск остальных: сборка падает в своей ветке, остальные идут дальше. Класс инцидентов «упал один — встали все» уходит, а границы отказа видны по каждому сервису, а не тонут в общем журнале.
Повторное использование зависимостей даёт ускорение без потери строгости. Кеш слоёв и артефактов привязывается к хешу манифеста: если состав зависимостей не менялся, шаг установки пропускается и берётся готовый результат — время сборки сокращается с десятков минут до единиц, и тем сильнее, чем больше сервисов используют общий набор библиотек.
Быстрый откат релиза — следствие того же разделения. Каждый сервис выпускается и откатывается своей версией артефакта: возврат на предыдущий образ не требует пересборки соседей и не тянет чужие изменения. В GitLab CI это выражается в правилах запуска по путям и отдельных окружениях на сервис; та же модель воспроизводима на любом зрелом инструменте сборки.
В сумме растёт частота релизов: выпуск перестаёт быть событием для всей команды и становится рутинной операцией отдельного сервиса.
Способы организации пайплайнов: сравнение вариантов
Модель организации конвейеров CI/CD выбирают не по размеру команды, а по тому, насколько сервисы расходятся по стеку сборки, частоте релизов и требованиям к изоляции. Границы конвейеров совпадают с границами ответственности: чем автономнее команда, тем дороже общий конвейер в сопровождении.
В монорепозитории те же модели дают разный компромисс. Общий конвейер собирает всё на каждый коммит, шаблонный оставляет единый стандарт этапов при своих триггерах у сервиса, раздельные конвейеры дают независимый выпуск, но требуют дисциплины при правках в общих библиотеках.
| Вариант | Когда подходит | Ограничения подхода |
|---|---|---|
| Общий конвейер | 3-5 сервисов с однотипным стеком и общим ритмом релизов | Правка одного этапа затрагивает все сервисы; сбой сборки блокирует остальные |
| Шаблонный конвейер с наследованием | Десятки сервисов, единый стандарт проверок и разные триггеры | Обратная совместимость шаблона: ломающее изменение этапа требует миграции всех наследников |
| Отдельный конвейер на сервис | Автономные команды, разные стеки, независимый выпуск | Дублирование описаний этапов; расхождение версий проверок между сервисами |
| Монорепозиторий с отбором затронутых сервисов | Много сервисов в одном репозитории, частые общие правки | Нужен точный разбор графа зависимостей: ошибка даёт пропущенный релиз или лишние сборки |
Что проверить перед выбором
Практический критерий — стоимость изменения: сколько сервисов затронет правка одного этапа. Если ответ «все», пора переходить от общего конвейера к шаблону или раздельным конвейерам.
Порядок работ: от аудита конвейеров до передачи команде
Разделение общего конвейера на независимые пайплайны начинают не с правки конфигурации, а с инвентаризации: пока не видно, что именно запускается на каждый коммит и что из этого действительно зависит от изменённого кода, любые изменения дают случайный результат. Ниже — последовательность, в которой риски снимаются по одному, а команда получает рабочую схему, а не набор файлов.
- Аудит конвейеров. Собираем список сборок, триггеров и стадий, замеряем время каждой из них и находим блоки, которые дублируются во всех сервисах. На выходе — картина, где сборка простаивает в ожидании чужого результата.
- Схема зависимостей. Фиксируем, какие сервисы связаны общими библиотеками, схемами данных и образами. Помечаем связи, которые обязаны вызывать пересборку, и те, что можно разорвать без риска.
- Проектирование раздельных конвейеров. Каждому сервису — свой набор стадий и свой триггер; повторяющиеся шаги выносим в переиспользуемые шаблоны, чтобы новая служба подключалась коротким описанием.
- Настройка окружений. Разводим среды, кэш и артефакты так, чтобы сборка одного сервиса не зависела от окружения соседей; доступы выдаём по принципу минимально необходимых.
- Проверка сборки на релизе. Прогоняем схему на реальных выпусках: параллельные сборки, откат на предыдущую версию, поведение при падении одной из служб. Убеждаемся, что изолированный сбой не останавливает остальные.
- Передача документации. Отдаём схемы конвейеров, описания зависимостей, регламент добавления сервиса и порядок правок, проводим разбор с командой. Сопровождение дальше идёт без нашего участия.
Что остаётся в репозитории: конфигурации, схемы, регламенты
Инфраструктура, описанная только в головах инженеров, живёт до первого отпуска или перехода автора на другой проект. Поэтому независимые пайплайны CI/CD мы фиксируем как код в репозитории: описания сборок, схемы окружений и регламенты лежат рядом с сервисом и меняются через ревью, а не по договорённости в чате. После сдачи заказчик получает полный комплект артефактов.
- Описания сборок. Декларативные конфигурации по каждому сервису: стадии, кэш зависимостей, условия запуска. Новый сервис подключается копированием шаблона, а не настройкой с нуля.
- Схемы окружений. Что где живёт: среды разработки, предпродакшена и продакшена, какие ветки в них попадают, где хранятся секреты и как они ротируются.
- Политики доступа. Роли для разработчиков, дежурных и ответственных за выпуск: кто запускает сборку, кто выкладывает в прод, где требуется подтверждение второго инженера.
- Регламент выпуска релиза. Порядок шагов от прогона тестов до продакшена, точки отката и критерии, при которых выпуск останавливается автоматически.
- Инструкции для дежурных. Что проверить при падении сборки, как откатить сервис к предыдущему образу, кому эскалировать — тексты, по которым можно действовать ночью без автора кода.
- Памятка по подключению нового сервиса. Пошаговый список: какие файлы добавить, какие политики расширить, как убедиться, что новый пайплайн не задел соседние.
Всё это хранится в той же системе контроля версий, что и код, — комплект обновляется вместе с проектом, а не устаревает отдельно от него.
Кейс: как раздельные конвейеры ускорили релизы в 8 раз
У клиента — платформа Финансовый сервис из 14 сервисов в одном репозитории. Правка в одном модуле запускала общий конвейер: он собирал, тестировал и публиковал всё, включая сервисы, которых изменения не касались. Очередь сборок занимала машины на часы, а релиз шёл единым пакетом — выкатить одну правку отдельно было нельзя.
Что показывали метрики до
Полный прогон длился около 48 минут, а если впереди стояли чужие сборки — ожидание растягивалось до 3-4 часов. Релизное окно открывалось раз в две недели, и срочная правка ждала его вместе с остальными. Доля успешных выпусков держалась на 62%: одна сломанная проверка в любом сервисе блокировала весь пакет, поэтому откатывали релиз целиком.
Что изменили
Разнесли общий конвейер на независимые: запуск по изменённым путям поднимает сборку только для тронутых сервисов, тесты и артефакты версионируются по каждому отдельно. Общие библиотеки вынесли в отдельные проверки, которые прогоняются лишь при их правке. Добавили раздельные окружения и автоматический откат на предыдущий артефакт сервиса.
Сборка укладывается в 6 минут, ожидание в очереди — минуты. Релиз любого сервиса идёт в день готовности, доля успешных выпусков выросла до 94%, а восстановление после сбоя сократилось с 40 минут до 7: откат затрагивает один сервис, а не всю платформу.
Что делать, если конвейер уже собран в один общий?
Общий конвейер на все сервисы — типовая точка роста: правка одного шага перезапускает сборку всех репозиториев, а падение на общем этапе блокирует релизы команд, которые ничего не меняли. Переписать всё разом нельзя — это остановка поставки. Поэтому переход делают слоями и держат общий конвейер рабочим до последнего сервиса.
Сначала из общего описания выносят базовую часть: установку зависимостей, проверки, публикацию артефакта, шаблоны развёртывания. Общий конвейер становится тонкой обёрткой над ней и продолжает собирать всё как раньше, а сервисный файл уже ссылается на ту же базу. Обратная совместимость сборок сохраняется: имена артефактов, теги образов и переменные окружения не меняются, поэтому откат на предыдущий релиз остаётся возможным.
Дальше сервисы переводят по одному, начиная с того, что релизится чаще всего и слабее связан с остальными. Новый независимый пайплайн CI/CD срабатывает только на изменения в своём репозитории, старый обслуживает остальных. Первые прогоны идут параллельно: артефакты и результаты проверок сравнивают, расхождения разбирают до отключения прежней схемы.
Заморозка релизов нужна локально: правки в общую часть на время переключения сервиса не вносят, иначе миграция и обычные изменения конфликтуют. Поставку команд при этом не останавливают — окно касается только общей обвязки. Секреты, доступы к реестру образов и права на окружения переносят заранее, чтобы сервисный конвейер получил ровно тот же объём доступа.
В системах вида GitLab CI и им подобных описание конвейера лежит в репозитории, поэтому переход сводится к переносу файла и подключению общих шаблонов, без переделки сборочного окружения. Когда переведён последний сервис, общий файл удаляют: релиз каждого сервиса больше не зависит от соседей.
Частые технические сомнения по раздельным сборкам
Независимые пайплайны CI/CD поднимают у заказчиков одни и те же инженерные вопросы — не про «сможете ли», а про поведение на их кодовой базе и в их команде.
Что делать с общими библиотеками, от которых зависят почти все сервисы?
Публикуем общий модуль как версионированный артефакт: сервис фиксирует конкретную версию, а не «последнюю». Обновление библиотеки перестаёт быть одновременным релизом — каждый сервис переходит своим конвейером, когда готов; совместимость держат контрактные тесты.
Нужен ли отдельный стенд тестирования под каждый сервис?
Нет: базовые окружения общие, а под ветку поднимается временное — живёт от первого коммита до слияния и удаляется само. Внешние зависимости подменяются заглушками с описанными ответами, поэтому проверки воспроизводимы и очередь за одним стендом не собирается.
Настройки сборок не разъедутся по сервисам?
Шаги сборки, проверок и публикации вынесены в переиспользуемые шаблоны: конфигурация сервиса описывает только свои отличия. Правка шаблона применяется ко всем сразу, а расхождения видны при слиянии, не в момент релиза.
Что с поддержкой после передачи?
Отдаём конфигурации, схемы зависимостей и регламент: как добавить шаг, как откатить релиз, что делать при падении проверок. Ваши инженеры разбирают это на живых сборках и дальше меняют их сами.
Обсудим задачу: разберём конвейеры и вернёмся с планом
Чтобы вернуться с планом перевода сервисов на независимые конвейеры, а не с общими соображениями, нам нужен доступ к вашей картине мира: репозитории, окружения и понимание, какие сервисы критичны для бизнеса. Разбор занимает одну встречу, после неё мы собираем схему и считаем объём работ по каждому сервису.
Что понадобится от вас для старта:
- доступы к репозиториям — на чтение веток, истории сборок и правил защиты веток, чтобы восстановить текущие регламенты, а не переписывать их наугад;
- перечень сервисов с приоритетами — что переводим первым, что связано с другими общими релизами и требует согласованного порядка;
- схема окружений — сколько контуров, чем отличаются их конфигурации, какие есть зависимости от внешних систем и баз данных;
- описание текущего пути кода до продакшена — где сейчас ручные шаги, какие проверки уже есть и на каком этапе чаще всего ломается выпуск;
- доступы к хранилищам образов, конфигураций и секретов на чтение — расширенные права выдадим позже, по согласованному плану и с ограничением по времени;
- контактное лицо со стороны разработки и эксплуатации — с кем согласовывать изменения в правилах сборки и порядок отката.
По итогам обсуждения вы получите карту конвейеров по сервисам, целевую схему окружений и поэтапный план перевода — от пилотного сервиса до остальных. Опишите задачу: вернёмся с оценкой объёма работ и планом.







