Деплой веб-приложений с помощью Ansistrano

bc49fd9d21d24c83814a517cb24c1543.png

ansistrano.deploy и ansistrano.rollback — роли Ansible, предназначенные для управления процессом развертывания приложений, созданных на скриптовых языках программирования (например, PHP, Python и Ruby). По сути это реализация Capistrano в Ansible.


Использование Ansistrano дает следующие преимущества:


  • откат за секунды (с ролью ansistrano.rollback);
  • настройка процедуры развертывания с использованием методов-обработчиков событий «до» и «после» критически важных шагов;
  • оптимизация использования дискового пространства за счет хранения ограниченного количества релизов;
  • выбор между SCP, RSYNC, GIT, SVN, HTTP Download или S3 GET-стратегиями развертывания (в дополнение возможно использование unarchive).

Как появился Ansistrano


Вначале был Capistrano, который является инструментом автоматизации управления серверами; его текущая версия — под номером 3. Версия 2.0 была создана для развертывания RoR-приложений. С помощью плагинов можно было работать с не-Rails приложениями, написанными, например, на PHP или Python, применяя различные стратегии развертывания, среды тестирования и многое другое. И это было хорошо.


Capistrano 2 — отличный инструмент, который работает до сих пор. Но он больше не поддерживается, поскольку разработчики переключились на третью версию. При этом, по мнению создателей Ansistrano, Capistrano 3 менее гибкий и не такой мощный, а также не обладает тем набором возможностей, который был у предыдущей версии. Кроме того, другие инструменты развертывания приложений (например, Ansible), не стоят на месте и постоянно совершенствуются.


Разработчики Ansistrano объясняют отказ от Capistrano отсутствием поддержки версии 2 и нехваткой функциональности в v3, а также тем, что все необходимые задачи выполнимы и с помощью Ansible. В качестве альтернативы предлагается посмотреть на Fabric и Chef Solo.


Кстати, название проекта — Ansistrano — получилось путем соединения Ansible и Capistrano.


Анонимная статистика использования Ansistrano


Недавно в Ansistrano был добавлен дополнительный необязательный шаг, который дает разработчикам возможность узнать, сколько людей разворачивают приложения с помощью Ansistrano. Поскольку Ansible Galaxy не предоставляет статистику по загрузкам или использованию, авторы Ansistrano утверждают, что это был чуть ли не единственный способ выяснить количество пользователей проекта.


Код по сбору анонимной статистики см. здесь. Кроме того, этот зонд функционал можно отключить, установив в false настройку ansistrano_allow_anonymous_stats во всех плейбуках.


Кто использует Ansistrano?


Готов ли Ansistrano к использованию?


Вот некоторые компании, которые работают с Ansistrano:
  • Atrápalo
  • Another Place Productions
  • Suntransfers
  • Ulabox
  • Euromillions.com
  • Uvinum
  • Cycloid
  • Spotahome
  • Ofertix
  • Nice&Crazy
  • Gstock
  • CMP Group
  • Jolicode
  • Wavecontrol
  • EnAlquiler
  • ABA English
  • Oferplan
  • Yubl
  • Fluxus
  • TechPump
  • Nodo Ámbar
  • Cabissimo
  • UNICEF Comité Español
  • Claranet France
  • OpsWay Software Factory

Установка и обновление


Для развертывания приложений с Ansistrano понадобятся:


  • Ansible на центральной машине;
  • rsync на целевой машине (если используется стратегия развертывания rsync, git или ansistrano_current_via = rsync).

Ansistrano доступен через Ansible Galaxy. Чтобы запустить установку, выполните:


$ ansible-galaxy install carlosbuenosvinos.ansistrano-deploy carlosbuenosvinos.ansistrano-rollback

Чтобы обновить Ansistrano, добавьте параметр --force:


$ ansible-galaxy install --force carlosbuenosvinos.ansistrano-deploy carlosbuenosvinos.ansistrano-rollback

Основная схема работы


Развертывание приложений с Ansistrano выполняется по той же схеме, что и в Capistrano.


  • Настройка (Setup): создается структура каталогов для хранения релизов.
  • Обновление кода (Code update): загрузка релиза на целевые машины.
  • Обновление ссылок (Symlink): после развертывания нового релиза на целевых машинах ссылка current устанавливается на новый релиз.
  • Очистка (Cleanup): с учетом параметра ansistrano_keep_releases удаляются старые версии (см. «Переменные роли»).

1349bc5e5eb745a28888380aaec5713c.png



Переменные роли


Далее для справки приведен список переменных Ansistrano.


Список переменных роли
- vars:
  ansistrano_deploy_from: "{{ playbook_dir }}" # Расположение проекта (относительный или абсолютный путь).
  ansistrano_deploy_to: "/var/www/my-app" # Путь для развертывания.
  ansistrano_version_dir: "releases" # Имя каталога с релизами.
  ansistrano_current_dir: "current" # Имя ссылки на текущий релиз, меняется редко.
  ansistrano_current_via: "symlink" # Стратегия развертывания в каталог "current". Варианты: "symlink" или "rsync".
  ansistrano_shared_paths: [] # Общие пути для ссылки на каталог с релизом.
  ansistrano_shared_files: [] # Общие файлы для ссылки на каталог с релизом.
  ansistrano_keep_releases: 0 # Релизы, которые необходимо сохранить. См. «Удаление старых релизов».
  ansistrano_deploy_via: "rsync" # Метод доставки кода на сервер. Варианты: "copy", "rsync", "git", "svn", "s3" или "download". Для "copy", "download" и "s3" есть возможность распаковать (unarchive) загруженный файл (нужно добавить "_unarchive"). Полный список опций можно найти в каталоге *tasks/update-code*.
  ansistrano_allow_anonymous_stats: yes

  # Переменные, используемые при стратегии развертывания "rsync" 
  ansistrano_rsync_extra_params: "" # Дополнительные параметры, которые будут использованы при развертывании с помощью rsync одной строкой. Хотя Ansible позволяет использовать массивы, могут быть проблемы при попытке добавления нескольких аргументов "--include". См. соответствующий отчет по ссылке https://github.com/ansistrano/deploy/commit/e98942dc969d4e620313f00f003a7ea2eab67e86
  ansistrano_rsync_set_remote_user: yes # См. [ansible synchronize module](http://docs.ansible.com/ansible/synchronize_module.html). Варианты: "yes", "no".

  # Переменные, используемые при стратегии развертывания Git
  ansistrano_git_repo: git@github.com:USERNAME/REPO.git # Расположение репозитория git.
  ansistrano_git_branch: master # Какую версию репозитория использовать. Это может быть целый 40-символьный хеш SHA-1, литерал HEAD, имя ветки или имя тега (tag name).
  ansistrano_git_repo_tree: "" # Если указано поддерево (subtree) репозитория для развертывания.
  ansistrano_git_identity_key_path: "" # Если указано, то этот файл копируется и используется в качестве идентификационного ключа для команд git, путь указывается относительно плейбука, в котором используется.

  # Переменные, используемые при стратегии развертывания SVN 
  # Обратите внимание: в Ansible 1.8.x была ошибка в модуле subversion (https://github.com/ansible/ansible-modules-core/issues/370), поэтому поддержка этой системы начинается только с Ansible 1.9.
  ansistrano_svn_repo: "https://svn.company.com/project" # Расположение репозитория svn
  ansistrano_svn_branch: "trunk" # Какую ветку репозитория использовать.
  ansistrano_svn_revision: "HEAD" # Какую ревизию репозитория использовать.
  ansistrano_svn_username: "user" # SVN authentication username
  ansistrano_svn_password: "Pa$$word" # SVN authentication password

  # Переменные, используемые при стратегии развертывания download 
  ansistrano_get_url: https://github.com/someproject/somearchive.tar.gz

  # Переменные, используемые при стратегии развертывания S3 
  ansistrano_s3_bucket: s3bucket
  ansistrano_s3_object: s3object.tgz # Добавьте суффикс _unarchive к  ansistrano_deploy_via, если ваш объект является пакетом (например, s3_unarchive)
  ansistrano_s3_region: eu-west-1
  ansistrano_s3_rgw: false # должна быть Ansible >= 2.2, используйте Ceph RGW (когда установлено в "true", игнорируйте ansistrano_s3_region)
  ansistrano_s3_url: http://rgw.example.com # при использовании Ceph RGW установите url
  # Необязательные переменные, не используются по умолчанию
  ansistrano_s3_aws_access_key: YOUR_AWS_ACCESS_KEY
  ansistrano_s3_aws_secret_key: YOUR_AWS_SECRET_KEY

  # Hooks: (добавьте в задачи необходимые обработчики событий)
  ansistrano_before_setup_tasks_file: "{{ playbook_dir }}//my-before-setup-tasks.yml"
  ansistrano_after_setup_tasks_file: "{{ playbook_dir }}//my-after-setup-tasks.yml"
  ansistrano_before_update_code_tasks_file: "{{ playbook_dir }}//my-before-update-code-tasks.yml"
  ansistrano_after_update_code_tasks_file: "{{ playbook_dir }}//my-after-update-code-tasks.yml"
  ansistrano_before_symlink_shared_tasks_file: "{{ playbook_dir }}//my-before-symlink-shared-tasks.yml"
  ansistrano_after_symlink_shared_tasks_file: "{{ playbook_dir }}//my-after-symlink-shared-tasks.yml"
  ansistrano_before_symlink_tasks_file: "{{ playbook_dir }}//my-before-symlink-tasks.yml"
  ansistrano_after_symlink_tasks_file: "{{ playbook_dir }}//my-after-symlink-tasks.yml"
  ansistrano_before_cleanup_tasks_file: "{{ playbook_dir }}//my-before-cleanup-tasks.yml"
  ansistrano_after_cleanup_tasks_file: "{{ playbook_dir }}//my-after-cleanup-tasks.yml"

{{ playbook_dir }} — переменная Ansible, которая хранит путь к текущему плейбуку.


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


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


  • Создайте новый файл hosts. В случае возникновения вопросов смотрите документацию по Ansible Inventory. В этом файле будут указаны целевые машины.
  • Создайте новый плейбук для развертывания приложения (например, deploy.yml).
  • Настройте переменные роли.
  • Включите роль carlosbuenosvinos.ansistrano-deploy в скрипт (play).
  • Запустите плейбук.

ansible-playbook -i hosts deploy.yml

Если все было настроено правильно, эта команда создаст примерно следующую структуру каталогов на сервере. Проверьте, как будет выглядеть каталог hosts после одного, двух и трех развертываний.


-- /var/www/my-app.com
|-- current -> /var/www/my-app.com/releases/20100509145325
|-- releases
|   |-- 20100509145325
|-- shared

-- /var/www/my-app.com
|-- current -> /var/www/my-app.com/releases/20100509150741
|-- releases
|   |-- 20100509150741
|   |-- 20100509145325
|-- shared

-- /var/www/my-app.com
|-- current -> /var/www/my-app.com/releases/20100512131539
|-- releases
|   |-- 20100512131539
|   |-- 20100509150741
|   |-- 20100509145325
|-- shared

Последовательные развертывания

Чтобы предотвратить установку различных временных меток при развертывании на несколько серверов с использованием опции serial, установите переменную ansistrano_release_version.


ansible-playbook -i hosts -e "ansistrano_release_version=`date -u +%Y%m%d%H%M%SZ`" deploy.yml

Откат


Чтобы откатиться с Ansistrano, необходимо настроить развертывание и выполнить плейбук отката.


ansible-playbook -i hosts rollback.yml

При попытке отката с количеством развернутых релизов, равным 1 или 0, система выдаст ошибку; никаких действий при этом выполнено не будет.


В сценарии отката по сравнению с развертыванием гораздо меньше настраиваемых переменных:


- vars:
  ansistrano_deploy_to: "/var/www/my-app" # Путь для развертывания.
  ansistrano_version_dir: "releases" # Имя каталога с релизами.
  ansistrano_current_dir: "current" # Имя ссылки на текущий релиз, меняется редко.

  # Hooks: (добавьте в задачи необходимые обработчики событий)
  ansistrano_before_symlink_tasks_file: "{{ playbook_dir }}//my-before-symlink-tasks.yml"
  ansistrano_after_symlink_tasks_file: "{{ playbook_dir }}//my-after-symlink-tasks.yml"
  ansistrano_before_cleanup_tasks_file: "{{ playbook_dir }}//my-before-cleanup-tasks.yml"
  ansistrano_after_cleanup_tasks_file: "{{ playbook_dir }}//my-after-cleanup-tasks.yml"

Многостадийные среды (multistage environments) (devel, preprod, prod и т. д.)


При развертывании в разные среды (например, devel, preprod и prod) рекомендуется создавать для них разные файлы hosts. Один и тот же плейбук можно запускать для разных hosts-файлов с помощью параметра -i. В каждом из этих файлов допускается указание различающихся данных (имена пользователей, пароли, параметры соединений и т. д.).


ansible-playbook -i hosts_devel deploy.yml
ansible-playbook -i hosts_preprod deploy.yml
ansible-playbook -i hosts_prod deploy.yml

Hooks: пользовательские задачи (custom tasks)


После шага Symlink обычно необходимо перезагрузить сервер, или перед Code update загрузить зависимости, или даже сделать это в production перед Symlink. Итак, для выполнения пользовательских задач необходимы обработчики (hooks), которые Ansistrano выполнит до или после каждого из 3 основных шагов.


-- /my-local-machine/my-app.com
|-- hosts
|-- deploy.yml
|-- my-custom-tasks
|   |-- before-code-update.yml
|   |-- after-code-update.yml
|   |-- before-symlink.yml
|   |-- after-symlink.yml
|   |-- before-cleanup.yml
|   |-- after-cleanup.yml

Например, чтобы перезапустить Apache после шага Symlink, добавим в after-symlink.yml следующие строки:


- name: Restart Apache
  service: name=httpd state=reloaded

Как добавить отправку уведомления о завершении развертывания по почте или очистить кеш? Очень просто! С помощью переменных роли ansistrano_before_*_tasks_file и ansistrano_after_*_tasks_file можно указать файл с пользовательскими задачами для точек «до» и «после» каждого шага.


Переменные в пользовательских задачах


При написании файлов пользовательских задач могут потребоваться некоторые переменные, доступные в Ansistrano:


  • {{ ansistrano_release_path.stdout }}: путь к текущему релизу для развертывания (это, возможно, самая нужная переменная);
  • {{ ansistrano_releases_path.stdout }}: путь к каталогу с релизами;
  • {{ ansistrano_shared_path.stdout }}: путь к общей папке (где могут храниться общие для всех релизов файлы);
  • {{ ansistrano_release_version }}: относительное имя каталога с релизом (по умолчанию равно текущей временной метке (timestamp) в зоне UTC).

Удаление старых релизов


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


Чтобы удалить старые релизы после развертывания, запишите в переменную ansistrano_keep_releases количество, которое необходимо сохранить.


Давайте посмотрим, как будет вести себя Ansistrano при развертывании трех релизов и ansistrano_keep_releases: 2:


-- /var/www/my-app.com
|-- current -> /var/www/my-app.com/releases/20100509145325
|-- releases
|   |-- 20100509145325
|-- shared

-- /var/www/my-app.com
|-- current -> /var/www/my-app.com/releases/20100509150741
|-- releases
|   |-- 20100509150741
|   |-- 20100509145325
|-- shared

-- /var/www/my-app.com
|-- current -> /var/www/my-app.com/releases/20100512131539
|-- releases
|   |-- 20100512131539
|   |-- 20100509150741
|-- shared

Заметьте, что релиз 20100509145325 был удален.


Пример плейбука


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


Чтобы его запустить, понадобятся Vagrant и роли Ansistrano. Для получения информации по работе с Vagrant см. https://www.vagrantup.com.


$ cd example/my-playbook
$ vagrant up
$ ansible-playbook -i hosts deploy.yml

После выполнения этих команд файл index.html, расположенный в каталоге my-app, будет развернут на обе машины, созданные с помощью Vagrant.


Для тестирования отката нужно запустить deploy.yml как минимум дважды (чтобы было к чему откатываться). После этого выполните:


$ ansible-playbook -i hosts rollback.yml

В папке test есть более сложные примеры, которые используют Travis-CI.

Комментарии (0)

© Habrahabr.ru