Инженерия ПО

CI/CD Pipeline

2011 год, конференция Velocity. Jon Jenkins из Amazon показывает цифру: production-деплой каждые 11.6 секунд в среднем. К 2014-му Werner Vogels отчитывается о 50 млн деплоев в год по dev/test/prod. Это не гипербола, это телеметрия. Что отличает Amazon, Google, Netflix от компаний, деплоящих раз в квартал? CI/CD pipeline. Автоматизация от коммита до прода, которая превращает релиз в скучную рутину вместо праздничного события с дежурством в ночь.

  • **Netflix Chaos Engineering + CD**: Netflix деплоит новую версию Chaos Monkey, проверяет что она правильно убивает инстансы, всё автоматически - от коммита до production за 20 минут
  • **Stripe**: полный CI pipeline (тысячи тестов) за 5 минут через параллелизацию на 100+ worker'ах. Без оптимизации те же тесты занимали бы 8 часов
  • **GitHub Actions для GitHub**: разработчики GitHub используют GitHub Actions для деплоя самого GitHub - несколько деплоев в день, zero-downtime через canary

Build Stage

Build stage - первый шаг pipeline: компиляция кода, сборка зависимостей, создание артефакта. Ключевое требование: быстро. Google установил норму: build за 10 минут считается медленным, цель - менее 5 минут. Медленный build - это прямые потери: разработчик ждёт вместо работы, feedback loop растягивается, частота коммитов падает.

Оптимизация build: кеширование зависимостей (node_modules, Maven .m2, pip cache), параллельная сборка модулей, incremental builds (пересобирать только изменившиеся части). Docker layer caching: COPY package.json до COPY . - если зависимости не менялись, слой с npm install берётся из кеша. Без этого каждый push пересобирает все зависимости.

Dockerfile сначала копирует весь код (COPY . .), потом устанавливает зависимости (npm install). В чём проблема?

Test Stage

Test stage запускает автоматические проверки: unit tests, integration tests, e2e tests, linting, security scanning. Пирамида тестирования определяет соотношение: много unit (быстрые, изолированные), меньше integration (проверяют взаимодействие компонентов), мало e2e (медленные, хрупкие, дорогие). Google Test Size: Small (unit, < 1 сек), Medium (integration, < 1 мин), Large (e2e, < 15 мин).

Fail fast: тесты с самым высоким signal/noise ratio запускаются первыми. Если lint или unit tests падают - integration tests не запускаются. Параллельное выполнение: разные тест-суиты в разных job'ах. GitHub Actions позволяет запустить 50+ параллельных job'ов. Stripe разбивает тесты на 100+ параллельных worker'ов - весь suite за 5 минут вместо 8 часов последовательно.

Unit tests проходят за 30 сек, integration tests за 5 мин, e2e за 20 мин. В каком порядке запускать в CI pipeline?

Deploy Stage

Deploy stage публикует артефакт в окружение. Environments: dev (автоматический деплой при каждом push в main), staging (production-like окружение для QA), production (с approval gate или автоматически для high-velocity команд). Принцип: один и тот же артефакт проходит через все окружения - никакой пересборки. Артефакт собирается один раз, параметры среды передаются через environment variables.

Deployment strategies в CI/CD: Rolling update (заменяет инстансы по одному, нет даунтайма, но временно сосуществуют две версии), Blue-Green (переключение трафика между двумя полными окружениями, мгновенный rollback), Canary (постепенный rollout с мониторингом метрик). Kubernetes поддерживает все три из коробки через Deployment, Service и Ingress объекты.

Команда собирает Docker image в staging, тестирует его, а для production пересобирает тот же код. В чём проблема?

Artifacts и Registry

Артефакт - неизменяемый результат build stage: Docker image, JAR файл, npm пакет, бинарный файл. Хранится в registry (Docker Hub, GHCR, AWS ECR, Artifactory). Ключевое: артефакт тегируется git commit SHA, а не latest или ветковым именем. latest - антипаттерн: у него нет трассировки к коду, любой push перезаписывает его.

Artifact retention policy: хранить N последних версий или N дней. Бесконтрольное накопление образов (каждый push добавляет 500MB - 2GB Docker image) создаёт проблемы: дорогое хранилище, медленный registry, потеря контроля. GitHub Container Registry позволяет настроить автоматическое удаление старых версий. Production артефакты хранятся дольше (90 дней) чем dev (7 дней).

Docker image всегда тегируется как 'latest' при push в main. Почему это проблема в production?

Rollback стратегия

Rollback - возврат к предыдущей рабочей версии при инциденте. Ключевой принцип: rollback должен занимать минуты, не часы. Kubernetes kubectl rollout undo: одна команда - предыдущий ReplicaSet становится активным. Это работает только если артефакты версионированы через SHA тег и предыдущая версия ещё в registry.

Database migrations усложняют rollback: новая версия добавила колонку - старая версия её не знает, но данные уже есть. Expand-Contract migration: сначала добавить новую колонку, деплоить код поддерживающий оба состояния, затем удалить старую колонку. Никогда не делать breaking migration и деплой одновременно. Blue-green упрощает rollback для stateless сервисов, но база данных всегда общая.

CI и CD - это одно и то же, просто разные аббревиатуры

Continuous Integration (CI) - автоматическая сборка и тестирование при каждом коммите. Continuous Delivery (CD) - автоматизация деплоя до staging с ручным approve для production. Continuous Deployment - полная автоматизация включая production без ручного approve

Разграничение важно: CI - техническая практика (тесты), CD - организационная зрелость (кто решает когда деплоить). Многие команды имеют CI без CD - тесты автоматические, деплой ручной

Новая версия API добавила NOT NULL колонку в таблицу. Деплой прошёл, но появились ошибки. Rollback к предыдущей версии кода невозможен потому что...

Ключевые идеи

  • **Build**: быстро (< 5 мин), кеширование зависимостей, Docker layer caching - один артефакт собирается один раз и тегируется git SHA
  • **Test**: пирамида (unit -> integration -> e2e), fail fast, параллельные job'ы - дают быстрый feedback loop при каждом коммите
  • **Deploy + Rollback**: один артефакт через все окружения, rollback через kubectl rollout undo, Expand-Contract для database migrations

Связанные темы

CI/CD - техническая основа современных процессов разработки:

  • Git Flow и стратегии ветвления — Trunk-Based Development требует CI как обязательного условия - нельзя коммитить в main без автоматических тестов
  • SRE: Site Reliability Engineering — CD pipeline реализует error budget - частота деплоев и rollback стратегия определяют reliability системы

Вопросы для размышления

  • Команда боится частых деплоев потому что 'каждый деплой - это риск'. Как CI/CD меняет это уравнение?
  • Когда database migration становится блокером для быстрого rollback и как Expand-Contract pattern решает эту проблему?
  • Как измерить зрелость CI/CD практики команды? Какие метрики показывают прогресс?

Связанные уроки

  • os-02-processes
CI/CD Pipeline

0

1

Войти