Study Topic: Vagrant

From Matt Morris Wiki
Jump to navigation Jump to search

This is a Study Leave topic.

What Is It?

From Vagrant Docs V2: Why Vagrant?:

Vagrant provides easy to configure, reproducible, and portable work environments built on top of industry-standard technology and controlled by a single consistent workflow to help maximize the productivity and flexibility of you and your team.

To achieve its magic, Vagrant stands on the shoulders of giants. Machines are provisioned on top of VirtualBox, VMware, AWS, or any other provider. Then, industry-standard provisioning tools such as shell scripts, Chef, or Puppet, can be used to automatically install and configure software on the machine.

Why Study It?

Standard method of provisioning VMs

Toggl code

Toggl code is TECH-VAGRANT

Deliverables

Max 7 hours of time: get something running and see what you can do!

WriteUp

TODO:

  • Look at AWS
  • DONE: Install Vagrant
  • DONE: Install VirtualBox
  • DONE: Get HashiCorp Atlas login (morrism, new)
  • DONE: Initial examples (write up as you do them) in Vagrant Getting Started
  • DONE: Work through "Vagrant: Up and Running"

AWS

Look at How to deploy on Amazon EC2 with Vagrant

Installed AWS plugin:

  • $ vagrant plugin install vagrant-aws

Installation

Don't Use Ruby Gems!

There's a lot of stuff still around saying you should install Vagrant via Ruby Gems but this is out of date! Abandoning RubyGems (21Mar2013) sets out why things have changed: Vagrant was originally packaged as a Ruby Gem, but:

  • This was a barrier to entry for non-Ruby users
  • Not having all dependencies done via the package manager system meant it was less clear what caused any problems with an installation
  • Using the packaging system gave more flexibility and scope for improvement

Installing Vagrant

Nowadays there are packages for Win, OsX, Deb & Rpm. Check the Vagrant downloads page for the latest versions.

For instance, CentOS Installation steps are simple, first download RPM:

Install it:

  • sudo rpm -i vagrant_x.y.z_x86_64.rpm

That’s it! Let’s check to make sure Vagrant works:

  • Command: vagrant -v
  • Result: Vagrant 1.4.2

Installlng VirtualBox

Since VirtualBox is free and is supported out-of-the-box by Vagrant, it's a good thing to download when working through introductory examples.

See VirtualBox downloads for standard stuff.

For instance, for CentOS7, can go through to Linux, then Oracle Linux 7 ("OL7") / Red Hat Enterprise Linux 7 ("RHEL6") / CentOS 7 AMD64, for a final link of http://download.virtualbox.org/virtualbox/4.3.28/VirtualBox-4.3-4.3.28_100309_el7-1.x86_64.rpm

Using Vagrant

Repository

For boxes, see Ashicorp Atlas

Basic Commands

See Vagrant Docs V2: Command Line Interface

I'm running off subdirectories of home/Vagrant, e.g. home/Vagrant/precise32

To set up new instance, change to new directory, then create VagrantFile via

  • $ vagrant init hashicorp/precise32

Starting:

  • $ vagrant up (works even if it has to download everything)
  • $ vagrant resume (only works if was stopped by vagrant suspend)

Stopping:

  • $ vagrant suspend (stores RAM image for quick restart)
  • $ vagrant halt (power down equivalent)
  • $ vagrant destroy (remove all cruft, need to reimport everything if restarting)

To connect

  • $ vagrant ssh

Vagrantfile settings (version 2)

See Vagrant Docs V2: Vagrantfile

  • config.vm.network "forwarded_port", guest : 80, host : 8080 will allow host to access guest port 80 via port 8080

Vagrant will map /vagrant on the VM to the host machine's Vagrantfile directory

  • config.vm.synced_folder ".", "/foo" will change syncing of Vagrantfile folder from '/vagrant" to "/foo"

Sharing

See Vagrant Docs V2: Vagrant Share

When logged in (vagrant login):

  • Http Sharing: you can issue vagrant share to then get a public URL allowing web browser access
  • SSH Sharing: vagrant share --ssh
  • Connect: when using vagrant share, others can then use vagrant connect to access all forwarded ports

Provisioning

See Vagrant Docs V2: Provisioning

"Provisioning" refers to the installation of software on a booted system. Vagrant supports provisioning with shell scripts, Chef or Puppet. The examples here will be from shell scripts, because they are easy to understand and won't bring a whole new system into the mix at this point.

Alternatives to shell scripts:

  • Chef: Chef Solo (for small deployments) or Chef Client (for organisations already with a Chef Server)
  • Puppet: masterless (for small deployments) or Puppet Agent (for organisations already with a Puppet Master)

Shell provisioning can be put inline in the Vagrantfile, or specified in an external script.

Shell Provisioning Example:

Create bootstrap.sh in your Vagrantfile directory:

#!/usr/bin/env bash

apt-get update
apt-get install -y apache2
if ! [ -L /var/www ]; then
  rm -rf /var/www
  ln -fs /vagrant /var/www
fi

Next, we configure Vagrant to run this shell script when setting up our machine. We do this by editing the Vagrantfile, which should now look like this:

Vagrant.configure("2") do |config|
  config.vm.box = "hashicorp/precise32"
  config.vm.provision :shell, path: "bootstrap.sh"
  config.vm.network :forwarded_port, host: 4567, guest: 80
end

Then browsing to http://127.0.0.1:4567 will show the Vagrantfile directory in the web browser - add an index.html to see a page instead of directory contents

Networking

See Vagrant Docs V2: Networking

Port forwarding

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

  • Simple but gets tedious as number of ports increases
  • Host (and other machines on network) can talk to guest, but guest can't talk to host
Host-Only Networking

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

  • Gives the guest an IP that only the host & guests can access
  • Allows host and all guests to interact with each other
  • Host gets IP as set, but with final octet = 1, eg 192.168.33.1
  • It's the best way to work with a multimachine environment that requires the guests to intercommunicate
Bridged Networking

This makes the virtual machine look like a separate physical machine on the main network

config.vm.network "public_network"

  • Fully-fledged network member, which is maximally useful (unless you want isolation)
  • Can't pick the IP as it's served via DHCP, so need to SSH into the guest and get the IP via ifconfig
  • May be no point if the main network router doesn't allow connection between machines
Composing Options

You can set up multiple networks: VirtualBox limit is 8 per guest. These networks can be the same or different types.

The First Network Interface

The first network, generally named "eth0" / "en0", is required to be a NAT (Network Address Translation) device that Vagrant uses for port forwarding: this is how Vagrant gets SSH access to the virtual machine.

Multiple Machines

See Vagrant Docs V2: Multi-Machine

Example:

  config.vm.define "web" do |web|
    web.vm.network "forwarded_port", guest: 80, host: 8080
    web.vm.provision "shell", path: "provision.sh"
    web.vm.provision "shell", inline: "apt-get -y install mysql-client"
    web.vm.network "private_network", ip: "192.168.33.10"
  end
  config.vm.define "db" do |db|
    db.vm.provision "shell", path: "db_provision.sh"
    db.vm.network "private_network", ip: "192.168.33.11"
  end

With db_provision.sh:

export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y mysql-server
sed -i -e 's/127.0.0.1/0.0.0.0/' /etc/mysql/my.cnf
restart mysql
mysql -uroot mysql <<< "GRANT ALL ON *.* TO 'root'@'%'; FLUSH PRIVILEGES;"

All the config.vm settings are inherited, then one can specialise as desired. See the individual network settings.

Vagrant commands now can take arguments if you want to run them on specific machines:

  • $ vagrant reload web
  • $ vagrant up db
  • $ vagrant status web

You can specify multiple machines too:

  • $ vagrant reload db web

Or even use a regular expression (start and end with /)

  • $ vagrant reload /node\d/

Some commands are single-machine only so will now require a parameter:

  • $ vagrant ssh db

Boxes

See Vagrant Docs V2: Boxes

Box data is off ~/.vagrant.d/boxes - so Box info is stored by user rather than by project directory.

To add:

  • $ vagrant box add boxname or url or boxfilepath

To list:

  • $ vagrant box list

To remove (a box is at least 200Meg, can be several Gig):

  • $ vagrant box remove boxname
    • Eg vagrant box remove precise64

To repackage an installed box so can pass boxfile onwards:

  • $ vagrant box repackage boxname provider version

To package a box from the current vagrant instance:

  • $ vagrant package

The Vagrant book has extensive instructions in Chapter 6 about how to produce a box from a VirtualBox image.

PlugIns

See Vagrant Docs V2: PlugIns

Plugins can add new commands, configuration options and provisioners. They can also add or change functionality within existing events (e.g. vagrant up, vagrant destroy). They can also add new guest- or host-specific functionality to help Vagrant work with any operating system.

To install (names refer to gems in the central, official RubyGems repo): $ vagrant plugin install name or gemfilepath To uninstall: $ vagrant plugin uninstall name To show installed: $ vagrant plugin list

Plugins are written in Ruby and packaged as RubyGems.

The definition contains main details: name, contained components. Should not make any Vagrant calls that might expire.

The "Vagrant: Up And Running" book has a lot of detail on how to make plugins - clearly Ruby expertise is necessary.

Environment Variables

  • VAGRANT_CWD: where to look for Vagrantfile (default: cwd)
  • VAGRANT_HOME: where to store global state (default: ~/.vagrant.d)
  • VAGRANT_LOG: log verbosity: debug, info, warn, error. Info most useful generally. (default: none)
  • VAGRANT_NO_PLUGINS: if set to any value, disables plugin load (default: unset)
  • VAGRANT_VAGRANTFILE: filename of Vagrantfile (default: Vagrantfile)

Common Issues

64bit issues

Tried this with precise64 and got the below, might be worth looking at this thread

==> default: Successfully added box 'hashicorp/precise64' (v1.1.0) for 'virtualbox'!
==> default: Importing base box 'hashicorp/precise64'...
==> default: Matching MAC address for NAT networking...
==> default: Checking if box 'hashicorp/precise64' is up to date...
==> default: Setting the name of the VM: Vagrant_default_1434649082545_79341
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 => 2222 (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
The guest machine entered an invalid state while waiting for it
to boot. Valid states are 'starting, running'. The machine is in the                                            
'poweroff' state. Please verify everything is configured                                                        
properly and try again.                                                                                         

If the provider you're using has a GUI that comes with it,                                                      
it is often helpful to open that and watch the machine, since the                                               
GUI often has more helpful error messages than Vagrant can retrieve.                                            
For example, if you're using VirtualBox, run `vagrant up` while the                                             
VirtualBox GUI is open.     

Running VirtualBox and starting in the GUI, get this:

Failed to open a session for the virtual machine Vagrant_default_1434649082545_79341.

VT-x is disabled in the BIOS. (VERR_VMX_MSR_VMXON_DISABLED).

Result Code: NS_ERROR_FAILURE (0x80004005)
Component: Console
Interface: IConsole {8ab7c520-2442-4b66-8d74-4ff1e195d2b6}

The answer is to go into the BIOS (press F12 at boot time) and enable Virtualisation options.