Vagrant to Escape Tight Coupling


@bikeonastick

@beckje01


Agenda


  • Who We Are
  • Problem Statement
  • How To Fix the Problem
  • What Tools We Will Use
  • Vagrant 
  • Puppet 
  • Demo 
  • Vagrant Gotchas

Who We Are


Robert Tomb @bikeonastick

He rides his bike everywhere.

Jeff Beck @beckje01

He doesn't own a bike.

We Work At


SOA


Service-oriented architecture - lots of web services.

The Good


  • The system is broken up into smaller code bases.
  • Systems should be interchangeable when the new shiny comes along.
  • Helps to build distributed services.
  • Many other items we don't care to talk about.

The Bad


  • Development dependancies go up.
  • Each system can have very different internal architectures.
  • Good luck setting up local development. 

How to Fix


  • Minimize setup time for local development.
  • Hide system setup from someone running your app locally.
  • Encapsulate services with their dependancies.
  • Script everything.

Tools to Accomplish


Vagrant


Create and configure environments. Bonus they are portable. 

Tools to Accomplish


Puppet


Configuration management so the environment is reproducible.

Vagrant


Install Vagrant

Go to the website use the install for your os. Or use the vagrant gem (not recommended).

This is based on VirtualBox

Vagrant - First Box


vagrant box add ubuntu12 http://files.vagrantup.com/precise64.box
vagrant init
vagrant up

This will give you an ubuntu box that you can ssh into.

vagrant ssh

Vagrant - The FILE


All config is done in a Vagrantfile
Vagrant::Config.run do |config|

  config.vm.box = "ubuntu12"

  # Assign this VM to a host only network IP, allowing you to access it
  # via the IP.
  config.vm.network :hostonly, "10.0.10.34"


  # Forward a port from the guest to the host, which allows for outside
  # computers to access the VM, whereas host only networking does not.
  config.vm.forward_port 8161, 8161
  config.vm.forward_port 6166, 6166
  config.vm.forward_port 6163, 6163
  config.vm.forward_port 8125, 8125, { :protocol => 'udp' }

end

Vagrant - Sharing Folders


You can mount folders from the host computer to the VM.

config.vm.share_folder "minnebar", "~/minnebar", "./minnebar"
Name, Mount Location, Path to Mount

Vagrant Multi VM


Ok that is great but what if I need a datastore server and an web server so it match production.

Vagrant::Config.run do |config|

  config.vm.define :grailsService do |web_config|
    web_config.vm.box = "ubuntu12"
    web_config.vm.network :hostonly, "10.0.10.30"
    config.vm.share_folder "minnebar", "~/minnebar", "./minnebar"
  end

  config.vm.define :redisServer do |redis_config|
    redis_config.vm.box = "ubuntu12"
    redis_config.vm.network :hostonly, "10.0.10.31"
  end
end

Provision the VMs


Ok that is nice but now there is a pile of boxes with nothing on them. We can now tell vagrant to provision the boxes with a number of different tools.

  • Chef Server
  • Chef Solo
  • Puppet Standalone
  • Puppet Server
  • Shell 

Puppet


  config.vm.provision :puppet do |puppet|
    puppet.module_path    = "puppet/modules"
    puppet.manifests_path = "puppet/manifests"
    puppet.manifest_file  = "development.pp"
    #puppet.options = "--verbose --debug"
  end

You can include your manifests and modules into the project. Just use this snip in your vagrant file to let puppet do the work.

Manifest File

node default {
  class { 'vagrant':}

  class  { 'java':
    distribution => 'jdk',
    version      => 'latest',
  }

  package { "unzip":
    ensure => "installed"
  }

  package { "curl":
    ensure => "installed"
  }
}
    
Use this to tell puppet what you want on a box.

Puppet Class


class vagrant {
    exec { 'apt-get update':
		command => '/usr/bin/apt-get update'
	}
}
A simple class that will always make sure everything it up to date before we start installing packages.

Puppet - Order Items


If we need to enforce some order we can do that require.

  exec { 'rvm autolibs 4':
    require => File['/home/vagrant/.rvmrc'],
    command => '/usr/local/rvm/bin/rvm autolibs 4',
    cwd => '/home/vagrant/minnebar',
  }
  exec { 'rvm requirements':
    require => Exec['rvm autolibs 4'],
    command => '/usr/local/rvm/bin/rvm requirements',
    cwd => '/home/vagrant/minnebar',
  }

Puppet


There is much much more, to learn about puppet. Dig in.

DEMO


Grails + Redis

Sinatra - Depends on Above

Vagrant Gotchas


  • .vagrant checked in will mess with things (ghost boxes)
  • When developing a box try both vagrant up / vagrant destroy cycle and vagrant up / vagrant halt
  • vagrant + puppet for ubuntu boxes needs to run apt-get update first
  • With chef + git need all the base folders use .placeholder files to fix this issue.
Made with Slides.com