CD проекта, как реализовать?

Всем привет, никогда не настраивал выкладку своего проекта автоматически, поэтому прошу помочь с организацией всего этого.

Имеется проект, в стиле микро сервисной архитектуры с использованием docker-compose, все хранится на GitLab, репозитории имеют следующий вид:

  • ServiceA - сервис A, хранит в себе исходный код + Dockerfile
  • ServiceB - сервис B, хранит в себе исходный код + Dockerfile
  • ServiceC - сервис C, хранит в себе исходный код + Dockerfile
  • Application - Перечисляет в себе сервисы (ServiceA...C), посредством git submodules + docker-compose.yml;

В docker-compose декларированы все сервисы из репозиториев (Помимо своих "модулей", перечислен docker-сервис из готового образа) и поэтому для запуска приложения достаточно, просто выполнить docker-compose up -d --build

Существуют 2 среды:

  • Staging - среда-приемки, тестовая, нет доступа по ssh
  • Production - прод, есть доступ по ssh (лучше конечно не трогать ssh)

Хочется сделать следующие:

  1. Когда я обновляю master - ветку, репозитория Application, обновление автоматически доставляется на Staging-среду и приложение обновляется.
  2. Когда все было успешно протестировано на Staging-среде, можно было нажать на кнопочку (Подтвердить выкладку) и изменения доставлялись на Production-среду (Процесс аналогичному на Staging-среде).

Теперь собственно сам вопрос :)

Каким образом можно организовать данный процесс? Возможно по неопытности, я пропустил какие-то процессы, но которые должны быть.


Ответы (1 шт):

Автор решения: AfsmNGhr

Имеется проект, в стиле микро сервисной архитектуры с использованием docker-compose, все хранится на GitLab, репозитории имеют следующий вид:

Service A - сервис A, хранит в себе исходный код + Dockerfile

Во-первых, желательно, чтобы микросервиcы можно было деплоить отдельно. В текущем описании конфигурация только в Application stack, а это не гибко. Если Service A меняется, нужно менять Application.

Решение:

  • своё описание инфраструктуры docker-compose.*.yml (в том числе и docker-compose.development.yml, пользуемся docker-compose.override.yml, делая ссылку)
  • описание environment docker-compose file (прямо в репозитории сервиса)
  • свои тесты, build & push в docker registry или через Application (.gitlab-ci.yml)
  • уменьшаем связность сервисов
  • коммуникация через external network

нет доступа по ssh
есть доступ по ssh (лучше конечно не трогать ssh)

SSH вполне себе вариант для деплоя. Главное не руками через ssh.

Application stack

Описываем в .gitlab-ci.yml qa, integration tests, деплои как staging / production. Тут же можно положить скрипты для автоматизации деплоя.

Разберем на примере. Некий аналог Application моей реализации CD. Смотри services/example (аналог Service A)

Для автоматизации используется bash + ansible.

Ansible:

  • Конфигурации серверов по environment и секреты (минимально шифруем host_vars.yml)
  • деплой через ssh (передаем файл stack, после удаляем)

Bash:

  • Проверки services, environments
  • Merge docker-compose.*.yml в один стек (build / deploy)

Как выглядит:

./build example staging

Билдим сервис example и заливаем в registry. Помним, что в этот момент нужны sources.

Аналогично деплой.

./deploy example staging

Под капотом у нас ansible и ему скармливаем пароль от vault для secrets. Можно использовать как group_vars, так и host_vars.

docker-compose.yml приводим к одному виду с ansible vars и уже через ansible контролируем переменные (кроме development).

Пример c gitlab

image: afsmnghr/ansible-gitlab-runner:1.2.1

variables:
  ...

stages:
  - integration
  - production

.ssh: &ssh |
  eval "$(ssh-agent -s)"
  echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null
  mkdir -p ~/.ssh
  ssh-keyscan "$PROD_IP" >> ~/.ssh/known_hosts

.ansible: &ansible |
  # WARNING: Ansible refuses to read from a world-writeable folder
  chmod -v 600 "$(pwd)"
  echo "$ANSIBLE_VAULT_PASSWORD" > .vault

build:
  stage: integration
  before_script:
    - *ssh
    - *ansible
  script:
    - ./build example production
  after_script:
    - rm -f .vault
  only:
    - tags
  except:
    refs:
      - schedules
      - branches
      - develop

deploy:
  stage: production
  before_script:
    - *ssh
    - *ansible
  script:
    - ./deploy example production
  after_script:
    - rm -f .vault
  only:
    - tags
  except:
    refs:
      - schedules
      - branches
      - develop

Пушим тег в master (настраиваем политики). Начинает билд и деплой на прод. Все легко реализовать, если базовые вещи можно описать простыми командами.

Вместо заключения

Основные проблемы и что может помочь:

  • Автоматизация (ansible playbooks / roles)
  • Secret management (ansible vault, hashicorp vault)
  • Infra / servers inventory (ansible)
  • IaC на каждый environment (много docker-compose файлов)
→ Ссылка