Материал открыт для чтения

Войдите, чтобы сохранять прогресс и результаты.

Войти
GitLab CI/CD: от первых проверок до деплоя

CI/CD без магии: зачем это вообще нужно

чтение ~13 минУрок 1 из 20

CI/CD без магии: зачем это вообще нужно

module9 gitlab ci Image01

Привет! В этом курсе разберемся с CI/CD с нуля: зачем он нужен, что такое GitLab, откуда берутся автоматические проверки и как код постепенно доходит от commit до тестового стенда и сервера.

Представь обычную ситуацию. Мы изменили код и сохранили его в Git. На этом работа не заканчивается. Нужно понять, что старый функционал не сломался, новый функционал действительно заработал, тесты проходят, сборка работает, а новую версию можно показать на тестовом стенде.

Без CI/CD эти шаги часто делают вручную. Один разработчик запустил только тесты, другой не выполнил проверку стиля кода и типовых ошибок, третий собрал проект с другой переменной окружения. В маленьком проекте такой порядок ещё может работать, но в команде он быстро становится ненадёжным.

CI/CD нужен, чтобы сделать этот путь постоянным, понятным и одинаковым для всех. Команда один раз описывает список шагов: проверить код, запустить тесты, собрать приложение, сохранить результат, иногда выкатить на стенд. После этого система выполняет эти шаги сама каждый раз, когда появляется новое изменение.

Такой автоматический список шагов называется pipeline. По-русски pipeline можно перевести как конвейер: изменение кода проходит через несколько этапов, и на каждом этапе система делает понятную проверку или подготовку. Например:

commit -> tests -> build -> docker image -> deploy на тестовый стенд
module9 gitlab ci Image11

Каждый отдельный шаг внутри этого конвейера обычно называют job. Job - это конкретное действие, которое CI/CD-система должна выполнить на этом шаге. Например:

  • run-tests - запустить тесты проекта;
  • check-code - проверить код на типовые ошибки и единый стиль;
  • build-image - собрать Docker image;
  • deploy-dev - выложить новую версию на тестовую среду.

Теперь нужен инструмент, который будет хранить этот сценарий, запускать его по событию и показывать результат команде. Такие инструменты обычно называют CI/CD-системами или CI/CD-серверами. Они следят за проектом, читают описание pipeline и передают отдельные задания исполнителям.

GitLab - один из самых мощных и популярных современных инструментов такого типа. Он умеет не только хранить Git-репозиторий, но и запускать CI/CD, хранить переменные, показывать результаты выполненных заданий, сохранять файлы и отчёты после выполнения, держать Docker-образы во встроенном хранилище и помогать команде работать с кодом.

GitLab - очень большая платформа, поэтому в одном базовом курсе невозможно разобрать каждую кнопку. Внутри есть репозитории, merge requests, issues, wiki, registry, runners, environments, security-разделы, package registry, настройки прав, approvals, интеграции и ещё много всего. В этом курсе мы берём основной рабочий сценарий, который чаще всего нужен DevOps-инженеру и разработчику на старте:

репозиторий -> .gitlab-ci.yml -> pipeline -> jobs -> artifacts/reports -> registry -> deploy

Остальные разделы GitLab будут встречаться постепенно и только там, где они помогают понять этот маршрут.

В учебных задачах мы часто будем использовать очень простые команды внутри job: echo, pwd, date, ls, создание маленьких файлов и вывод переменных. Это сделано специально: нам важно разобраться с самим написанием и выполнением pipeline. Реальные команды тестирования, сборки и deploy постепенно появятся дальше.

В реальной работе вместо этих простых команд обычно стоят команды проекта:

  • запустить тесты;
  • проверить код линтером;
  • собрать frontend или backend;
  • собрать Docker image;
  • отправить image в registry;
  • выполнить deploy на тестовый стенд или production.

То есть учебный echo "hello" - это не цель CI/CD, а простой пример команды внутри job. Механика та же самая: GitLab создаёт job, runner выполняет команды, а pipeline показывает результат.

В GitLab описание pipeline обычно лежит в файле .gitlab-ci.yml в корне репозитория. Когда ты делаешь git push, GitLab автоматически читает этот файл, понимает, какие jobs нужно запустить, и передаёт их специальному исполнителю. Этот исполнитель называется runner (подробнее рассмотрим далее).

Некоторые термины GitLab встретятся дальше, поэтому коротко:

  • issue - задача или обсуждение внутри проекта;
  • merge request - предложение разработчика добавить изменения из одной ветки в другую; (обычно после окончания написания кода по отдельной задаче)
  • artifact - файл, который job сохранил после выполнения, например отчёт тестов или архив сборки;
  • container registry - хранилище Docker images внутри проекта.

В реальной командной работе GitLab часто используют так: в issue описывается задача, разработчик делает отдельную ветку, после выполнения открывает merge request, GitLab запускает pipeline для этой ветки, команда смотрит тесты и review, а затем изменения попадают в основную ветку. В этом курсе основной упор на CI/CD, но merge requests и issues важно узнавать в интерфейсе: они часто находятся рядом с pipeline и помогают понять, почему pipeline вообще был запущен.

GitLab не единственный инструмент для CI/CD. Часто встречаются:

  • GitHub Actions - встроенный CI/CD в GitHub;
  • Jenkins - старый и очень гибкий CI-сервер, который часто живет отдельно;
  • TeamCity - CI/CD от JetBrains;
  • CircleCI, Drone, Buildkite, Azure Pipelines и другие платформы.

Идея у них похожая: есть событие, например git push, есть описание шагов, есть исполнитель, который эти шаги запускает. В этом курсе мы используем GitLab, потому что в нём репозиторий, CI/CD, переменные, отчёты и Docker registry собраны в одной системе.

Коротко:

  • CI проверяет новый код: тесты, линтеры, сборка, отчёты.
  • CD готовит код к доставке или выкатывает его дальше.
  • Continuous Delivery обычно означает, что новая версия собрана и готова к релизу, но финальное решение может принять человек.
  • Continuous Deployment означает, что успешная версия выкатывается автоматически без ручного подтверждения.

Что такое CI

CI - continuous integration. Практически это означает: после изменений код автоматически проверяется.

Примеры CI-задач:

  • проверить, что основной функционал не сломался;
  • запустить линтер (проверка самого кода по правилам);
  • запустить unit tests (тестирование);
  • собрать приложение (например java);
  • собрать Docker image;
  • запушить Docker image в registry;
  • сохранить test report и т.п.

Главная цель CI - автоматически проверить, что после нового commit не сломалось то, что уже работало, а также подготовить новый код к следующему шагу: собрать приложение, сохранить отчёты, подготовить артефакты или Docker image, который потом можно показать на тестовом стенде.

Что такое CD

CD означает continuous delivery или continuous deployment, то есть доставку собранного приложения на сервер.

Примеры CD-задач:

  • подключиться к серверу;
  • обновить .env;
  • выполнить docker compose up -d или kubectl apply;
  • записать, какой commit задеплоен.

Кто что делает

Важно не путать CI/CD-сервер и исполнителя заданий. GitLab, Jenkins и похожие системы обычно не выполняют команды сами внутри своего основного процесса. Их главная роль - организовать процесс: хранить репозиторий, прочитать описание pipeline, решить какие jobs нужно запустить, показать статус, сохранить logs, artifacts и историю запусков.

Но сами команды из job должен выполнить отдельный “работник”. В GitLab такой исполнитель называется runner. Runner получает job от GitLab, запускает команды из script, следит за результатом и отправляет обратно статус: job прошёл успешно или упал с ошибкой.

Runner может быть установлен по-разному:

  • как отдельный сервис на отдельной машине, специально выделенной под CI/CD;
  • как контейнер Docker;
  • внутри Kubernetes-кластера;

Ещё у runner есть разные способы выполнять job. В GitLab это называют executor. Самые базовые варианты:

  • shell executor - runner запускает команды прямо в shell той машины, где он установлен;
  • docker executor - runner для каждого job создаёт отдельный Docker container и выполняет команды внутри него;
  • kubernetes executor - runner создаёт временный Pod в Kubernetes и запускает job там.

В этом курсе мы чаще всего будем использовать docker executor. Когда в job написано:

test:
  image: alpine:3.20
  script:
    - echo "hello"

это означает не “установи alpine на сервер”. Выполнится следующее, runner берёт Docker image alpine:3.20 (все равно что мы запустим docker run alpine:3.20), создаёт из него временный container, запускает внутри этого container команды из script, собирает log и завершает job. После этого container обычно удаляется, а в GitLab остаются статус, log и artifacts, если job их сохранил.

В этом курсе runner уже настроен заранее. Поэтому в лабораторных тебе не нужно регистрировать runner вручную: мы сосредоточимся на работе pipeline. Ты пишешь .gitlab-ci.yml, делаешь git push, а подключённый runner забирает jobs и выполняет их. Но если ты будешь разворачивать GitLab самостоятельно, важно помнить: одного GitLab недостаточно. Нужно ещё создать runner, зарегистрировать его в GitLab и убедиться, что он доступен проекту. Это не сложно и делается несколькими командами.

GitLab       хранит репозиторий, pipeline, variables, artifacts и registry
Runner       забирает задания от GitLab и выполняет сами команды из job

В лабораторных у тебя будет отдельный пользователь GitLab и приватный проект. Проект создается под твою учебную VM и удаляется после остановки VM.

В следующей статье отдельно познакомимся с интерфейсом GitLab: где находится проект, куда нажимать после входа, где смотреть pipeline, jobs и logs. Сейчас важно удержать общую картину: GitLab хранит сценарий, runner выполняет команды, а .gitlab-ci.yml описывает, что именно должно произойти.

Что будет в этом курсе

Мы идем от самого простого к рабочему сценарию:

  1. Первый pipeline с echo, date, pwd и shell-командами.
  2. Stages и jobs: почему одни задачи идут параллельно, а другие ждут.
  3. Variables, artifacts и cache: как передавать данные и настройки.
  4. Rules: запуск по push, вручную, через API и только по тегу.
  5. Include, extends и matrix: как не копировать один и тот же YAML.
  6. Reports, retry, timeout и resource group.
  7. Docker image, GitLab Container Registry и deploy на учебную VM через SSH.
  8. Docker Compose на VM как имитация сервера.

gitlab-ci

Условно весь курс и почти вся практическая работа с GitLab CI/CD будут крутиться вокруг одного главного файла - .gitlab-ci.yml.

Это обычный текстовый YAML-файл в корне Git-репозитория. Но для GitLab он играет роль инструкции: что делать после изменений в коде, какие проверки запустить, в каком порядке выполнять этапы, какие команды отдавать runner-у, какие файлы сохранить как результат и когда можно переходить к deploy.

Проще всего думать о .gitlab-ci.yml как о плане работы для автоматического конвейера:

  • pipeline - весь запуск целиком;
  • stages - крупные этапы этого запуска, например проверка, сборка и deploy;
  • jobs - конкретные действия внутри этапов;
  • script - команды, которые runner реально выполнит;
  • image - окружение, внутри которого job будет выполняться.

В начале курса этот файл будет совсем маленьким: один job и несколько команд. Потом мы будем постепенно добавлять в него новые возможности: несколько stages, variables, artifacts, cache, rules, manual jobs, environments, include, matrix, сборку Docker image и deploy. Так ты не просто увидишь много отдельных настроек GitLab, а поймёшь, как из одного маленького файла постепенно вырастает нормальный CI/CD pipeline для проекта.

Минимальный pipeline

stages:
  - verify

hello:
  stage: verify
  image: alpine:3.20
  script:
    - echo "hello from GitLab CI"

Рассмотрим самый минимальный pipeline.

Здесь есть один stage и один job. Runner скачает образ alpine:3.20, запустит контейнер и выполнит команды из script.

Запомним минимальный набор:

  • stages - список этапов pipeline;
  • имя вроде hello - это job; (может быть любым)
  • stage говорит, к какому этапу относится job;
  • image задаёт контейнер, где выполняются команды;
  • script содержит сами команды job;
  • отступы в YAML важны: job стоит без отступа, а его поля идут с двумя пробелами.

Если в данный момент не особо понятно что это и зачем, дальше на примере все встанет на свои места.

Важная привычка

Pipeline - это обычный код. Его нужно писать маленькими шагами:

  • сначала добиться одного успешного job;
  • потом добавить второй job;
  • потом добавить artifacts;
  • потом добавить variables;
  • потом добавить rules;
  • только после этого делать deploy.

Так проще отлаживать. Если сразу написать большой deploy pipeline, ошибка может быть в YAML, shell, Docker, правах registry, SSH, переменных или приложении.

Материал изучен?

Войдите, чтобы сохранить прогресс и перейти к практической лаборатории.

Войти и продолжить