CI/CD пайплайны
CI против CD и Continuous Deployment, стадии и гейты пайплайна, стратегии выката и откат, раннеры, артефакты и кеш, секреты и безопасность цепочки поставки.
15 вопросов
JuniorТеорияОчень частоВ чём разница между CI, Continuous Delivery и Continuous Deployment?
В чём разница между CI, Continuous Delivery и Continuous Deployment?
CI (Continuous Integration) — автосборка и автотест каждого влитого изменения, чтобы проблемы всплывали рано. Continuous Delivery держит каждую сборку релизной за одобрением человека. Continuous Deployment убирает гейт — прошедшие изменения едут в прод сами.
Типичные ошибки
- ✗Считать Continuous Delivery и Continuous Deployment одним и тем же
- ✗Думать, что CI включает выкат в прод, а не сборку и тесты
- ✗Верить, что Continuous Deployment всё ещё требует ручного одобрения
Уточняющие вопросы
- →Почему Continuous Deployment требует сильного набора автотестов и мониторинга?
- →Какие изменения в процессах позволяют команде перейти от Delivery к Deployment?
MiddleДизайнОчень частоКоманда держит stateless веб-API за балансировщиком на фиксированном парке машин. Деплой сейчас вызывает краткий простой, а откаты медленные и ручные. Есть бюджет примерно удвоить ёмкость на окно релиза. Спроектируйте blue-green деплой: как поднять новую версию, переключить трафик, проверить её и мгновенно откатиться при сбое. Объясните стоимость по ёмкости и одно ограничение blue-green при изменениях схемы базы данных.
Команда держит stateless веб-API за балансировщиком на фиксированном парке машин. Деплой сейчас вызывает краткий простой, а откаты медленные и ручные. Есть бюджет примерно удвоить ёмкость на окно релиза. Спроектируйте blue-green деплой: как поднять новую версию, переключить трафик, проверить её и мгновенно откатиться при сбое. Объясните стоимость по ёмкости и одно ограничение blue-green при изменениях схемы базы данных.
Два одинаковых окружения — blue (боевое) и green (простаивающее). Разверните новую версию на green и smoke-тестируйте, пока blue обслуживает пользователей. Переключитесь, наведя балансировщик на green — мгновенный свитч; blue держите тёплым для отката. Нужно ~2x ёмкости, схема остаётся обратно совместимой.
Типичные ошибки
- ✗Переключать трафик на green до его smoke-тестов рядом с blue
- ✗Забывать, что blue-green нужна примерно двойная ёмкость на окно
- ✗Катить ломающее изменение схемы, которое терпит лишь новая версия
Уточняющие вопросы
- →Как слить незавершённые запросы из blue во время переключения?
- →Как разбить ломающее изменение схемы на обратно совместимые шаги?
SeniorДизайнОчень частоВы держите высоконагруженный пользовательский сервис и хотите сузить радиус поражения плохих релизов — полный выкат иногда катит регрессию, будящую дежурного раньше, чем её кто-то заметит. Спроектируйте canary-релиз с автоматическим продвижением по метрикам: как направить малую долю трафика на новую версию, какие сигналы гейтят продвижение, как прогрессирует выкат и что запускает автоматический откат. Сравните с blue-green и укажите, когда canary — неверный выбор.
Вы держите высоконагруженный пользовательский сервис и хотите сузить радиус поражения плохих релизов — полный выкат иногда катит регрессию, будящую дежурного раньше, чем её кто-то заметит. Спроектируйте canary-релиз с автоматическим продвижением по метрикам: как направить малую долю трафика на новую версию, какие сигналы гейтят продвижение, как прогрессирует выкат и что запускает автоматический откат. Сравните с blue-green и укажите, когда canary — неверный выбор.
Разверните новую версию рядом со старой и направьте малую долю трафика (скажем, 5%). Следите за error rate, задержкой и насыщением против baseline. Держатся bake-период — поднимайте долю (5, 25, 50, 100%); пробили порог — откат к 0%. В отличие от blue-green, экспозиция растёт постепенно.
Типичные ошибки
- ✗Слать весь трафик разом вместо малой начальной доли
- ✗Гейтить продвижение по прошедшему времени, а не по сигналам здоровья
- ✗Считать, что canary всегда лучше blue-green независимо от трафика и метрик
Уточняющие вопросы
- →Как выбрать пороги, ловящие регрессии без ложных откатов?
- →Как canary честно сравнивает новую версию с baseline?
MiddleДебаггингЧастоИнтеграционный job зелёный локально, но флакает в CI примерно в 1 прогоне из 5 без изменений кода. Найдите и устраните причину.
Интеграционный job зелёный локально, но флакает в CI примерно в 1 прогоне из 5 без изменений кода. Найдите и устраните причину.
sleep 3 — гонка: под нагрузкой CI приложение или база не всегда готовы за три секунды, поэтому часть прогонов тестит рано и падает с connection-refused. Замените его опросом готовности health-эндпоинта с таймаутом перед pytest. Ждите условие, а не часы.
Типичные ошибки
- ✗Лечить гонку удлинением sleep вместо ожидания готовности
- ✗Прятать флакование сплошным retry задачи вместо корневой причины
- ✗Винить железо CI вместо допущения о таймингах в конфиге
Уточняющие вопросы
- →Как выглядел бы опрос готовности с таймаутом в скрипте?
- →Когда ограниченный retry задачи уместен, а когда прячет реальные баги?
MiddleТеорияЧастоКак feature-флаги разделяют выкат кода и релиз фичи для пользователей?
Как feature-флаги разделяют выкат кода и релиз фичи для пользователей?
Feature-флаг оборачивает новый код в условие времени выполнения, так что он едет выключенным. Это разделяет деплой (бинарник на прод) и релиз (включение для пользователей). Незавершённый код вливают, включают постепенно и мгновенно гасят флагом, без передеплоя.
Типичные ошибки
- ✗Думать, что флаг — это compile-time, а не рантайм-переключатель
- ✗Смешивать деплой (бинарник на проде) и релиз (фича включена для пользователей)
- ✗Упускать, что флаги дают постепенный выкат и мгновенный выключатель
Уточняющие вопросы
- →Какой операционный риск несут устаревшие, неудалённые feature-флаги?
- →Как флаги поддерживают A/B-тесты или процентный выкат?
MiddleДизайнЧастоCI-пайплайну нужны пароль реестра для пуша образа, облачный ключ для деплоя и URL базы для интеграционных тестов — сейчас они лежат открытым текстом в YAML репозитория. Спроектируйте безопасный поток секретов: где они хранятся, как задачи их получают, как не пустить их в логи сборки и как ограничить радиус поражения, если раннер или форк скомпрометированы.
CI-пайплайну нужны пароль реестра для пуша образа, облачный ключ для деплоя и URL базы для интеграционных тестов — сейчас они лежат открытым текстом в YAML репозитория. Спроектируйте безопасный поток секретов: где они хранятся, как задачи их получают, как не пустить их в логи сборки и как ограничить радиус поражения, если раннер или форк скомпрометированы.
Держите секреты вне репозитория — в менеджере секретов или защищённых переменных CI, отдавая их переменными окружения только нужным задачам. Ограничьте каждый окружением и ветками, маскируйте в логах, не выводите. Предпочитайте короткоживущие ротируемые доступы (OIDC-токены) долгоживущим ключам.
Типичные ошибки
- ✗Коммитить секреты в репозиторий, пусть в base64, считая это шифрованием
- ✗Открывать каждый секрет каждой задаче и пайплайнам недоверенных форков
- ✗Выводить секреты в логи или полагаться лишь на долгоживущие ключи
Уточняющие вопросы
- →Как OIDC даёт задаче облачный токен без единого хранимого ключа?
- →Почему пайплайны форков особенно опасны для защищённых секретов?
MiddleПроизводительностьЧастоCI-сборка идёт 40 минут и блокирует каждый мёрж. Где искать первый прирост скорости с наибольшей отдачей?
CI-сборка идёт 40 минут и блокирует каждый мёрж. Где искать первый прирост скорости с наибольшей отдачей?
Сначала профилируйте пайплайн, чтобы найти медленные стадии — не гадайте. Больше всего дают кеш зависимостей, параллелизм независимых задач (шардинг тестов, lint и сборка вместе), переиспользование кеша слоёв Docker через порядок в Dockerfile и запуск затронутой работы. И fail-fast, чтобы сборка падала рано.
Типичные ошибки
- ✗Оптимизировать наугад вместо профилирования самых медленных стадий
- ✗Пропускать кеш зависимостей и слоёв Docker как небезопасный
- ✗Гонять всё последовательно, когда независимые задачи могли бы идти параллельно
Уточняющие вопросы
- →Как порядок инструкций в Dockerfile влияет на то, какие слои остаются в кеше?
- →Что позволяет гонять только затронутые данным изменением тесты?
JuniorТеорияИногдаКаковы типичные стадии CI/CD-пайплайна и почему он должен падать рано (fail-fast)?
Каковы типичные стадии CI/CD-пайплайна и почему он должен падать рано (fail-fast)?
Пайплайн выполняет упорядоченные стадии — сборка, юнит-тесты, статический анализ и сканы безопасности, упаковка артефакта, затем деплой. Дешёвые быстрые проверки идут первыми, поэтому сбой останавливает прогон сразу (fail-fast): разработчик быстро получает фидбэк, а поздние медленные стадии не тратят минуты, раз ранняя уже сломалась.
Типичные ошибки
- ✗Запускать медленные end-to-end тесты до дешёвых быстрых проверок
- ✗Продолжать пайплайн после сбоя вместо ранней остановки
- ✗Пропускать статический анализ или сканы безопасности как необязательные
Уточняющие вопросы
- →Куда поставить стадию интеграционных или end-to-end тестов относительно юнит-тестов?
- →Как fail-fast сочетается с задачами, которые вы хотите запускать параллельно?
JuniorТеорияИногдаЧем отличаются общие и self-hosted CI-раннеры, и когда нужен self-hosted?
Чем отличаются общие и self-hosted CI-раннеры, и когда нужен self-hosted?
Общие раннеры — пул облачных машин под управлением провайдера: ноль настройки, универсальное окружение. Self-hosted — машины, которыми владеете вы. Их выбирают ради GPU или особого железа, приватной сети или on-prem, больших кешей и контроля.
Типичные ошибки
- ✗Менять местами определения общих и self-hosted раннеров
- ✗Думать, что общий раннер дотянется до on-prem или приватной сети
- ✗Упускать, что self-hosted берут ради особого железа или больших кешей
Уточняющие вопросы
- →Какие новые обязанности по безопасности приносят свои self-hosted раннеры?
- →Почему self-hosted раннеры часто делают эфемерными, а не долгоживущими?
JuniorТеорияИногдаКак убедиться, что деплой действительно прошёл, прежде чем ему доверять?
Как убедиться, что деплой действительно прошёл, прежде чем ему доверять?
Не доверяйте нулевому коду деплоя — проверьте работающее приложение: health- и readiness-эндпоинты healthy, smoke-тесты по критичным путям, error rate и задержка без регрессии, отдаётся новая версия. Гейт блокирует или откатывает при провале.
Типичные ошибки
- ✗Считать код 0 доказательством, что деплой жив и здоров
- ✗Пропускать smoke-тесты и health-проверки работающего приложения
- ✗Не подтверждать, какая версия на деле отдаётся
Уточняющие вопросы
- →В чём разница между health-проверкой и smoke-тестом здесь?
- →Как встроить автоматический откат в этот гейт продвижения?
MiddleТеорияИногдаКак устроена модель исполнения CI-раннера — как задача подхватывается и выполняется?
Как устроена модель исполнения CI-раннера — как задача подхватывается и выполняется?
Раннер — агент, опрашивающий CI-сервер на задачи под его теги. Взяв задачу, он поднимает чистый executor — свежий контейнер, VM или shell — клонирует репозиторий на коммите, восстанавливает кеши, выполняет script, загружает артефакты и сносит его.
Типичные ошибки
- ✗Считать, что состояние живёт между задачами, а не чистый executor на задачу
- ✗Думать, что сервер проталкивает задачи, а не раннер опрашивает их
- ✗Забывать, что раннер клонирует репозиторий на конкретном коммите задачи
Уточняющие вопросы
- →Почему свежий executor на каждую задачу важен для воспроизводимых сборок?
- →Как теги раннера решают, какой раннер возьмёт данную задачу?
MiddleТеорияИногдаВ чём разница между артефактом пайплайна и кешем, и когда использовать каждый?
В чём разница между артефактом пайплайна и кешем, и когда использовать каждый?
Артефакт — выход сборки, который вы храните и передаёте дальше — jar, образ, отчёт — версионируемый и неизменяемый; от него зависит корректность. Кеш — оптимизация скорости: переиспользуемые входы по хешу lock-файла. Пайплайн обязан работать с пустым кешем.
Типичные ошибки
- ✗Полагаться на кеш ради корректности вместо отношения к нему как к необязательному
- ✗Хранить крупные неизменяемые выходы как кеш, а не как артефакты
- ✗Не ключевать кеш хешем lock-файла, из-за чего он не инвалидируется
Уточняющие вопросы
- →Что делает ключ кеша хорошим и что будет, если он никогда не инвалидируется?
- →Почему артефакты должны быть неизменяемыми и уникально версионируемыми в релизе?
MiddleДебаггингИногдаЗадача деплоя завершается с кодом 0, но прод продолжает отдавать прошлую сборку. Где сломался пайплайн?
Задача деплоя завершается с кодом 0, но прод продолжает отдавать прошлую сборку. Где сломался пайплайн?
Изменяемый тег latest не меняет спецификацию Deployment, поэтому kubectl set image не видит разницы и не запускает выкат — ничего не тянется. Фикс — неизменяемые теги: пушьте app:$CI_COMMIT_SHA и наводите Deployment на него. Собирайте раз, продвигайте тот же артефакт.
Типичные ошибки
- ✗Использовать изменяемый тег
latest, из-за чего спецификация не меняется - ✗Ждать выкат, когда
kubectl set imageне видит разницы - ✗Пересобирать отдельный образ под каждое окружение вместо продвижения одного
Уточняющие вопросы
- →Почему build-once-promote-many безопаснее пересборки под каждое окружение?
- →Как
imagePullPolicyвзаимодействует с переиспользуемым изменяемым тегом?
SeniorДизайнИногдаПосле инцидента с отравлением зависимостей в индустрии ваша организация хочет укрепить цепочку поставки ПО в CI/CD. Спроектируйте меры: как сделать сборки доверенными и воспроизводимыми, как точно знать, что вошло в выпущенный артефакт, как не дать подменённой или вредоносной зависимости либо шагу сборки дойти до прода и как потребитель ниже по цепочке может проверить, что артефакт действительно из вашего пайплайна. Назовите ключевые артефакты и механизмы.
После инцидента с отравлением зависимостей в индустрии ваша организация хочет укрепить цепочку поставки ПО в CI/CD. Спроектируйте меры: как сделать сборки доверенными и воспроизводимыми, как точно знать, что вошло в выпущенный артефакт, как не дать подменённой или вредоносной зависимости либо шагу сборки дойти до прода и как потребитель ниже по цепочке может проверить, что артефакт действительно из вашего пайплайна. Назовите ключевые артефакты и механизмы.
Закрепите зависимости версией и хешем в lock-файле из внутреннего прокси, не из интернета. Сгенерируйте SBOM (software bill of materials) и просканируйте на известные уязвимости. Собирайте в изолированном раннере с малыми правами и пишите подписанный provenance (SLSA). Допускайте в прод только подписанные.
Типичные ошибки
- ✗Тянуть зависимости без закрепления и хеша прямо из публичных индексов
- ✗Считать SBOM, provenance и подпись бумажной работой без ценности
- ✗Собирать с широкими правами вместо изолированного раннера с минимумом прав
Уточняющие вопросы
- →Как подписанный provenance мешает скомпрометированному шагу сборки спрятаться?
- →Что обеспечивает допуск только подписанных, прошедших политику артефактов при деплое?
JuniorТеорияРедкоКак в GitLab CI стадии и задачи (jobs) в .gitlab-ci.yml формируют пайплайн?
Как в GitLab CI стадии и задачи (jobs) в .gitlab-ci.yml формируют пайплайн?
.gitlab-ci.yml описывает пайплайн как задачи (jobs), каждая в своём stage. Задачи одной стадии идут параллельно; стадии — последовательно, и следующая стартует лишь после прохождения всех задач текущей. У каждой задачи свой script.
Типичные ошибки
- ✗Думать, что стадии идут параллельно, а задачи последовательно (всё наоборот)
- ✗Ждать старта следующей стадии до полного прохождения текущей
- ✗Верить, что задача не может объявить свои артефакты, кеш или rules
Уточняющие вопросы
- →Как
needsпозволяют задаче стартовать до завершения всей предыдущей стадии? - →Что меняет
allow_failureво влиянии задачи на пайплайн?