Vagrant
To avoid any unexpected behavior, your development should resemble your production environment.
That means:
- Run the same OS
- Run the same distribution and version
- Run the same version of Puppet
It is uncommon that your working station is an exact match to your production server. To solve this situation we can use virtualization to provide a host that will match our production server.
Let's take a look at a tool called Vagrant, that will make it easy to manage our VM setup.
Vagrant is a tool that helps us provision and manage VMs. It works with common virtualization tools like Virtualbox, Vmware and Amazon EC2.
The Vagrant site reads "Create and configure lightweight, reproducible, and portable development environments.".
Vagrant accomplished this by:
- Providing a standard way to share base Os boxes.
- Allow your to describe how to provision your VM.
- Mount and sync your local source into the VM.
Installing Vagrant
Vagrant needs a virtualization provider to be able run. The default provider is Virtualbox. If your system doesn't have it installed, go to the Downloads section of the site and get the corresponding installer for your system.
After Virtualbox is intalled go the Downloads section of the Vagrant Site to download and run the appropriate installer for your system.
Starting a Vagrant project
Create a directory where to host your vagrant project or use a directory that contains the source of a current project.
# create a new project
$ mkdir ~/my-vagrant-project
$ cd ~/my-vagrant-project
Vagrant configuration is managed by a Vagrantfile
( read it's documentation ). You can add a basic Vagrantfile
to your project by using the vagrant init
command.
# initialize a Vagrant file
$ vagrant init
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.
Lets take a look at the file we just created. After removing it's comments you can focus on two facts.
First, the Vagrantfile
is a Ruby file, thus its contents can be manipulated just like any Ruby script.
Second, the configure
class method takes arguments that allow us to define the image that our VM should be booted from.
Our default Vagranfile
uses the base
image to boot our VM. This is a place holder were we are expected to set the name of the vagrant box to use.
# a Vagrant file comments removed
$ cat Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure(2) do |config|
config.vm.box = "base"
end
You can find more vagrant boxes with the Hashicorp Atlas tool [1]. This site hosts several officially supported boxes as many custom community maintained boxes. Choose wisely.
Lets re initialize our Vagrantfile
with an Ubuntu 14.04 x64 box.
$ rm Vagrantfile
$ vagrant init ubuntu/trusty64
...
$ cat Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure(2) do |config|
config.vm.box = "ubuntu/trusty64"
end
Now we are ready to provision our VM.
Provisioning
The easiest way to provision a Vagrant box is to use the Shell provisioner.
Uncomment the config.vm.provision
section so your Vagrantfile
so it looks like this:
Vagrant.configure(2) do |config|
config.vm.box = "ubuntu/trusty64"
config.vm.provision "shell", inline: <<-SHELL
sudo apt-get update
sudo apt-get install -y apache2
SHELL
end
The provisioner section will run the first time you start a new system. If it is successful, it will mark the system as provisioned and will not run it again unless your force a re provision.
Starting your box for the first time
Use the vagrant up
command to start your vagrant box and trigger a provisioning event if needed.
$ cd my-vagrant-project
$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'ubuntu/trusty64'...
...
==> default: Forwarding ports...
default: 22 => 2222 (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
default: SSH address: 127.0.0.1:2222
...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
==> default: Mounting shared folders...
default: /vagrant => /Users/jmangt/my-vagrant-project
==> default: Running provisioner: shell...
default: Running: inline script
==> default: stdin: is not a tty
==> default: Ign http://security.ubuntu.com trusty-security InRelease
==> default: Ign http://archive.ubuntu.com trusty InRelease
...
==> default: The following extra packages will be installed:
==> default: apache2-bin apache2-data libapr1 libaprutil1 libaprutil1-dbd-sqlite3
==> default: libaprutil1-ldap ssl-cert
...
==> default: * Starting web server apache2
...
After Vagrant has finished its run you will now have a fully functional Ubuntu server running apache2.
Check the status of your VM
User the vagrant status
command to check the current status of your VM.
$ cd ~/my-vagrant-project
$ vagrant status
Current machine states:
default running (virtualbox)
The VM is running. To stop this VM, you can run `vagrant halt` to
shut it down forcefully, or you can run `vagrant suspend` to simply
suspend the virtual machine. In either case, to restart it again,
simply run `vagrant up`.
SSH into your box
Use the vagrant ssh
to start a remote session into your box.
$ cd ~/my-vagrant-project
$ vagrant ssh
Welcome to Ubuntu 14.04.2 LTS (GNU/Linux 3.13.0-55-generic x86_64)
* Documentation: https://help.ubuntu.com/
System information as of Sat Sep 12 23:51:42 UTC 2015
System load: 0.38 Processes: 80
Usage of /: 3.2% of 39.34GB Users logged in: 0
Memory usage: 25% IP address for eth0: 10.0.2.15
Swap usage: 0%
Graph this data and manage this system at:
https://landscape.canonical.com/
Get cloud support with Ubuntu Advantage Cloud Guest:
http://www.ubuntu.com/business/services/cloud
0 packages can be updated.
0 updates are security updates.
vagrant@vagrant-ubuntu-trusty-64:~$
Networking
If you try to reach the apache2 instance your will find yourself stuck. Vagrant does not provide a simple way to find the ip address of the VM. You can always ssh into the box and run a ifconfig
command to find out.
Private IP address
Use the config.vm.network
property in your Vagrantfile
to setup a private ip address for your VM.
# ~/my-vagrant-project/Vagranfile
...
# Create a private network, which allows host-only access to the machine
# using a specific IP.
config.vm.network "private_network", ip: "192.168.33.10"
...
Port Forwarding
The second change to your Vagrantfile
is to forward a port from your host to the corresponding port 80
in your VM.
# ~/my-vagrant-project/Vagranfile
...
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine. In the example below,
# accessing "localhost:8080" will access port 80 on the guest machine.
config.vm.network "forwarded_port", guest: 80, host: 8080
...
SSH forward keys
Optinally, if you need to clone git repositories via ssh you can configure Vagrant to forward your session's rsa keys.
Add the following to your config.ssh
section.
# ~/my-vagrant-project/Vagranfile
...
config.ssh.forward_agent = true
...
Reload to apply changes
Now, we need to reboot our VM so the changes can take effect.
Use the vagrant reload
command to reboot your VM.
cd ~/my-vagrant-project
vagrant reload
==> default: Attempting graceful shutdown of VM...
...
==> default: Forwarding ports...
default: 80 => 8080 (adapter 1)
...
==> default: Machine already provisioned. Run `vagrant provision` or use the `--provision`
==> default: to force provisioning. Provisioners marked to run always will still run.
All that we have left to do is try our shiny new apache instance.
$ curl 192.168.33.10
In case you wanted other packages, users or directories added to your VM all you need to do is add the corresponding commands to the provision
section and run vagrant reload --provision
for the changes to be applied.
Shared directories
When you start your VM, Vagrant takes care of mounting the directory where your Vagrantfile
resides into the /vagrant
directory inside your VM.
All changes that you make from your host into that directory, will be automatically reflected in the /vagrant
directory inside your VM. This is also true for changes made in the /vagrant
directory inside the VM.
This is a greate feature! Since it allows us to use our favorite text editor in our host to update the code that will be run inside the VM.
Try it! Everybody is doing it...
$ cd ~/my-vagrant-project
$ touch a-new-file.txt
$ ls
Vagrantfile a-new-file.txt
# ssh into the VM
$ vagrant ssh
vagrant:$ cd /vagrant
vagrant:$ ls
Vagrantfile a-new-file.txt
An that is all you need to know to start using Vagrant.
In later chapters we will use this work flow to configure a production like Puppet environment. Stay tuned.
[1] Hashicorp Atlas: https://atlas.hashicorp.com/boxes/search