Vagrant и chef-solo

vagrant_header_background-482a12a7

Vagrant — это такой теоретический способ упростить жизнь разработчикам в сложном окружении. Бывает, что у приложения есть большое количество разнообразной обвязки, требуемых зависимостей, или, что еще сложнее, оно запускается только в конкретной операционной системе или с определенными версиями библиотек. Вот в этом случае Vagrant может сильно упростить и автоматизировать процесс развертывания окружения разработки.

Как это работает? Есть Vagrantfile, в котором написано, какой базовый образ виртуальной машины взять, и каким образом его налить, то есть, поставить и настроить нужный софт.

Базовый образ — это образ диска виртуальной машины от одной из популярных платформ виртуализации. Поддерживаются и VirtualBox, и Parallels и VMWare. Важный момент заключается в том, что под каждую платформу виртуализации (провайдер в терминах Vagrant) нужно готовить отдельный образ, а потом его поддерживать. Для сборки образов существует Packer от HashiCorp же, но я им не пользовался, предпочитая использовать минимальный образ, который не нужно часто обновлять.

Собственно, минимальный образ предоставляет базовую систему и некоторые необходимые для работы виртуализации пакеты. Дальше в дело вступает процесс наливки. Vagrant поддерживает все популярные системы управления конфигурациями: Chef, Ansible, Puppet, а также простые shell-скрипты. В целом идея в том, чтобы взять те же книги рецептов от Chef, что используются на продакшене, переконфигурировать их параметрами для разработки и переиспользовать. Идея отличная, но есть в ней большая доля лукавства. В большом проекте окружение production и development различается довольно сильно, вплоть до невозможности использовать одинаковый конфиг для половины сервисов. Часто это дань legacy коду, когда никаких средств автоматизации еще не существовало.

При проектировании новых сервисов стоит учитывать возможности инструментов автоматического конфигурирования окружения типа Vagrant и писать Chef cookbooks так, чтобы их можно было переиспользовать.

Другая особенность в том, что, по ощущениям, Vagrant и Chef мало кто использует, что создает некоторые дополнительные сложности, особенно, при развертывании среды разработки для Ruby проектов. Вот некоторое количество особенностей, с которыми пришлось столкнуться.

Разные версии Chef

От релиза к релизу Chef обрастает новыми функциями, улучшает синтаксис и исправляет баги. Проблема в том, что имеющиеся в изобилии библиотеки рецептов или cookbooks (дальше я буду писать просто кукбуки) при обновлении даже минорной версии Chef запросто могут перестать работать.

Хотя Vagrant способен установить при наливке требуемую версию Chef, это меняет логику работы с ним в дальнейшем. Например, если  Vagrant думает, что шеф установлен им самим, то искать его он будет в /opt, а не в PATH.

В случае с Ruby-сервисами все еще интереснее, так как Chef сам по себе — это Ruby gem. При необходимости поставить в систему RVM, сразу же получаем неработоспособную установку Chef, так как версия интерпретатора меняется. Кукбука chef-rvm, вроде бы, содержит необходимые сценарии для обхода этого поведения, но в моем случае они не сработали.

Выход: использовать двухстадийную наливку. В Vagrantfile прописывается сразу две секции config.vm.provision :chef_solo . Первая стадия лишь устанавливает RVM, нужную версию Ruby и ставит общесистемный набор gems, включая нужную версию Chef. При этом в базовый образ устанавливается версия Chef, которая есть в репозитории. Отлаживать такой простой рецепт, чтобы он работал как с версией из поставки ОС, так и с нужной версией намного проще, чем весь набор кукбук.

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

При запуске второй фазы будет использована уже нужная версия Chef, при этом, если потребуется переналивка, то Vagrant сможет корректно найти все исполняемые файлы по путям поиска, а не в /opt.

Монтирование cookbooks

В Vagrant 1.7.2 добавили замечательный баг. Суть его в том, что каталог с кукбуками монтируется только один раз — при первой наливке виртуалки. При последующих вызовах vagrant reload --provision  кукбуки смонтированы не будут и наливка упадет.

Есть понимание, что монтирование отключается, когда Vagrant создает файл с кешем синхронизированных каталогов, и, если этот файл удалять в нужные моменты, то монтирование происходить будет. Однако, просто так всегда удалять файл с кешем не получится, так как Vagrant смотрит в него при работе с rsync синхронизацией (зачем она нужна, в следующем пункте). Соответственно, когда Vagrant работает — файл должен быть на месте, когда перезагружает виртуалку и монтирует каталоги — файл можно удалить.

Такого поведения можно добиться при помощи плагина vagrant-triggers и следующей конфигурации (все в Vagrantfile).

Сначала нужно проверить, что плагин есть, и дать внятное предупреждение, если его нет

А потом в конфиге задать нужные триггеры

Теперь кукбуки монтируются и rsync не сломан.

Медленная работа сервиса

По умолчанию Vagrant монтирует в виртуальную машину дерево проекта через общие папки самой платформы виртуализации. В случае VirtualBox это будет работать медленно. Очень медленно. Поэтому есть рекомендация использовать для синхронизированных папок rsync. Делается это просто. Для каталога указывается тип в конфиге

… и, в общем-то, все. При запуске Vagrant синхронизирует каталог один раз, а после запуска можно использовать vagrant rsync  и vagrant rsync-auto  для однократной или постоянной синхронизации. Чуть менее удобно, но намного быстрее. vagrant rsync  для работы использует тот самый файл с кешем синхронизированных каталогов, поэтому и пришлось использовать плагин.

Зато теперь всё окружение разработки настраивается двумя командами

Чего и всем желаю.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *