Skip to content
страница целиком, в Markdown — вставьте в чат с моделью

Поток пайплайна ​

Эта страница описывает полный жизненный цикл CI/CD-пайплайна — от git push до работающего сервиса на ноде своего окружения.

Общая схема ​

mermaid
flowchart TD
    A[Разработчик пушит в ветку] --> B{Какая ветка?}
    B -->|dev| C[Цель: dev]
    B -->|stage| D[Цель: stage]
    B -->|main| E[Цель: prod]

    C --> F[Этап сборки]
    D --> F
    E --> F

    F --> G[docker build с --platform linux/amd64]
    G --> H[Тегирование образа именем окружения]
    H --> I[Отправка в registry.amztop.io]

    I --> J[Этап деплоя]
    J --> K[Контейнер hashicorp/nomad на раннере]
    K --> L["nomad job run по HTTP API"]
    L --> M[Nomad тянет образ и катит канарейку]
    M --> N[Сервис работает с новым образом]

    style A fill:#4a6fa5,stroke:#2d4a7a,color:#fff
    style N fill:#4a9a5c,stroke:#2d7a3a,color:#fff
    style F fill:#c9a24e,stroke:#a68232,color:#fff
    style J fill:#c9a24e,stroke:#a68232,color:#fff

Этап 1: Сборка ​

Этап сборки запускается при каждом пуше в dev, stage или main. Каждый сервис в репозитории получает собственную параллельную задачу сборки. Все задачи идут на раннере new-server-builder — по тегу new-server.

Что происходит ​

  1. Раннер запускает контейнер docker:24 с Docker-in-Docker (docker:24-dind) в качестве вспомогательного сервиса.
  2. Авторизация в registry штатной учёткой джобы:
    bash
    docker login registry.amztop.io -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD
  3. Переход в каталог сервиса ($SERVICE_DIR).
  4. Определение тега по ветке: main → prod, stage → stage, dev → dev.
  5. Сборка образа с фиксацией платформы linux/amd64:
    bash
    docker build ${BUILD_ARGS} \
      --platform linux/amd64 \
      -t registry.amztop.io/integrations/hub/backend:dev .
  6. Отправка образа в registry. Если у проекта не выставлен DUAL_PUSH: "false", следом уходит копия в старый registry.

Кеш базовых образов

На раннере поднят pull-through кеш Docker Hub, поэтому повторные сборки не упираются в лимиты Hub и тянут базовые слои локально.

Параллельные сборки ​

Когда репозиторий содержит несколько сервисов (например, Hub включает backend и frontend), задачи сборки выполняются параллельно:

mermaid
gantt
    title Выполнение этапа сборки
    dateFormat X
    axisFormat %s

    section Сборка
    build:backend   :0, 90
    build:frontend  :0, 70

    section Деплой
    deploy (ожидает все сборки) :90, 30

Этап деплоя не начинается, пока все задачи сборки не завершатся успешно. Если любая сборка падает, пайплайн останавливается.

Ошибки сборки

Неудачная сборка полностью блокирует деплой. Типичные причины сбоев:

  • Синтаксические ошибки в Dockerfile
  • Отсутствующие зависимости сборки
  • BUILD_ARGS ссылаются на неопределённые ARG в Dockerfile
  • Сетевые проблемы при загрузке базовых образов

Проверьте логи CI-задачи, чтобы увидеть конкретную ошибку docker build.

Этап 2: Деплой ​

После успешного завершения всех сборок запускается задача деплоя для соответствующего окружения.

Что происходит ​

  1. Запускается контейнер hashicorp/nomad:1.11.3 — в нём уже есть нужный CLI.
  2. Выставляются адрес и токен кластера из переменных группы:
    bash
    export NOMAD_ADDR=$NEW_NOMAD_ADDR
    export NOMAD_TOKEN=$NEW_NOMAD_TOKEN
  3. Джоба отправляется в нужный namespace прямо из репозитория — файлы никуда не копируются:
    bash
    nomad job run -namespace=dev \
      -var image_tag=dev \
      -var deploy_ts=$CI_PIPELINE_ID \
      -var-file=nomad/vars-dev.hcl nomad/hub.nomad.hcl
  4. Nomad планирует аллокацию на ноду своего окружения — за это отвечает constraint по meta.env внутри джобы.
  5. Нода тянет образ из registry и поднимает канареечную копию рядом со старой.
  6. После успешных health-чеков трафик переключается, старая копия гасится.

Диаграмма последовательности деплоя ​

mermaid
sequenceDiagram
    participant GL as GitLab Runner
    participant NM as Nomad API
    participant ND as Нода окружения
    participant REG as registry.amztop.io

    GL->>NM: nomad job run (namespace, image_tag, deploy_ts)
    NM->>NM: Планирование аллокации по meta.env
    NM->>ND: Разместить задачу
    ND->>REG: Pull образа :dev
    REG-->>ND: Слои образа
    ND->>ND: Старт канареечной копии
    ND-->>NM: Health-чеки зелёные
    NM->>ND: Промоут канарейки, стоп старой
    NM-->>GL: Exit 0 (success)

Соответствие веток и окружений ​

Весь пайплайн управляется тем, в какую ветку выполнен пуш:

ВеткаТег сборкиЦель деплояNamespaceNomad var-файл
dev:devdev-окружениеdevnomad/vars-dev.hcl
stage:stagestage-окружениеstagenomad/vars-stage.hcl
main:prodprod-окружениеprodnomad/vars-prod.hcl

Feature-ветки

Пуши в ветки, отличные от dev, stage или main, не запускают никаких задач пайплайна. Чтобы протестировать feature-ветку в CI, сначала влейте её в dev.

Прод — по кнопке

Задача deploy:prod описывается с when: manual. Пуш в main собирает образ :prod, но выкатку запускает человек нажатием в пайплайне.

Полный пример пайплайна ​

Как выглядит полный пайплайн для сервиса Hub при пуше в ветку dev:

yaml
# Triggered by: git push origin dev

# Job 1: build:backend
# - extends: .docker_build, tags: [new-server]
# - Builds back/Dockerfile
# - Pushes: registry.amztop.io/integrations/hub/backend:dev

# Job 2: build:frontend (runs in parallel with Job 1)
# - extends: .docker_build, tags: [new-server]
# - Builds front/Dockerfile with --build-arg VITE_API_URL=...
# - Pushes: registry.amztop.io/integrations/hub/frontend:dev

# Job 3: deploy:dev (runs after Jobs 1 & 2 succeed)
# - extends: .nomad_new, tags: [new-server]
# - Runs: nomad job run -namespace=dev -var image_tag=dev
#         -var deploy_ts=$CI_PIPELINE_ID
#         -var-file=nomad/vars-dev.hcl nomad/hub.nomad.hcl

Временная шкала ​

mermaid
flowchart LR
    A["git push origin dev"] --> B["build:backend<br/>(~90 сек)"]
    A --> C["build:frontend<br/>(~70 сек)"]
    B --> D["deploy:dev<br/>(~30 сек)"]
    C --> D
    D --> E["Сервис доступен на dev"]

    style A fill:#4a6fa5,stroke:#2d4a7a,color:#fff
    style E fill:#4a9a5c,stroke:#2d7a3a,color:#fff

Типичное общее время пайплайна: 2--3 минуты от пуша до работающего сервиса.

Решение проблем ​

Ошибки на этапе сборки ​

Образ не собирается

Проверьте вывод docker build в логах CI-задачи. Типичные причины:

  • Базовый образ не найден (сетевая проблема или неверный тег)
  • COPY ссылается на файлы, исключённые .dockerignore
  • Аргумент сборки требуется, но не передан через BUILD_ARGS
Отправка в registry не удалась

Проверьте, что в проекте заданы REGISTRY_HOST: registry.amztop.io и REGISTRY_IMAGE: $REGISTRY_HOST/$CI_PROJECT_PATH. Если push падает с denied, а pull работает — дело в скоупе токена: у deploy-токена должна стоять галка write_registry, а не только read_registry.

Задача ушла не на тот раннер

Если в логе видно, что джобу подобрал раннер старого сервера — забыт тег new-server. Он нужен и сборке, и деплою.

Ошибки на этапе деплоя ​

Пустой NOMAD_ADDR или 403 от API

Скорее всего у переменных NEW_NOMAD_ADDR / NEW_NOMAD_TOKEN стоит галка Protect, а ветка не защищена. Снимите галку — на группе integrations они заведены без неё.

Отправка Nomad-задачи не удалась

Типичные причины:

  • Некорректный HCL-синтаксис в nomad/<job>.nomad.hcl
  • В var-файле отсутствует обязательная переменная
  • Джоба отправлена в namespace, которого нет

Проверьте локально под VPN, до пуша:

bash
export NOMAD_ADDR=http://192.168.100.1:4646
export NOMAD_TOKEN=<ваш токен>

nomad job validate -var image_tag=dev -var deploy_ts=1 \
  -var-file=nomad/vars-dev.hcl nomad/hub.nomad.hcl
Пайплайн зелёный, но версия старая

Повторный запуск задачи в том же пайплайне отдаёт прежний deploy_ts, и Nomad не считает это новой выкаткой. Запустите новый пайплайн.

Ошибки загрузки образа во время выполнения

Если Nomad принял задачу, но аллокация упала, наиболее вероятная причина — ошибка загрузки образа. Проверьте:

  1. Тег образа существует в registry
  2. Нода может достучаться до registry.amztop.io
  3. Учётные данные Docker на ноде не истекли

Docker на ноде хранит одну учётку на registry — сейчас это deploy-токен группы integrations. Проект из другой группы потребует обновления логина на нодах.

bash
# На ноде окружения:
docker pull registry.amztop.io/integrations/hub/backend:dev

Документация по инфраструктуре