» » » Как мы настраивали процесс CI/CD для наших SOA-проектов

 

Как мы настраивали процесс CI/CD для наших SOA-проектов

Автор: admin от 14-11-2017, 12:20, посмотрело: 38

Как мы настраивали процесс CI/CD для наших SOA-проектов
Хотел бы поделиться опытом настройки CI/CD в нашей компании, плюс, послушать советы, если у вас похожая структура проектов.



Кому, как мне кажется, данная статья может оказаться полезной:




  • ваши проекты содержат несколько отдельных репозиториев с приложениями;

  • вы хотите быть уверены, что каждый репозиторий проходит тесты;

  • вы хотите быть уверены в совместимости версий между репозиториями;

  • вы ещё не успели, но планируете, перевести свои проекты на докер;

  • хотите посмотреть пару playbook'ов Ansible.

«Continuous Delivery Using Docker And Ansible». Мы оттакливались от него при разработке нашего решения.



Задачи для CI/CD



Один наш проект в среднем — это 4-5 репозиториев, взаимодействующих между собой по rest-api. Считается ли это микросервисной архитектурой или нет, не знаю точно, но, учитывая это, перед CI/CD мы ставили следующие задачи:




  • в каждом репозитории в каждой из основных веток должен быть рабочий (протестированный) код;

  • каждая эта ветка, плюс каждый тэг, должны быть полностью консистены между всеми репозиториями в проекте;

  • должна быть возможность развернуть проект локально, как полноценно, так и отдельно любой репозиторий, для разработки;

  • должна быть возможность развернуть проект на разных окружениях: testing, staging, production.



Итак, приступим.



Настройка CI/CD



Предварительный шаг




  • мы перешли на git-flow. Оказалось, что наша кастомная vcs-workflow, по-сравнению с «классикой», избыточна и сложна, особенно для новичков;

  • наш недельный спринт — это новая версия продукта. Каждая задача, будь то баг или фича, в таск-менеджере прикрепляется к конкретной версии. У каждого репозитория в конце спринта появляется тэг с новой версией, даже если именно в данной репе для данной версии ничего и не делали. Исключение, если ни один репозиторий из проекта за спринт не трогали;

  • запретили напрямую пушить в ветки master, develop и release, только через пул-реквесты;

  • повесили хук на пул-реквесты в вышеуказанные ветки для сборки и тестирования в Jenkins;

  • запретили слияние пул-реквестов без удачного тестирования Jenkins'ом и без одобрения Code Review.



В качестве CI инструмента мы выбрали Jenkins, который запускает юнит тесты и интеграционные тесты api.



В качестве CD инструментов — Ansible + Docker.



Первый шаг, настройка отдельного репозитория



Мы изменили структуру каждого нашего репозитория внутри проекта:



app
  |-src
  |-docker
  |   |-ci
  |   |-develop
  |   |-release
  |-requirements
  |-Jenkinsfile
  |-Makefile


Настроенный хук на пул-реквесте скажет Jenkins'у, что репозиторий необходимо протестировать. Jenkins будет искать и исполнять Jenkinsfile. Последний последовательно вызывает команды Makefile для сборки контейнера и тестирования. Makefile запускает команды docker-compose из каталога ./docker/ci. Почему мы не настроили запуск команд docker-compose сразу из Jenkinsfile? Чтобы сохранить его универсальность для всех репозиториев. Т.е. разным репозиториям для сборки и запуска требуются разные команды docker-compose, и эти различия настроены в Makefile, который для Jenkinsfile всегда имеет одинаковый интерфейс сборки и запуска.



NB. В конце статьи находятся ссылки на репозитории с примерами.



Также в Makefile находятся команды по сборке и запуску репозитория локально в develop-режиме — настроен проброс с исходниками с хостовой машины внутрь докера, и достаточно будет только перезапустить docker-compose, что тоже сделано через make-команду, чтобы увидеть новые изменения. За это отвечает Makefile + ./docker/develop.



В ./docker/release находятся настройки сборки репозитория для среды testing/staging и пр. Они, настройки, будут использоваться позже.



Второй шаг. Настройка дополнительного devops-репозитория



Назначение общего репозитория — сохранение целостности проекта при разворачивании репозиториев, которые в него входят, а также в возможности интеграционного тестирования.



Структура репозитория



devops
  |-ansible
  |   |-plays
  |   |-roles
  |-projects
  |   |-project_1
  |   |   |-apps
  |   |   |   |-app_1
  |   |   |   |-app_2
  |   |   |   |-app_3
  |   |   |   |-...
  |   |   |-docker
  |   |   |   |-ci-api
  |   |   |   |-ci-selenium-gherkin
  |   |   |   |-develop
  |   |   |   |-testing
  |   |   |   |-staging
  |   |   |   |-production
  |   |   |-Makefile
  |-requirements
  |-Jenkinsfile
  |-Makefile


Сперва о том, как этот репозиторий выполняет интеграционное тестирование.

Не самое простое дело, попробую объяснить.

Как и в случае репозитория с приложением, здесь есть файлы Jenkinsfile и Makefile, которые при пул-реквесте запустят команды сборки и тестирования. Настройки сборки располагаются в ./projects/PROJECT/docker/ci-api, где «PROJECT» — название текущего проекта. Сборка включает в себя клонирование каждого репозитория в нужной ветке/тэге, запуск контейнера-тестировщика api.



«Нужная ветка/тэг» — это то, что мы пытается протестировать — либо общая ветка (master, develop, release) для всех репозиториев, либо тэг-версия проекта. Тэг необходимо проставить в каждом репозитории. Затем создать ветку в devops-репозитории с названием, совпадающим с «нужным». После этого можно делать пул-реквест.



Jenkins попытается собрать проект по выбранному тэгу/ветке, если в каком-то репозитории не найдётся такого — тестирование провалено. Если собрать проект удалось, то запустится «тестовый фреймворк», в качестве которого мы используем Postman и его утилиту для командной строки — Newman. Если тесты прошли успешно — на выходе мы сливаем пул-реквест и проставляем тестируемый тэг в devops-репозиторий. Наличие этого тэга говорит, что эта версия проекта протестирована.



Для запуска тестов Постмана, нам требуется ссылка расшаренной коллекции, которую вставляем в command контейнера.



Пока это единственный вид интеграционного тестирования, чуть позже мы добавим тестирование с помощью gherkin'a или selenium'a, по крайней мере, каталог docker/ci-selenium-gherkin уже есть.



Теперь про функции CD в данном репозитории.

Здесь, в ./ansible, находится пульт управления всем проектом по сборке образов и их доставке на разные сервера и окружения, а именно:




  • develop.yml — настройки по разворачиванию всего проекта локально;

  • make-images.yml — создание docker-образов с определённой версией проекта и пуш в докер-registry;

  • deploy-and-run-images.yml — разворачивание проекта на серверах с разным окружением.



В начале каждого пункта указан playbook, который выполняет данный сценарий.



Запускаются они командой:



$ ansible-playbook -i ../testing.ini make-images.yml -e 'project=todo ver=2017.1'
где
- -i ../testing.ini -- файл inventory, в котором указан сервер для данного окружения, куда впоследствии надо будет сделать доставку проекта
- make-images-yml -- playbook
- -e 'project=todo ver=2017.1' -- дополнительные параметры, которые ожидает playbook, в данном случае указывается проект и тэг.


В ./ansible/plays/group_vars/all.yml находятся настройки проекта:


  • какие репозитории относятся к данному проекту;

  • какой docker-registry использовать, какие логин-пароль к нему;

  • индивидуальные настройки для каждого окружения и пр.



Как вы могли заметить, хотя данный репозиторий полностью посвящён только одному проекту, всё равно мы передаём название проекта в параметры playbook'а, а также каталог проекта находится в каталоге projects. Это из-за того, что данный devops-репозиторий — это форк от master-devops-репозитория, от которого точно также форкнуты devops-репозитории других проектов. И подобная структура позволяет обмениваться кодом общих настроек и ansible команд между мастером-форками и между самим форками без угрозы что-то сломать. Точнее, каталог ansible — общий, и его рефакторинг легко можно переносить из мастера в форк и наоборот. А все частные проектные настройки находятся в своём отдельном каталоге в projects. И пул из мастера, либо из соседнего devops-репозитория — не будет конфликтовать с текущим.



Возвращаемся к каталогу docker/release в приложениях, в котором находится Dockerfile, отвечающий за сборку для окружения testing/staging и production, т.е. за всё, кроме develop. Сама по себе релизная сборка одного репозитория ничего полезного не даёт, только в совокупности с остальными репозиториями проекта. Ansible настроен таким образом, что для develop-сборки он возьмёт Dockerfile из каталога docker/develop каждого проекта, а для сборки под релизное окружение — из каталога docker/release.



Итого, у нас получилось сделать:




  • возможность клонирования любого репозитория и запустить develop-версию

  • каждый репозиторий проверяется Jenkins'ом;

  • есть общий репозиторий, которая запускает интеграционные тесты по всем репозиториям по общей версии;

  • ansible playbook: разворачивает локально и запускает все репозитории проекта в develop-режиме;

  • ansible playbook: собирает образы в зависимости от выбранной схемы окружения и отправляет в докер-registry;

  • ansible playbook: на сервере настраивает проект;

  • ansible playbook: на сервере запускает приложение.



Ссылки на приложения для демонстрации системы:




  • todo_todo — форк с проекта todobackend.com. Изменил структуру и добавил тесты. Создаёт todo'шк;

  • todo_crm — создаёт пользователей, отправляет запрос в todo_todo, создаёт todo и привязывает его к пользователю;

  • todo_ops — devops-репозиторий с конфигами



Источник: Хабрахабр

Категория: Программирование » Веб-разработка

Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Добавление комментария

Имя:*
E-Mail:
Комментарий:
Полужирный Наклонный текст Подчеркнутый текст Зачеркнутый текст | Выравнивание по левому краю По центру Выравнивание по правому краю | Вставка смайликов Выбор цвета | Скрытый текст Вставка цитаты Преобразовать выбранный текст из транслитерации в кириллицу Вставка спойлера
Введите два слова, показанных на изображении: *