В этом посте подробно рассказывается, как мы используем Vagrant , инструмент с открытым исходным кодом для создания и распространения виртуализированных сред разработки, в нашей повседневной работе. Мы используем его с командой из 7 человек для интеграции довольно сложного приложения. Чтобы получить представление о сложности:
- У нас есть сервер nodejs, говорящий с базой данных redis
- приложение grails, которое читает из базы данных redis и записывает в базу данных mysql
- интерфейс рельсов, который читает из сервисов отдыха Grails и пишет в MySQL DB
- приложение perl, импортирующее данные в базу данных mysql из внешнего источника
- nodejs записывает через flume в хранилище hadoop
- мы извлекаем данные через sqoop из хранилища hadoop
И все это делается на одной машине Vagrant. Мы даже не можем представить себе необходимость синхронизировать эту настройку на всех разных машинах разработки без Vagrant.
Так что спасибо «Митчелл Хасимото» и «Джон Бендер» за этот потрясающий инструмент!
Мы надеемся, что этот пост (и следующие в этой серии) вдохновит вас на то, чтобы делать с ним что-то интересное.
Готовимся к взлету
Стандартные требования
Vagrant, как описано на сайте, является инструментом для создания и распространения виртуализированных сред разработки.
- Чтобы использовать его, вам нужно иметь некоторые вещи на месте:
- вам нужно иметь Virtualbox 4.0.x установлен.
- есть рубиновый бег
- Мы хотели бы добавить следующее в смесь (не обязательно)
- мы рекомендуем использовать RVM )
- и у нас установлен какой-то контроль версий (мы используем git)
Установка rvm (необязательно)
RVM — это отличный способ управления различными элементами ruby в системе. Нам это очень нравится, потому что: — Он делает все в пользовательском пространстве (нет sudo для драгоценных камней) — он позволяет использовать отдельные наборы гемов для каждого (проекта / клиента) в отдельности — позволяет использовать разные версии ruby на одной машине
Установить его просто:
$ bash < <( curl http://rvm.beginrescueend.com/releases/rvm-install-head )
Чтобы ваша оболочка подняла ее, вы можете
$ source "$HOME/.rvm/scripts/rvm"
или чтобы сделать его постоянным, добавьте его в свой .bash_profile
# This loads RVM into a shell session. $ [[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"
Настройка rvm
До сих пор у нас есть только сценарии RVM и пока нет рубина. Чтобы установить fi ruby 1.9.2 в вашей системе, вы можете:
$ rvm install 1.9.2
Настройка vagrant проекта под названием ‘awesome’ с помощью rvm
Создать структуру каталогов
$ mkdir awesome-vagrant
Теперь создайте файл с именем .rvmrc
echo "rvm_gemset_create_on_use_flag=1" > .rvmrc echo "rvm gemset use awesome-vagrant" >> .rvmrc echo "rvm use 1.9.2" >> .rvmrc
Вернуться на один каталог
$ cd ..
Запустите чтение .rvmrc (работает через bash hooks). Это попросит вас доверять вашему новому файлу .rvmrc
$ cd awesome-vagrant ... RVM has encountered a not yet trusted .rvmrc file in the = = current working directory which may contain nasty code. ...
Теперь вы должны увидеть правильную версию ruby и gem
$ ruby -version $ gem -version
Так что теперь каждый раз, когда вы входите в каталог ‘awesome-vagrant’, в него загружается правильный набор gemset ‘awesome-vagrant’, и у вас есть версия ruby, которая вам нравится. Довольно круто, не так ли?
Установка git (необязательно)
Большинство ОС теперь имеют пакет для git. Просто используйте ваш любимый yum, apt, dpkg или любой другой, чтобы установить его.
В Mac OSX вы можете использовать macports , мы используем homebrew, потому что вам не нужны права root (он устанавливает файлы в / usr / local / bin)
Кроме того, rvm предоставляет основанную на сценариях установку git
bash < <( curl http://rvm.beginrescueend.com/install/git )
Зажигать двигатели
Бродяга 101
Теперь, когда все предпосылки созданы, мы можем перейти к самому базовому примеру использования vagrant.
Пример на бродячем сайте выглядит так
$ cd awesome-vagrant $ gem install vagrant $ vagrant box add base http://files.vagrantup.com/lucid32.box $ vagrant init $ vagrant up $ vagrant ssh
И вуаля, это все, что нужно, чтобы вы начали работать как разработчик с ясной коробкой! Довольно аккуратно он? Под прикрытием происходит следующее:
- Бродячая коробка добавить базу http://files.vagrantup.com/lucid32.box
- это загрузит файл lucid32.box
- распакуйте файл lucid32.box в каталог $ HOME / .vagrant / boxes
- и дать ему название «база»
- бродячий init :
- создает файл с именем Vagrantfile в вашем текущем каталоге
- когда вы смотрите на файл, он будет содержать директиву
... config.vm.box = "base" ...
это то, что делает ссылку на поле, которое мы назвали «база»
- Вы можете дополнительно отредактировать Vagrantfile, прежде чем запустить
- бродячий до :
- до сих пор виртуальная машина не создавалась
- поэтому vagrant будет импортировать диски из коробки ‘base’ в Virtualbox
- сопоставьте через NAT порт 22 вашей виртуальной машины с бесплатным локальным портом
- он создаст файл .vagrant: файл, содержащий отображение между вашим описанием ‘base’ и UUID виртуальной машины.
- Если вы хотите следовать магии, просто запустите Virtualbox, и вы увидите, что машина создается
- бродячий сш :
- это будет искать сопоставление ssh внутри и выполнит процесс SSH для входа в систему
- используйте закрытый ключ use vagrant для входа в систему, в которой пользователь vagrant имеет открытую настройку на виртуальной машине
А как насчет окон?
Некоторые из членов нашей команды не используют вариант MacOSX или Linux, но работают под управлением Windows.
Есть несколько отличных инструкций по запуску Vagrant на Windows в качестве хоста: — Vagrant и Windows — Vagrant и Windows 64-Bit — Jruby, Winole32, Vagrant и Windows
Мы использовали следующее:
- Установите версию Java 64 Bit
- Установите для переменной среды $ JAVA_HOME 64-битную версию
- Поместите $ JAVA_HOME / bin в свой путь
- Установите Jruby 64 Bit (Оле версия)
- Поместите $ Jruby / bin на свой путь
- установить бродячий драгоценный камень
- используйте Putty вместо команды vagrant ssh
- импортировать бродячий закрытый ключ в вашу замазку
Запуск команды vagrant намного медленнее, чем в linux / macosx. Я не знаю почему, но это замедляет взаимодействие.
- Мы обнаружили, что для уничтожения окна Windows иногда требуется вручную очистить каталог Virtualbox Machine этой виртуальной машины.
Запуск Windows в качестве виртуальной машины под управлением Vagrant в настоящее время остается мечтой. Но проект Winrm делает хороший способ стать ssh-альтернативой Windows-машинам. Ребята из opscode уже интегрируют winrm в шеф-повар / нож . Возможно, я скоро начну писать плагин winrm vagrant.
Слово о Vagrant базовых коробках
До недавнего времени поиск базовых пакетов Vagrant требовал поиска в Интернете и поиска URL-адресов на разных сайтах. Гарет Рашгроув проделал большую работу, настроив vagrantbox.es, где вы можете отправлять свои собственные базовые блоки в центральный каталог.
Эти базовые ящики хороши, но вы должны доверять тому, кто упаковал коробку. В будущем мы можем увидеть поставщиков, предоставляющих базовые блоки для своих настроек, аналогичных официальным AMI на Amazon, но мы еще не готовы.
Вы можете создать виртуальную машину virtualbox самостоятельно (ручная установка, установка pxe или запуск из существующего базового блока), а затем экспортировать ее как бродячую коробку.
$ vagrant package --base my_base_box
Представляем veewee: простой способ загрузить новые базовые блоки
Альтернативой является использование veewee для автоматической загрузки машины с нуля. Этот бродячий плагин, который я создал, облегчает создание базовых блоков с нуля. Он имитирует ручную установку, нажимая VRDP, чтобы набрать некоторую строку загрузки linux и прочитать кикстарт / preseed через HTTP-сервер.
Ниже приводится краткое изложение того, как создать базовую версию Ubuntu с помощью veewee.
Установите драгоценный камень:
$ gem install veewee
Перечислите доступные определения базовых пакетов veewee:
$ vagrant basebox templates The following templates are available: ... vagrant basebox define '<boxname>' 'ubuntu-10.10-server-i386' vagrant basebox define '<boxname>' 'ubuntu-10.10-server-i386-netboot' ...
Определите новое поле, это создаст каталог определения
$ vagrant basebox define 'myubuntu' 'ubuntu-10.10-server-i386'
Взгляните на каталог определений и измените их, если хотите
$ ls definitions/myubuntu definition.rb postinstall.sh preseed.cfg
Постройте коробку. Обратите внимание, что при необходимости будет загружен необходимый ISO-файл.
$ vagrant basebox build 'myubuntu'
Экспортируйте созданный vm как базовый ящик. Это, наконец, создаст myubuntubox.box
$ vagrant basebox export'myubuntu'
Он все еще экспериментальный, но у нас есть автоматическая установка для различных версий Archlinux, Centos, Debian, Freebsd, Ubuntu. Я думаю, что выгода от этого заключается в том, что вам не нужна среда PXE для настройки машин, и она позволяет вам тестировать ваши предварительные требования, запускать файлы и управлять версией вашего базового блока.
Помните, что это код
Сейчас самое подходящее время для контроля версий вашего проекта
$ cd $ git init $ git add Vagrantfile $ git commit -m "This was just my first commit"
Взятие испытательного полета
Получение вашего кода на борту
Теперь, когда у вас запущен базовый ящик и вы можете войти в него, я знаю, что вы готовы начать разработку. Итак, давайте возьмем тот код, который вы уже сделали из git.
$ cd awesome-vagrant $ git clone git@somerepo:/var/git/awesome-datastore $ git clone git@somerepo:/var/git/awesome-frontend $ git clone git@somerepo:/var/git/awesome-data
Это приводит к следующей структуре
[DIR] awesome-vagrant - [DIR] awesome-datastore (component1) - [DIR] awesome-frontend (component2) - [DIR] awesome-data (component3) - Vagrantfile
Каждый каталог, показанный здесь, является git-репозиторием, который проверяется отдельно. Теперь мы можем смонтировать это как каталоги внутри нашей виртуальной машины. Это то, что Бродяга называет общими папками.
Наш Vagrantfile выглядит следующим образом
config.vm.share_folder "awesome-datastore", "/home/vagrant/awesome-datastore", "./awesome-datastore" config.vm.share_folder "awesome-frontend", "/home/vagrant/awesome-frontend", "./awesome-frontend" config.vm.share_folder "awesome-data", "/home/vagrant/awesome-data", "./awesome-data"
Это позволит настроить каталоги внутри вашей виртуальной машины, чтобы вы могли редактировать их, используя любимую среду IDE на своем ноутбуке, и мгновенно получать доступ к файлам внутри вашей виртуальной машины без необходимости синхронизации.
После редактирования файла вам необходимо «перезагрузить» машину, чтобы принять эти настройки
$ vagrant reload
У нас довольно много проблем с записью в общие папки. Стандартный Vagrant использовал дополнения Virtualbox Guest для предоставления доступа к папке вашего локального / хост-компьютера на виртуальной машине. Было много жалоб на стабильность, и поэтому вы можете проверить использование папок NFS для общего доступа к каталогам. Просто добавьте флаг NFS в конце. Обратите внимание, что для этого сначала необходимо установить nfs-client в basebox.
config.vm.share_folder "awesome-frontend", "/home/vagrant/awesome-frontend", "./awesome-frontend",<b>{:nfs => true}</b> ...
Связь между host и vm осуществляется через сеть только для хоста, поэтому ваши общие ресурсы nfs не будут видны внешнему миру. Поэтому вам нужно включить hostonly network, добавив следующее в ваш vagrant файл
config.vm.network "33.33.33.10"
Не забудьте перезагрузить после изменения этого
$ vagrant reload
Добавление управления конфигурацией в смесь
Может быть заманчиво войти в ваш новый бродячий ящик и вручную установить несколько пакетов, чтобы начать работу. Вы все должны помнить, Виллем ван ден Энде сказал, что вход на сервер считается вредным
Реальная сила Vagrant в том, что он способствует использованию управления конфигурациями для этого. Инфраструктура как код, FTW!
В настоящее время Vagrant поддерживает сценарии Chef-Solo, Chef, Puppet, Puppet-Server и bash в качестве «провайдеров». Поставщики отличаются от традиционных сценариев установки, поскольку они следуют принципу идемпотентности. Их можно запускать снова и снова и получать одинаковые результаты.
Команда vagrant для запуска это:
$ vagrant provision
и инициализация также выполняется, когда вы делаете
$ vagrant up
Если не хотите, чтобы он работал, вы можете указать
$ vagrant up --no-provision
Пример установки Chef-Solo
Настройка и объяснение Chef выходит за рамки этого поста. На веб-сайте Opscode есть отличное описание того, как настроить хранилище chef.
awesome-chefrepo [DIR]cookbooks #those that come from opscode [DIR]site-cookbooks #or your own
Пример фрагмента Vagrantfile выглядит следующим образом:
config.vm.provision :chef_solo do |chef| chef.cookbooks_path = ["awesome-chefrepo/cookbooks", "awesome-chefrepo/site-cookbooks"] chef.log_level = "debug" chef.add_recipe("nfs-client") chef.json.merge!({ :mysql => { :server_root_password => "supersecret", :server_repl_password => "supersecret", :server_debian_password => "supersecret"}, :java => { :install_flavor => "sun"} }) end
Запуск «Бродячего обеспечения» будет:
- поделиться cookbooks_path (и rolepaths, …) в виртуальной машине
- создать конфигурационный файл solo.rb и перенести его в / tmp
- сгенерируйте файл dna.json: объединение информации о бродячем json и предоставленном вами json
- войти в виртуальную машину как бродяга и сделать
sudo chef-solo -r solo.rb -j dna.json
Более подробные заметки можно найти в разделе сайта Vagrant Provisioner.
Пример установки куклы
Джеймс Тернбулл написал поставщика марионеток
Мы настраиваем наше кукольное репо следующим образом:
awesome-puppetrepo [DIR] manifests [DIR] modules mybox.pp
С соответствующим следующим разделом кукольный Vagrantfile
config.vm.provision :puppet do |puppet| puppet.pp_path = "/tmp/vagrant-puppet" puppet.manifests_path = "./awesome-puppetrepo/manifests" puppet.module_path = "./awesome-puppetrepo/modules" puppet.manifest_file = "./awesome-puppetrepo/mybox.pp" end
Где mybox.pp содержит манифест (fi apache2) для запуска в этом окне
package "apache2": { ensure => 'installed' }
Запуск «Бродячего обеспечения» будет:
- поделитесь manifes_paths + module_paths в виртуальной машине
- перенесите ваш файл manifest_file в / tmp
- войти в виртуальную машину как бродяга и сделать
sudo puppet --modulepath awesome-puppetrepo/modules mybox.pp
Более подробные заметки можно найти в разделе сайта Vagrant Provisioner.
Открытие коробки — Сеть
Теперь, когда у вас есть и код, и ваша среда в настройке виртуальной машины, следующий шаг — получить доступ к некоторым сетевым службам. Vagrant облегчает эту задачу, сопоставляя порты внутри виртуальной машины с портами в вашей локальной системе.
# Forward a port from the guest to the host, which allows for outside # computers to access the VM, whereas host only networking does not. # config.vm.forward_port "http", 80, 8080 config.vm.forward_port "awesome-datastore", 8080, 8080 config.vm.forward_port "awesome-frontend", 8000, 80
Снова, чтобы эти эффекты вступили в силу, вам нужно перезапустить бродячую коробку
$ vagrant reload
Теперь вы можете зайти на ваш http: // localhost: 8080 и получить доступ к вашему интерфейсу внутри коробки.
Преодоление плохой производительности сети
Мы заметили, что некоторые из наших сетевых служб будут работать плохо при доступе извне и будут быстрыми изнутри. Сначала мы подозревали, что это происходит из-за замедления работы сети Virtualbox, но оказалось, что разрешение DNS вызывает задержки. Ранее нам говорили, что « все проблемы с DNS » и да:
- в зависимости от сети, в которой вы работали, DNS плохо настраивался для разрешения внутренних IP-адресов. Проверьте свой распознаватель
- у нас была установлена библиотека libavahi (очевидно, поставленная с java): поэтому нам пришлось отключить ее, чтобы ускорить разрешение
Тюнинг ваших двигателей
Настройка Vagrantfile
Самое замечательное в Vagrantfile — это фактический код ruby.
Настройки только для некоторых хостов
Следующий фрагмент позволяет нам по-прежнему предоставлять общий доступ к Vagrantfile, но позволяет людям использовать NFS, если им это нужно.
# Switching to nfs for only those who want it nfs_hosts=%w(mylaptop1 ruben-meanmachine) require 'socket' my_hostname=Socket.gethostname.split(/\./)[0] if nfs_hosts.include?(my_hostname) # Assign this VM to a host only network IP, allowing you to access it # via the IP. config.vm.network "33.33.33.10" share_flags={:nfs => true} else share_flags={} end
Включение различных настроек в зависимости от среды
Помимо людей, разрабатывающих код или код управления конфигурацией, у нас также есть люди, которые используют машины Vagrant для демонстрации демонстраций в разных местах. Они получают последнюю версию из git и могут собирать виртуальные машины с включенными новейшими функциями.
Для демонстраций им не нужно иметь общие каталоги всех доступных компонентов кода. Мы ввели понятие
- vagrant_env: разработка, тестирование, производство, демонстрация,
- awesome_mode: флаг, указывающий, в каком режиме должны работать наши приложения
Оба могут быть установлены как переменные окружения и подобраны Vagrantfile
if (vagrant_env=="development" && ENV["AWESOME_MODE"]!="demo")
Установить эти переменные так же просто, как добавить их к команде vagrant
$ vagrant_env=development vagrant up
А теперь, как команда, пожалуйста:
Некоторые наблюдения
Мы использовали vagrant как команду уже около 2 месяцев, и вот некоторые замечания, которые мы сделали:
- Очевидно, что это помогает всем создать единую среду для разработки, последняя версия — всего один шаг.
-
Центральный подход побуждает людей а) делать частые коммиты и б) делать стабильные коммиты.
-
Задача написания рецептов / манифестов не решается всеми членами команды и, похоже, остается основной работой ориентированных на систему людей в команде.
- Манифесты чтения помогают людям понять, что необходимо, и позволяют легко указать, что необходимо изменить. Но обучение навыкам написания рецептов / манифеста является блокирующим фактором, так же как наличие бэкэнд-разработчика, пишущего код внешнего интерфейса.
- When manifest/recipes are modified during a sprint, provisioning an existing virtual machine might fail as we don’t take migrations from one VM state to the other into account. In that case, a box destroy and full provision is required.
-
The test the admins do before committing their manifests, is that they destroy their own ‘development’ box and re-provision a new box to see if this works.
-
The longer the the provision takes, the less frequent people do it. It’s important to keep that process as fast as possible. It’s all about feedback and we want it fast.
- Installation problems would get noticed far sooner in the process.
- People would only do a full rebuild in the morning when getting their coffee.
Having both development and production mode running on the Vagrant box
In our environment we have both the development and the production version running.
F.i. for our rails component we have:
- a share of the awesome-frontend inside the box (and when this starts it runs on port 3000)
- we have the production mode running on port 80 (pulled from git as the latest tagged production)
This allows us to easily have both versions running. The production version is installed by a manifest/recipe and the share is started manually.
In summary
Vagrant rocks, but by now you should know !
Don’t worry the journey continues…
In the next post, I’ll introduce you how we setup Vagrant with testing and use a Continuous integration environment to have it build a new box , run the tests and make everybody happy. So stay tuned!
For additional inspiration:
- Vagrant main website
- Mitchell Hashimoto Blog
- John Bender’s blog
- Cloudspace: Setting up development environments with vagrant and the opscode platform
- My vagrant workflow — by Dougal Matthews
- Bring the cloud on your desktop with Vagrant
- Start using Vagrant by Theodo
- Vagrant — Spatula
- Rvm with vagrant
- Instant Rails in A Virtualbox
- Openstack — Single node nova installation using Vagrant and chef
- Upgrading to Movable Type5 using chef and vagrant
- Haskell and Vagrant’s Middleware
- Getting the most out of chef with Scalarium and Vagrant
- Gareth Rushgrove — talk at Fosdem on Configuration Management for development environments
- Gareth Rushgrove — default Recipes for Vagrant Virtual Machines — Using Gitrepos for your recipes
- Gareth Rushgrove — A continuous deployment example setup