April 11, 2013

How to Create a Virtualized Environment With Chef and Vagrant

DevOps
Java Tools

Today, we will show how to combine Vagrant and Chef to create your first virtualized environment in a fully-automated fashion. But before we get started, let's look at Vagrant and Chef, and why combining them can be beneficial.

What Is Vagrant?

Vagrant is an open-source software that is used for building and maintaining portable, virtual software IDEs. It allows users to create and configure and reproduce low profile development environments, and, as we'll see later, it offers the flexibility to destroy (and recreate) virtual machine images with a single command.

What Is Chef?

Chef is a configuration management tool used for creating system configuration specifications, or "recipes." Compatible with a variety of cloud-based platforms, it's a popular choice for both large and small scale systems.

Why Use Vagrant With Chef?

The biggest benefit of Vagrant and Chef is the ability recreate configured virtualized environments quickly and easily. In our Vagrant Chef tutorial, we'll show how to configure your first Vagrant build with Chef, then how to recreate a destroyed build with a single command. Here's what you'll need to get started.

Creating a Vagrant Project

We assume you have successfully installed Vagrant. What’s awesome is that you don’t need to worry about installing Chef, Vagrant will take care of that automatically for you.

First, we need to create a new Vagrant project - here we are basically going to quickly fast-forward you through the instructions in the original Vagrant post. If you still have that project around, feel free to jump straight to the next section.

So, let’s get it over with and just execute the following commands:


mkdir my-env
cd my-env
vagrant init precise32 http://files.vagrantup.com/precise32.box

 

As a result, you should have a Vagrantfile in the current directory with a bunch of comments and the following active lines:


Vagrant.configure("2") do |config|
    config.vm.box = "precise32"
    config.vm.box_url = "http://files.vagrantup.com/precise32.box"
end

 

You can check the original Vagrant post for full explanation of the above steps and the meaning of the Vagrantfile contents.

Adding Chef to the Vagrant Project

Now that we have a basic Vagrant project set up, let’s add Chef provisioning to it, so we can install new software packages to the bare-bones box in an automatic fashion. As an example, let’s ask Chef to provision Apache httpd for us by adding 4 lines to Vagrantfile:


Vagrant.configure("2") do |config|
    config.vm.box = "precise32"
    config.vm.box_url = "http://files.vagrantup.com/precise32.box"
    config.vm.provision :chef_solo do |chef|
        chef.add_recipe "apache2"
        chef.json = { :apache => { :default_site_enabled => true } }
    end
end

 

The added lines instruct Vagrant to use Chef Solo for provisioning (solo-mode is the best for getting started) and to provision “apache2” on the box. How does it know how to provision “apache2”? It looks for a cookbook in the cookbooks subdirectory in the current directory.

Finding the Right Cookbook

But wait, I do not have any cookbooks! Where is the nearest library? Have no fear, we’ve got you covered - if you want to provision some commonly used package (e.g. Apache httpd), the chances are that someone has already written a cookbook for it and you can head over to OpsCode Community website and look for it there. Of course, you can always look for it on the interwebs or roll your own.

Using the Knife Command

But let’s not get carried away, we are trying to provision “apache2” package and, as that is readily available on the OpsCode site, we can use knife (a command-line tool for Chef that we also mentioned in the last post) to download the cookbook to the current directory:


knife cookbook site download apache2

 

If you do not have knife installed, you can also manually download the apache2 cookbook and place it in the current directory (“my-env”).

Next, create the cookbooks directory and extract the downloaded package into it:


mkdir cookbooks
tar xvzf apache2-*.tar.gz -C cookbooks

 

That’s it - if you were to bring the virtual machine up now, “apache2” module would be nicely provisioned on it. But there is still one final piece missing from this puzzle.

Adding Port Forwarding

Although we have added all the instructions for installing and running Apache httpd, we still need some way to verify that it actually works on that virtual machine. How could we do that? Usually, you would open the website with a browser -- but this site is contained inside a virtual machine, so how can we get access to it?

Yep, you guessed it - this is a common problem, so Vagrant has a solution built-in. It allows you to map a port on the host machine to a port on the virtual machine, forwarding all the traffic. So, let’s map port 8888 on localhost to port 80 on the virtual machine - fortunately, this is as simple as adding just one line to the Vagrantfile:


Vagrant.configure("2") do |config|
    config.vm.box = "precise32"
    config.vm.box_url = "http://files.vagrantup.com/precise32.box"
    config.vm.network :forwarded_port, guest: 80, host: 8888
    config.vm.provision :chef_solo do |chef|
        chef.add_recipe "apache2"
        chef.json = { :apache => { :default_site_enabled => true } }
    end
end

 

Elegant, isn’t it? :-)

Bringing Vagrant Up

Now we should be all set for trying it out. Let’s bring the machine up (this will also automatically provision it):


vagrant up

 

Or, if it is already up, just re-provision it:


vagrant provision

 

Now you can open http://localhost:8888/ on your machine and you should see the good-old “It works!” page.

Why Use Chef?

You might be wondering: “Well, can’t I just ssh into the Vagrant virtual machine, type in ‘sudo apt-get install apache2’ and be on my way - why all this trouble with Chef and recipes?”

That is a valid question, and let’s answer that by throwing away the freshly built virtual machine and recreating it from scratch with just two commands.

Destroy the machine (this will delete the virtual machine image, freeing up your precious disk space):


vagrant destroy

 

And now, recreate the machine:


vagrant up

 

With a single command, you now have a freshly built virtual machine, all configured and ready to go. Finally, you can reuse that Vagrantfile also with other virtualization/cloud providers, such as VMware Fusion or AWS.

Final Thoughts

As you can see, it is quite easy to use Chef and Vagrant together in order to automatically create virtual machines from scratch -- this combination is very powerful and enables you to treat your infrastructure as code, which is a huge step in the DevOps direction.

Additional Resources

Want more DevOps insights? Check out our latest DevOps articles, webinars, and white pages at our resources page.

See Recent Resources

Get Started With Our Java Tools

Build better applications faster with JRebel -- try free for 10 days!

Start Trial