Статьи

Непрерывное развертывание: реализация с помощью Ansible и Docker

Эта статья является частью серии « Непрерывная интеграция, доставка и развертывание ».

В предыдущей статье описано несколько способов реализации непрерывного развертывания . В частности, он описал, среди прочего, как реализовать его с помощью Docker для развертывания приложений в качестве контейнеров и nginx для обратного прокси-сервера, необходимого для успешного использования сине-зеленой техники развертывания . Все это работало поверх CoreOS , операционной системы, специально разработанной для запуска контейнеров Docker.

В этой статье мы попытаемся выполнить тот же процесс, используя Ansible (платформа с открытым исходным кодом для настройки и управления компьютерами). Вместо CoreOS мы будем использовать Ubuntu .

Исходный код, используемый в этой статье, можно найти в GitHub repo vfarcic / provisioning (каталог ansible).

анзибль

ansiblelogo_transparent_web Ansible — это программная платформа с открытым исходным кодом для настройки и управления компьютерами. Он сочетает в себе многоузловое развертывание программного обеспечения, выполнение специальных задач и управление конфигурацией. Он управляет узлами по SSH. Модули работают над JSON и стандартным выводом и могут быть написаны на любом языке программирования. Система использует YAML для выражения многократно используемых описаний систем.

Предпочтительный способ работы с Ansible — это роли. Они описывают набор задач, которые необходимо выполнить, чтобы что-то настроить. В нашем случае у нас будет 5 ролей, описанных в bdd.yml .

Первые четыре роли (etcd, confd, docker и nginx) обеспечат наличие инструментов, необходимых для сине-зеленого развертывания. Например, роль Docker определяется следующим образом:

Он устанавливает Docker, используя apt-get, Python PIP и Docker-py. Нам нужен Docker для управления нашими контейнерами. Docker-py — это библиотека Python, необходимая для модуля Ansible Docker, который мы будем использовать для запуска контейнера nginx.

Как видите, Ansible очень прост в использовании и понимании. Просто читая YML-файлы, можно легко увидеть, что происходит. Простота является одним из основных преимуществ, которые она имеет перед аналогичными инструментами, как Puppet и Chef. После очень короткого знакомства с Ansible все, что нам нужно сделать, — это найти модуль, который выполняет задачи, которые нам нужны (т.е. пригодные для установки пакетов Debian), и описать его как задачу YML.

развертывание

После того, как мы установили инструменты, пришло время взглянуть на последнюю роль Ansible bdd . Это где развертывание происходит. Однако, прежде чем мы продолжим, позвольте мне объяснить цели, которые я имел в виду, прежде чем я начал работать над этим.

Развертывание должно следовать сине-зеленой технике. Пока приложение работает, мы будем развертывать новую версию параллельно со старой. Контейнер, который будет использоваться, уже прошел всевозможные модульные и функциональные тесты, что дает нам разумную уверенность в том, что каждый выпуск работает правильно. Однако нам все еще нужно протестировать его после развертывания, чтобы окончательно убедиться, что то, что мы развернули, работает правильно. После того, как все тесты после развертывания пройдены, мы готовы сделать новую версию общедоступной. Мы можем сделать это, изменив обратный прокси-сервер nginx, чтобы перенаправить все запросы во вновь развернутый выпуск. Другими словами, мы должны сделать следующее.

  • Вытащите последнюю версию контейнера приложения
  • Запустите последнюю версию приложения, не останавливая существующую
  • Запустите тесты после развертывания
  • Сообщите etcd о новой версии (порт, имя и т. Д.)
  • Измените конфигурацию nginx, чтобы она указала на новый выпуск
  • Остановить старый релиз

Если мы сделаем все вышеперечисленное, мы должны достичь нулевого времени простоя. В любой момент наше приложение должно быть доступно.

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

Роль Bdd заключается в следующем.

Первая задача — убедиться, что ресурс шаблона bdd.toml присутствует. Он используется confd для указания шаблона, назначения и команды, которую следует выполнить (в нашем случае перезапуск контейнера nginx).

Второе задание обеспечивает наличие шаблона confd (bdd.conf.tmpl) [https://github.com/vfarcic/provisioning/blob/master/ansible/roles/bdd/files/bdd.conf.tmpl]. Этот шаблон вместе с bdd.toml изменяет прокси-сервер nginx, чтобы указывать на новый выпуск каждый раз, когда мы его развертываем. Таким образом, у нас не будет никаких помех нашему сервису.

Третья задача гарантирует, что сценарий развертывания deploy-bdd.sh присутствует и последний из которых он запущен.

С точки зрения Ansible, это все, что есть. Настоящая «магия» заключается в самом сценарии развертывания. Давайте пройдем через это.

Мы начнем с выяснения, следует ли нам выполнять развертывание в синем или зеленом цвете Если текущий синий, мы развернем зеленый и наоборот. Информация о развернутом в данный момент «цвете» хранится в файле etcd key / bdd / color.

01
02
03
04
05
06
07
08
09
10
11
12
13
BLUE_PORT=9001
GREEN_PORT=9002
CURRENT_COLOR=$(etcdctl get /bdd/color)
if [ "$CURRENT_COLOR" = "" ]; then
  CURRENT_COLOR="green"
fi
if [ "$CURRENT_COLOR" = "blue" ]; then
  PORT=$GREEN_PORT
  COLOR="green"
else
  PORT=$BLUE_PORT
  COLOR="blue"
fi

Как только решение принято, мы останавливаем и удаляем существующие контейнеры, если они есть. Имейте в виду, что текущая версия будет продолжать работать и не будет затронута до самого конца.

1
2
docker stop bdd-$COLOR
docker rm bdd-$COLOR

Теперь мы можем запустить контейнер с новым выпуском и запустить его параллельно с существующим. В данном конкретном случае мы развертываем контейнер BDD Assistant vfarcic / bdd .

1
2
docker pull vfarcic/bdd
docker run -d --name bdd-$COLOR -p $PORT:9000 vfarcic/bdd

Как только новая версия будет запущена, мы сможем запустить окончательный набор тестов. Это предполагает, что все тесты, которые не требуют развертывания, уже выполнены. В случае BDD Assistant модульные (Scala и JavaScript) и функциональные тесты ( сценарии BDD ) выполняются как часть процесса сборки контейнера, описанного в Dockerfile . Другими словами, контейнер отправляется в хранилище, только если все тесты, которые выполняются как часть процесса сборки, пройдены. Однако тестов, выполняемых до развертывания, обычно недостаточно. Мы должны убедиться, что развернутое приложение работает должным образом. На этом этапе мы обычно проводим интеграционные и стресс-тесты. Сами тесты также являются контейнером, который запускается и автоматически удаляется (аргументы -rm) после его завершения. Важно отметить, что по умолчанию localhost на хосте доступен через 172.17.42.1 из контейнера.

В этом конкретном случае набор сценариев BDD запускается с использованием браузера без поддержки PhantomJS.

1
2
3
4
5
docker pull vfarcic/bdd-runner-phantomjs
docker run -t --rm --name bdd-runner-phantomjs vfarcic/bdd-runner-phantomjs
  --story_path data/stories/tcbdd/stories/storyEditorForm.story
  --composites_path /opt/bdd/composites/TcBddComposites.groovy
  -P url=http://172.17.42.1:$PORT -P widthHeight=1024,768

Если все тесты пройдены, мы должны сохранить информацию о новом выпуске с помощью etcd и запустить confd, который обновит нашу конфигурацию nginx. До этого момента nginx перенаправлял все запросы на старый выпуск. Если пока что ничего не получилось в процессе, только с этого момента пользователи приложения будут перенаправлены на версию, которую мы только что развернули.

1
2
3
4
5
etcdctl set /bdd/color $COLOR
etcdctl set /bdd/port $PORT
etcdctl set /bdd/$COLOR/port $PORT
etcdctl set /bdd/$COLOR/status running
confd -onetime -backend etcd -node 127.0.0.1:4001

Наконец, поскольку мы выпустили, протестировали и сделали новую версию доступной для широкой публики через обратный прокси-сервер nginx, мы готовы остановить и удалить старую версию.

1
2
docker stop bdd-$CURRENT_COLOR
etcdctl set /bdd/$CURRENT_COLOR/status stopped

Исходный код сценария deploy-bdd.sh можно найти в репозитории GitHub vfarcic / provisioning .

Запуск всего этого вместе

Давайте посмотрим на это в действии. Я подготовил Vagrantfile, который создаст виртуальную машину Ubuntu и запустит Ansible playbook, который установит и настроит все и, наконец, развернет приложение. Предполагая, что Git , Vagrant и VirtualBox установлены, выполните следующее.

1
2
3
git clone https://github.com/vfarcic/provisioning.git
cd provisioning/ansible
vagrant up

Первый запуск может занять некоторое время, так как Vagrant и Ansible нужно будет загрузить много вещей (ОС, пакеты, контейнеры …). Пожалуйста, будьте терпеливы, особенно на медленной полосе пропускания. Хорошей новостью является то, что каждый последующий пробег будет намного быстрее.

Чтобы смоделировать развертывание новой версии, выполните следующее.

1
vagrant provision

Если вы подключитесь к виртуальной машине по протоколу SSH, вы увидите, что текущая версия меняется с синего (порт 9001) на зеленый (порт 9002) и наоборот при каждом запуске vagrant provision.

1
2
vagrant ssh
sudo docker ps

До, во время и после развертывания приложение будет доступно без перерыва (без простоев). Вы можете проверить это, открыв http: // localhost: 8000 / в вашем любимом браузере.

Резюме

Как вы могли видеть, развертывание значительно упрощается благодаря Docker и контейнерам. В то время как в более традиционной настройке Ansible должен был бы установить кучу вещей (JDK, веб-сервер и т. Д.) И убедиться, что постоянно увеличивается количество файлов конфигурации, с контейнерами главная роль Ansible состоит в том, чтобы убедитесь, что ОС настроена, Docker установлен и что некоторые другие вещи установлены правильно. Другими словами, Ansible продолжает быть полезным, в то время как важная часть его работы значительно упрощается благодаря контейнерам и концепции неизменяемых развертываний (то, что мы развертываем, неизменяемо). Мы не обновляем наши приложения новыми версиями. Вместо этого мы разворачиваем совершенно новые контейнеры и удаляем старые.

Весь код, используемый в этой статье, можно найти в каталоге ansible внутри GitHub repo vfarcic / provisioning .

В следующих статьях будет рассказано, как выполнить ту же процедуру с другими инструментами обеспечения. Мы будем исследовать шеф-повара, кукол и соль. Наконец, мы попробуем сравнить все четыре из них. Будьте на связи!