В статье «Как CI/CD и Flux делят ответственность в DocOps-проекте» разобрана схема доставки: пайплайн собирает и публикует образ контейнера, меняет его версию в отдельном GitOps-репозитории, а Flux приводит Kubernetes к записанному там состоянию.
Теперь рассмотрим условие, при котором проверки не блокируют развёртывание. В GitOps-репозитории настроен CI, но автоматизация отправляет изменение напрямую в ветку, которую отслеживает Flux. Проверка существует, но не стоит перед публикацией состояния.
Для анализа этой модели не требуется инцидент. Достаточно проверить порядок событий. Ниже разбирается сам механизм, а не состояние прав доступа или история изменений конкретной команды.
Один коммит запускает два независимых процесса
Если пайплайн меняет тег образа в GitOps-репозитории и отправляет коммит напрямую в основную ветку, один push может запускать два процесса:
коммит в основной ветке GitOps-репозитория
├── запускает GitOps CI
└── становится доступен Flux
GitLab начинает выполнять проверки. Flux независимо от него получает новую ревизию Git и запускает согласование состояния.
В модели Flux ресурс GitRepository получает указанную ветку и формирует артефакт из её текущей ревизии. Kustomization реагирует на изменение этого артефакта, строит манифесты и применяет их в Kubernetes.
Без дополнительной связи статус пайплайна GitLab в этой последовательности не участвует. Между CI и Flux нет причинной зависимости: ни один из них не ждёт результата другого.
Gate — это зависимость, а не задержка
На первый взгляд риск может казаться небольшим. CI обычно работает быстро, а Flux получает изменения с заданным интервалом. Пайплайн может завершаться раньше почти при каждом обычном развёртывании.
Но deployment gate не может основываться на слове «обычно».
Увеличение интервала Flux тоже не решает проблему. Пайплайн иногда выполняется дольше, согласование можно запустить вручную, а webhook способен передать изменение Flux почти сразу.
Пока между проверкой и публикацией коммита нет явной зависимости, порядок остаётся случайным.
Настоящая граница допуска должна обеспечивать следующую последовательность:
изменение конфигурации
→ обязательная проверка
→ успешный результат
→ публикация в отслеживаемую ветку
→ согласование состояния Flux
При прямом push порядок другой:
публикация в отслеживаемую ветку
→ параллельно проверка и согласование состояния
CI проверяет состояние, которое уже опубликовано для Flux.
Красный пайплайн ничего не возвращает назад
Если автоматический коммит содержит ошибку, GitOps CI может обнаружить её и завершиться неуспешно.
Красный статус сам по себе не удаляет коммит из основной ветки. Он не возвращает предыдущий тег образа, не отменяет уже начатое согласование состояния и не сообщает Flux, что эту ревизию применять нельзя.
К этому моменту Flux уже может получить коммит и начать обработку манифестов. Если изменение отклоняет сам Flux или Kubernetes API, это другой защитный слой. GitOps CI по-прежнему ничего не блокирует.
Такая проверка остаётся полезной. Она может обнаружить ошибку и сообщить о ней инженеру. Но в этой схеме CI работает как детектор после публикации, а не как предварительный допуск.
Как поставить проверку перед Flux
Вместо прямого push в отслеживаемую ветку автоматизация может подготовить изменение отдельно:
- Создать временную ветку в GitOps-репозитории
- Изменить тег уже собранного образа
- Отправить временную ветку в GitLab
- Создать Merge Request в основную ветку
- Разрешить слияние только после успешных обязательных проверок
Имена веток и поведение повторного запуска нужно определить отдельно. Разные выпуски не должны случайно перезаписывать изменения друг друга, а повтор не должен бесконтрольно создавать дубликаты Merge Request. Конкретный формат имени не является частью принципа deployment gate.
Последовательность получается такой:
подготовка новой версии
→ временная ветка в GitOps-репозитории
→ обновление тега образа
→ Merge Request
→ обязательный GitOps MR pipeline
→ успешные проверки и выполнение условий слияния
→ merge в основную ветку
→ Flux получает новый коммит
Изменение становится доступно Flux только после merge. Это работает как gate лишь при условии, что GitLab действительно требует успешные проверки перед слиянием.
Auto-merge не заменяет обязательные проверки
Автоматическое слияние может убрать ручное ожидание завершения CI. Но само включение auto-merge не доказывает, что нужный набор проверок обязателен: условия допуска нужно настроить и проверить отдельно.
После этого порядок выглядит так:
GitOps CI завершился успешно
→ выполнены остальные условия слияния
→ GitLab выполняет merge
→ коммит появляется в основной ветке
→ Flux получает новую ревизию
Создание Merge Request, включение auto-merge и фактическое слияние — разные результаты. Пайплайн, который только подготовил изменение, не должен выдавать это за завершённый merge или deployment.
Существенна причинная зависимость:
успешный обязательный GitOps CI
→ merge
→ публикация состояния для Flux
Ошибка должна оставлять изменение вне основной ветки
При неуспешном обязательном CI изменение должно оставаться во временной ветке и открытом Merge Request. Flux продолжает читать прежнее состояние основной ветки.
Конфликт также должен останавливать автоматическое слияние. Для продолжения нужен отдельный разбор, а не скрытое разрешение конфликта или переписывание истории ради зелёного результата.
Это важное свойство процесса. Ошибка автоматизации не должна маскироваться автоматическим исправлением Git-истории.
Merge Request нужен не только ради ручного согласования
В этой цепочке Merge Request не обязательно означает, что человек должен вручную подтверждать каждое обновление образа. Для стандартного изменения можно использовать auto-merge после выполнения настроенных условий.
Merge Request здесь служит технической границей:
временная ветка
→ проверка
→ основная ветка
Главное изменение заключается не в появлении новой сущности в GitLab. Меняется момент публикации желаемого состояния.
Не нужно учить Flux ждать GitLab
Другой вариант — заставить Flux перед согласованием состояния запрашивать статус пайплайна GitLab.
Такое решение связывает механизм доставки с конкретной CI-системой и добавляет новую точку отказа. Потребуется определить, кто получает статус, где хранятся учётные данные, какой пайплайн считается обязательным и что делать при недоступности GitLab.
Появится и новая гонка: статус одной ревизии может быть получен уже после появления следующей.
Проще изменить точку публикации. Отслеживаемая ветка должна быть источником состояния, уже прошедшего предусмотренный процесс.
Тогда Flux продолжает выполнять свою обычную задачу: читает Git и приводит Kubernetes к записанному там состоянию.
Гарантия зависит от всех способов изменить ветку
Схема обеспечивает предварительную проверку только для изменений, проходящих через неё. Отдельно нужно проверить прямые push, ручные слияния и административные исключения. Наличие MR в автоматизации само по себе не гарантирует защиту всех способов изменения отслеживаемой ветки.
Это условие применимости модели, а не утверждение о существующих обходах в какой-либо организации. Рабочие и аварийные процедуры должны иметь явно определённые правила допуска и полномочия.
Проверять следует не только обычный успешный выпуск. Нужны сценарии неуспешного CI, конфликта, повторного запуска и попытки изменить отслеживаемую ветку вне предусмотренного пути.
Что именно подтверждает этот gate
Эта статья рассматривает порядок событий: когда изменение проверяется и когда оно становится доступно Flux.
Она не оценивает полноту конкретного набора проверок GitOps CI. Состав и качество проверок — отдельный вопрос.
Даже идеальная проверка не является gate, если запускается после прямого push в отслеживаемую ветку. И наоборот, правильный порядок не гарантирует, что набор проверок покрывает все возможные ошибки.
Это две разные задачи:
положение проверки в процессе
≠
полнота самой проверки
Gate не подтверждает результат развёртывания
Правильно поставленная граница допуска решает только одну задачу: не позволяет изменению из предусмотренного процесса попасть в отслеживаемую ветку до успешного завершения обязательного GitOps CI.
Она не подтверждает, что Kubernetes скачал образ, завершил обновление Deployment и запустил работоспособное приложение.
Подтверждение результата развёртывания требует отдельного наблюдения за Flux, Kubernetes и самим приложением. Это следующая граница процесса, а не обязанность GitOps CI.
Как проверить собственную GitOps-схему
Для проверки процесса достаточно ответить на четыре вопроса:
- Какую ветку, тег или другую Git-ссылку отслеживает Flux
- Кто и каким способом может изменить эту ссылку
- Какие проверки должны завершиться до её изменения
- Может ли изменение попасть в неё в обход этих проверок
Если успешный результат CI не определяет, попадёт ли изменение в отслеживаемую ссылку, этот CI не является deployment gate.
Вывод
При прямом push в отслеживаемую ветку отдельный CI может создавать впечатление предварительной проверки. Но порядок событий другой: сначала коммит публикуется, а затем CI и Flux независимо начинают с ним работать.
Вариант с временной веткой, Merge Request и обязательными проверками меняет порядок:
изменение
→ GitOps CI
→ разрешённый merge
→ Flux
Deployment gate определяется не наличием CI и не скоростью пайплайна. Он определяется порядком событий и правилами доступа: сначала проверка, потом публикация состояния для Flux.
