Vagrant Introduction

Vagrant Introduction

The problem: I need to test something or learn something new and it takes too long to get a clean machine up and running.

The problem: Well it works on MY machine. Why not yours?

On their site their tag line is "Create and configure lightweight, reporducible, and portable development environments."

On their site they show it is this easy to get started.

$ vagrant init ubuntu/trusty64
$ vagrant up

Their tutorial starts off here ; we'll use it as our guide.

Mise en Place (Everything in Place)

Before we get started let us get Vagrant and Virtualbox installed. Below I've included links to the download section of each.

Some Vocab

Okay, lets go through some of the terms we're going t be using in this section so we are all have the same base understanding.

  • Vagrantfile - The main configuration file for Vagrant. Yes the V in Vagrantfile must be capitalized.
  • Provider - Vagrant can talk to many different APIs to deploy systems in various environments. Think of the term provider as what API we are talking to.
  • Vagrant Boxes (Or Box) - This is a Vagrant base image. This is what helps make Vagrant so quick to deploy environments.

Core Commands

In this section we'll discover the basic Vagrant work flow. We'll see that regardless of provider this work flow for the most part remains the same.

Creating the Vagrantfile

Before we do anything we need to create a directory we'll use as our project directory. Each directory represents an environment.

Once we have created our project directory we can create the Vagrantfile with the vagrant init command. The command is followed by which box we want to use in this environment.

$ vagrant init ubuntu/trusty64

Note: The Vagrantfile is very well documented, but we wanted to make it less verbose we could use the --minimal option.

Bringing our Machine Up

Bringing the machine up is simple.

$ vagrant up

That's it. This command will read our Vagrantfile and bring up a machine based off the provider and the settings in our Vagrantfile.

Getting in to our Machine

One of the beautiful things about Vagrant is we do not have to worry so much about passwords and IP addresses to remember. We access our machine via the ssh sub-command.

$ vagrant ssh

Boom! Now we can get work.

And once we are done?

In the way we are going to be using Vagrant and Virtualbox we are going to be bringing up and tearing down machines often. We can tear a machine down using the destroy sub-command.

$ vagrant destroy

Note: Keep in mind all of these commands work relative to the machines in the current project directory

What else?

There are a few more one-off commands we might use within our workflow.

Checking the status of a machine.

$ vagrant status

Checking the status of ALL the machines

$ vagrant global-status

If you have made changes to your Vagrantfile and need to reload your settings.

$ vagrant reload

If you do want to bring down your machine, but do not want to completely destroy it.

$ vagrant halt

Hands-On

Let us see if we can do the following. For each step, how do we verify our work?

  1. Get Vagrant and Virtualbox installed
  2. Create a new Vagrant environment using ubuntu/trusty64 as your box
  3. Bring your machine up.
  4. SSH in to your machine and update all of the available packages.

Extending Our Vagrant Knowledge

Getting and Managing Additional Boxes

In previous examples we used an Ubuntu Trusty (14.04) box from Vagrant's box repository. There are two sources for additional boxes.

Atlas / Vagrant Cloud - HashiCorp Atlas ( a.k.a Vagrant Cloud)

Vagrantbox.es - Just more boxes. Can be used as secondary source. In most cases we would look to use images form Atlas

As we start to manage additional Vagrant boxes we'll want to use the vagrant box sub-commands to manage this boxes.

List out all of the Boxes

$ vagrant box list
centos/7        (virtualbox, 1607.01)  
jhcook/centos6  (virtualbox, 2.6.32.642.3.1)  
rscloud         (rackspace, 0)  
ubuntu/trusty64 (virtualbox, 20160801.0.0)  
ubuntu/trusty64 (virtualbox, 20160816.0.0)  
xenial          (virtualbox, 0)  

Add a new box without a vagrant init

$ vagrant box add <SOME-NAME>

Remove a box once it is no longer needed

$ vagrant box remove <SOME-NAME>

Networking

There are two ways we can access our guest VM from our host machine.

Via Port Forwarding

The following will configure the host machine to forward port 8080 to port 80 of our guest VM.

config.vm.network "forwarded_port", guest: 80, host: 8080  

With this setting we can access our VM via http://127.0.0.1:8080

Via a Private Network

The following will configure an additional NIC on our guest machine. It will assign the NIC the IP address of 192.168.33.10.

config.vm.network "private_network", ip: "192.168.33.10"  

With this setting we can access our VM via http://192.168.33.10

Provisioning

Vagrant's main purpose is to deploy an environment. It talks to the API and configures and creates VMs. The other of the environment is configuration management. Vagrant can use a number of provisioners such as Shell, Ansible, Salt Stack, Puppet and Chef.

The default Vagrantfile gives us an example of using the Shell provisioner.

config.vm.provision "shell", inline: <<-SHELL  
sudo apt-get update  
sudo apt-get install -y apache2  
SHELL  

The commands between <<-SHELL and SHELL will be executed on the VM.

Other provisioners can be found on Vagrant's site. https://www.vagrantup.com/docs/provisioning/

RE-provisioning

If at first we don't succeed . . . . Vagrant allows us to iteratively re-run just the provisioning section of our Vagrantfile.

$ vagrant provision

Multi-Machine

Up until this point we have only been working with a single machine. Part of the power of Vagrant is we can deploy and configure entire environments.

The following is an example of creating a Vagrantfile with multiple machines.

Example Vagrantfile for multiple machines

This file configures two machines with the hostnames of server and client.

Vagrant.configure(2) do |config|  
  config.vm.define "server" do |server|
    server.vm.box = "ubuntu/trusty64"
    server.vm.hostname = "master"
    server.vm.network "private_network", ip: "192.168.33.100"
    server.vm.provider "virtualbox" do |vb|
      vb.gui = false
      vb.memory = "1024"
    end
  end

  config.vm.define "client" do |client|
    client.vm.box = "ubuntu/trusty64"
    client.vm.hostname = "slave"
    client.vm.network "private_network", ip: "192.168.33.200"
    client.vm.provider "virtualbox" do |vb|
      vb.gui = false
      vb.memory = "1024"
    end
  end
end  

With multiple machines we bring up and access them in a slightly different way.

Interacting with the Machines

Bring up the entire environment

$ vagrant up

Note: the following examples refers to what is listed in config.vm.define "SERVER-NAME" Bring up a specific machine.

$ vagrant up <SERVER-NAME>

Connecting to a single machine

$ vagrant ssh <SERVER-NAME>

Destroying a single server

$ vagrant destroy <SERVER-NAME>

Hands On - Extended Vagrant

Let us see if we can do the following. Use this as a template and expand to try out new ideas.
Keep in mind to think about how you would verify each step of your work.

  1. Create a new project directory
  2. Create a multi-machine Vagrant file
    • The machine should be two different operating systems
    • Machine 1 - 192.168.33.100
    • Machine 2 - 192.168.33.200
  3. Configure the shell provisioner to do the following
    • Server 1
      • Configure Apache, PHP, Wordpress
    • Server 2
      • Configure MySQL
  4. Share your Vagrantfile with somebody else and see if they can bring up the same environment.
Here is mine.
# Example Vagrantfile for multiple machines
# This file configures two machines with the hostnames of server and client.

Vagrant.configure(2) do |config|  
  config.vm.define "server" do |server|
    server.vm.box = "centos/6"
    server.vm.hostname = "cent6"
    server.vm.network "private_network", ip: "192.168.33.100"
    server.vm.synced_folder "./", "/var/www/html"
    server.vm.provision "shell", inline: <<-SHELL
        sudo yum update
        sudo yum install -y httpd php php-mysql
    SHELL
    server.vm.provider "virtualbox" do |vb|
      vb.gui = false
      vb.memory = "1024"
    end
  end
  config.vm.define "client" do |client|
    client.vm.box = "centos/7"
    client.vm.hostname = "cent7"
    client.vm.network "private_network", ip: "192.168.33.200"
    client.vm.provider "virtualbox" do |vb|
      vb.gui = false
      vb.memory = "1024"
    end
   client.vm.provision "shell", inline: <<-SHELL
      sudo yum update
      sudo yum install -y mariadb-server
   SHELL
  end
end  

YAY! You made it!

Thank you for taking the time to go through this quick-start tutorial.