📜 ⬆️ ⬇️

Development Environment with Vagrant and Chef






In this article I will try to introduce you to the wonderful utilities of Vagrant and Chef using the example of the automatic configuration of the development environment for a PHP developer (in fact, PHP is just an example here, everything described below can be used for any technology stack).

What do we do?


')
We will configure a virtual machine (VM) with Ubuntu 12.04 to work on a project in PHP, namely:



Quite a boring thing, especially if you do it with some frequency, so we will force the computer to do it yourself.

How can this help you?





All this is reality. The only question is "how?"



Vagrant



Vagrant is a utility that allows you to create a virtual machine and configure it automatically as you specified. Out of the box, Vagrant works with VirtualBox, although there is support for other solutions.

Looking ahead, all you need in order to deploy the environment on your computer is to run one command:

vagrant up 


Everything will be done automatically. Let's get down to our task.

To configure Vagrant uses only one file - Vagrantfile . That is what describes everything that needs to be done when starting a virtual machine. To initialize the Vagrant project, you must run the command

 vagrant init 


at the root of your project.

We have the following directory structure:
 recipes www Vagrantfile 


One of the main concepts in Vagrant is box. Box is an archive that contains an image of a virtual machine and a file with settings for Vagrant itself.

We'll use the box from the Vagrant website (each box includes at least the installed Chef, Puppet - this will be very useful for us a bit later).

The final Vagrantfile file will look like this (standard comments have been removed, see their documentation):

Vagrantfile
 # -*- mode: ruby -*- # vi: set ft=ruby : Vagrant::Config.run do |config| #  box'a config.vm.box = "precise64" # ,     box config.vm.box_url = "http://files.vagrantup.com/precise64.box" #   IP       config.vm.network :hostonly, "11.11.11.11" #   ,         ,   config.vm.share_folder "www", "/var/www", "www", :create => true #  Chef config.vm.provision :chef_solo do |chef| chef.cookbooks_path = "recipes/cookbooks" chef.roles_path = "recipes/roles" chef.add_role "web" # chef.data_bags_path = "../my-recipes/data_bags" chef.json = { "mysql" => { "server_root_password" => "%your_pass0%", "server_repl_password" => "%your_pass1%", "server_debian_password" => "%your_pass2%" } } end end 



Used by Ruby to describe the configuration file.
It makes no sense to describe all the details and trivialities of Vagrant, they can (and even should) be read in the documentation. It, by the way, is written well.

In the file we specify the name for the box. If it has not yet been downloaded, Vagrant will do it automatically and save it to your hard drive. For this, there is a URL where the box can be found. It is possible to specify the path in the file system.

In the network property, we indicate that the VM will be available on IP 11.11.11.11. This is done in order to be able to create and use several projects, defining names for them and storing the file of our real computer into the hosts.

Ports can also be used here: in this example

 ... config.vm.forward_port 80, 8080 ... 


we configure the VM so that on port 8080 from the host machine we get to port 80 of the guest machine. (in the Vagrant documentation, the host machine is our computer, the guest machine is a virtual machine). Read more here .

The share_folder property allows you to configure shared folders for the host machine and the guest machine. It is very convenient. You open your IDE and work with files located on your computer, not on the VM (although you can set up the editor to work with remote files), and they are instantly synchronized. By default, the folder with your project will be available on the VM along the /vagrant . In our case, we make available the www folder on the host machine along the path /var/www on the guest machine.

Next come the Chef settings, which will be described below. With the help of Chef, all the necessary software will be installed.
Here we have a choice , you can use:

  1. Chef
  2. Puppet
  3. bash scripts


Chef



Chef is a utility for managing configurations, project deployment, and more. In conjunction with Vagrant, we will use Chef to install all the software, as well as to create VirtualHost and the folders of the new project. Links to interesting articles on using Chef in clusters are provided at the end of the article.

Here a question may arise - how can you install so much of everything automatically? Here comes a large community of Chef and official cookbooks from its creators.

A cookbook is a collection of recipes, templates, attributes, and other settings files for Chef. For example, there is the Apache2 cookbook, with which Chef will put apache on your OS.
It is not clear what are recipes, templates, attributes? Do not worry, there is an excellent article that will shed light and help you deal with Chef very quickly. Below in the article we will create our own cookbook and everything will become even more transparent.

To install all the necessary software, we will use the following existing cookbooks:

  1. Apache2
  2. Mysql
  3. Php
  4. Vim
  5. Composer
  6. and others (some cookbooks are dependent on others, so you have to add them)


It is for Chef in our directory structure that the recipes folder exists.

Software installation process


For convenience, you can install Chef on the host machine to use knife to generate the basic folder structure for the new cookbook. This step is absolutely optional.

Run the following command as root:

 curl -L https://www.opscode.com/chef/install.sh | bash 


At the root of our project we make a config for Knife:

 mkdir .chef echo "cookbook_path [ '/path-to/recipes/cookbooks' ]" > .chef/knife.rb 


Create our own cookbook. It will run after the standard ones, when all the software is already installed, and will create VirtualHost with the specified domain name and with the specified path to the project, as well as create a database with the specified name. Let's call it app .

 knife cookbook create app 


Our cookbook will depend on the standard Database and, of course, on Apache2 , so add dependencies:

/path-to/recipes/cookbooks/app/metadata.rb
 name 'app' maintainer 'YOUR_COMPANY_NAME' maintainer_email 'YOUR_EMAIL' license 'All rights reserved' description 'Installs/Configures app' long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) version '0.1.0' depends "apache2" depends "database" 



Set the cookbook database for example. Since I installed Chef locally, I can take advantage of the possibilities of knife. Otherwise, you can simply download from github and copy it to the / path-to / recipes / cookbooks folder:

 cd recipes/cookbooks/ knife cookbook site download database tar zxf database-*.tar.gz rm *.tar.gz 


It also installs any other cookbook we need.

Creating VirtualHost for Apache


Create a template:

/path-to/recipes/cookbooks/app/templates/default/vhost.erb
 <VirtualHost *:80> ServerAdmin <%= @params[:server_email] %> ServerName <%= @params[:server_name] %> DocumentRoot <%= @params[:docroot] %> <Directory <%= @params[:docroot] %>> Options Indexes FollowSymLinks MultiViews AllowOverride ALL Order allow,deny Allow from all </Directory> ErrorLog ${APACHE_LOG_DIR}/<%= @params[:server_name] %>.log LogLevel debug </VirtualHost> 



As you have noticed, variables can be used in the template (set via attributes). We will save the default values ​​for them in a separate file:

/path-to/recipes/cookbooks/app/attributes/default.rb
 default["app"]["database"] = "app" default["app"]["path"] = "/var/www/vm-app" default["app"]["server_name"] = "vm-app" default["app"]["server_email"] = "vm.app@example.com" 



And let us redefine all variable through Vagrantfile.

Vagrantfile
 ... chef.json = { "app" => { "path" => "/var/www/cool-another-app", "server_name" => "cool-another-app", "server_email" => "cool@another-app.com", "database" => "cool_another_app_db" }, "mysql" => { "server_root_password" => "%your_path0%", "server_repl_password" => "%your_path1%", "server_debian_password" => "%your_path2%" } } ... 


Great, it remains to use Chef to create the desired folder, and create a specific virtual host file. All this can be done through auxiliary functions, called resources. We write these actions directly in the recipe:

/path-to/recipes/cookbooks/app/recipes/default.rb
 # # Cookbook Name:: app # Recipe:: default # # Copyright 2013, YOUR_COMPANY_NAME # # All rights reserved - Do Not Redistribute # include_recipe "mysql::ruby" #     directory node["app"]["path"] do owner "root" group "root" mode "0755" action :create recursive true end #    VirtualHost,    () web_app 'app' do template 'vhost.erb' docroot node['app']['path'] server_name node['app']['server_name'] server_email node['app']['server_email'] end 


At the same time, Chef will do everything automatically. In our case: add the site to / etc / apache2 / sites-available and execute a2ensite server_name

A list of all available resources can be found in the documentation .

Creating a database


To do this, we simply add the following code to the /path-to/recipes/cookbooks/app/recipes/default.rb file:

 mysql_database node['app']['database'] do connection ({:host => 'localhost', :username => 'root', :password => node['mysql']['server_root_password']}) action :create end 


The list of all cookbooks that Chef needs to perform is configured in the run_list array in the file:

/path-to/recipes/roles/web.json
 { "name": "web", "default_attributes": { }, "override_attributes": { }, "json_class": "Chef::Role", "description": "web server role", "chef_type": "role", "run_list": ["recipe[apt]", "recipe[chef-dotdeb]", "recipe[chef-dotdeb::php54]", "recipe[apache2]", "recipe[apache2::mod_php5]", "recipe[apache2::mod_rewrite]", "recipe[php]", "recipe[mysql]", "recipe[mysql::server]", "recipe[app]", "recipe[composer]", "recipe[sqlite]", "recipe[vim]", "recipe[cron]", "recipe[ntp]"] } 


That's all! Our environment is ready to check. Perform in the project root:

 vagrant up 


After this command, Vagrant initializes the specified box and starts installing all necessary software.

What do we have in the end?



As a result, we have a fully configured virtual machine. SSH access. To do this, simply execute

 vagrant ssh 


After adding the IP address and the name of the test site to the hosts, you simply open it in the browser on the host machine, and the code runs on the VM.
The important point is to maintain the state of the VM. If this is not done, then after each launch via vagrant up , the software will be reinstalled . At the same time, the whole point of our idea is lost. To solve this situation, Vagrant has the following commands:

  1. vagrant suspend - saves the current state and after the vagrant up command, work continues from the saved point
  2. vagrant halt - turns off VM


After executing these commands, you can safely restart the OS and resume work again.

To destroy all resources associated with a VM, use the vagrant destroy command.
Some articles advise keeping the database on the host machine so as not to risk data loss.

With the help of Vagrant, it is also possible to raise a test cluster, while the communication between virtual machines is configured via the network config property.

Useful links for reading



For those who are interested, I suggest to get acquainted with the following resources:

Vagrant + Chef environment files that were configured in this article.

Vagrant:

  1. docs.vagrantup.com/v2 - documentation. Required to read.
  2. www.vagrantbox.es - list of boxes on all popular OS
  3. habrahabr.ru/post/140714
  4. net.tutsplus.com/tutorials/setting-up-a-staging-environment is a very cool article on setting up a staging environment. Required to read.
  5. www.phptherightway.com - php developers


Chef:

  1. docs.opscode.com - official website
  2. docs.opscode.com/resource_deploy.html - deployment
  3. gettingstartedwithchef.com - must be read. Reveals all the basic things Chef
  4. habrahabr.ru/company/scalaxy/blog/87302





Thanks to everyone who read to the end. I hope the article turned out to be useful and caused you positive emotions, as is the case with those who hear, for example, about Vagrant for the first time.
I apologize in advance for inaccuracies and, possibly, technical illiteracy in one form or another.

Source: https://habr.com/ru/post/178797/


All Articles