It works on your machine but not on a team mates? Coding on Windows but deploying to Linux? Or vice versa? Help remove the risk of deployment issues and problems sharing a codebase with your team members and use a project-wide development environment that is easy to manage and quick to install.
9. Environment per project
Dev ~= Test ~= Staging ~= Production
Easy to define & transport
Easy to tear down
Provisionable
Versionable
Shared across the team
10. ➜ ~
Usage: vagrant [options] <command> [<args>]
-v, --version Print the version and exit.
-h, --help Print this help.
vagrant
Common commands:
box manages boxes: installation, removal, etc.
connect connect to a remotely shared Vagrant environment
destroy stops and deletes all traces of the vagrant machine
global-status outputs status Vagrant environments for this user
halt stops the vagrant machine
help shows the help for a subcommand
init initializes a new Vagrant environment by creating a Vagrantfile
login log in to Vagrant Cloud
package packages a running vagrant environment into a box
plugin manages plugins: install, uninstall, update, etc.
provision provisions the vagrant machine
rdp connects to machine via RDP
reload restarts vagrant machine, loads new Vagrantfile configuration
resume resume a suspended vagrant machine
share share your Vagrant environment with anyone in the world
ssh connects to machine via SSH
ssh-config outputs OpenSSH valid configuration to connect to the machine
status outputs status of the vagrant machine
suspend suspends the machine
up starts and provisions the vagrant environment
version prints current and latest Vagrant version
11. For help on any individual command run `vagrant COMMAND -h`
Additional subcommands are available, but are either more
advanced or not commonly used.
To see all subcommands, run the command
`vagrant list-commands`.
13. Select base box
Choose virtualization provider
Configure VM parameters
Configure networking
Tweak SSH settings
Mount local folders
Provision machine
14. ➜ ~
Usage: vagrant init [options] [name [url]]
Options:
-f, --force Overwrite existing Vagrantfile
-m, --minimal Create minimal Vagrantfile (no help comments)
--output FILE Output path for the box. '-' for stdout
-h, --help Print this help
vagrant init -h
➜ ~ 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.
15. 15
Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "base"
end
16. ➜ ~ vagrant init precise32 http://files.vagrantup.com/precise32.box
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.
17. 17
Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "precise32"
config.vm.box_url = "http://files.vagrantup.com/precise32.box"
end
29. ➜ ~ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'precise32'...
==> default: Matching MAC address for NAT networking...
==> default: Setting the name of the VM: test_default_1430903546481_36514
==> 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...
default: SSH address: 127.0.0.1:2222
default: SSH username: vagrant
default: SSH auth method: private key
default: Warning: Connection timeout. Retrying...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
default: The guest additions on this VM do not match the installed version of
default: VirtualBox! In most cases this is fine, but in rare cases it can
default: prevent things such as shared folders from working properly. If you see
default: shared folder errors, please make sure the guest additions within the
default: virtual machine match the version of VirtualBox you have installed on
default: your host and reload your VM.
default:
default: Guest Additions Version: 4.2.0
default: VirtualBox Version: 4.3
==> default: Mounting shared folders...
default: /vagrant => /Users/monkehworks/my_project
30. ➜ ~
Bringing machine 'default' up with 'virtualbox' provider...
==> default: VirtualBox VM is already running.
vagrant up
➜ ~ 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`.
31. ➜ ~
==> default: Saving VM state and suspending execution...
vagrant suspend
➜ ~ vagrant status
Current machine states:
default saved (virtualbox)
To resume this VM, simply run `vagrant up`.
32. ➜ ~ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Resuming suspended VM...
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
default: SSH address: 127.0.0.1:2222
default: SSH username: vagrant
default: SSH auth method: private key
default: Warning: Connection refused. Retrying...
==> default: Machine booted and ready!
33. ➜ ~
==> default: Attempting graceful shutdown of VM...
vagrant halt
➜ ~ vagrant status
Current machine states:
default power (virtualbox)
The VM is powered off. To restart the VM, simply run `vagrant up`.
34. ➜ ~ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> 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...
default: SSH address: 127.0.0.1:2222
default: SSH username: vagrant
default: SSH auth method: private key
default: Warning: Connection timeout. Retrying...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
default: The guest additions on this VM do not match the installed version of
default: VirtualBox! In most cases this is fine, but in rare cases it can
default: prevent things such as shared folders from working properly. If you see
default: shared folder errors, please make sure the guest additions within the
default: virtual machine match the version of VirtualBox you have installed on
default: your host and reload your VM.
default:
default: Guest Additions Version: 4.2.0
default: VirtualBox Version: 4.3
==> default: Mounting shared folders...
default: /vagrant => /Users/monkehworks/my_project
==> default: Machine already provisioned. Run `vagrant provision` or use the `--provision`
==> default: to force provisioning. Provisioners marked to run always will still run.
35. ➜ ~
==> default: Forcing shutdown of VM...
==> default: Destroying VM and associated drives...
vagrant destroy
➜ ~ vagrant status
Current machine states:
default not created (virtualbox)
default: Are you sure you want to destroy the 'default' VM? [y/N] y
The environment has not yet been created. Run `vagrant up` to
create the environment. If a machine is not created, only the
default provider will be shown. So if a provider is not listed,
then the machine is not created for that environment.
37. ➜ ~ vagrant ssh
Welcome to Ubuntu 12.04 LTS (GNU/Linux 3.2.0-23-generic-pae i686)
* Documentation: https://help.ubuntu.com/
New release '14.04.2 LTS' available.
Run 'do-release-upgrade' to upgrade to it.
Welcome to your Vagrant-built virtual machine.
Last login: Wed May 6 13:56:45 2015 from 10.0.2.2
vagrant@precise32:~$ sudo su
root@precise32:/home/vagrant#
52. 52
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "precise32"
config.vm.box_url = "http://files.vagrantup.com/precise32.box"
config.vm.network :private_network, ip: "192.168.10.10"
end
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'precise32'...
==> default: Matching MAC address for NAT networking...
==> default: Setting the name of the VM: test_default_1431011744813_57334
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
default: Adapter 1: nat
default: Adapter 2: hostonly
==> default: Forwarding ports...
default: 22 => 2222 (adapter 1)
➜ ~ vagrant up
53. 53
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "precise32"
config.vm.box_url = "http://files.vagrantup.com/precise32.box"
config.vm.network :private_network, ip: "192.168.10.10"
end
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'precise32'...
==> default: Matching MAC address for NAT networking...
==> default: Setting the name of the VM: test_default_1431011744813_57334
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
default: Adapter 1: nat
default: Adapter 2: hostonly
==> default: Forwarding ports...
default: 22 => 2222 (adapter 1)
➜ ~ vagrant up
54. 54
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "precise32"
config.vm.box_url = "http://files.vagrantup.com/precise32.box"
config.vm.network :forwarded_port, guest: 80, host: 8080
end
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'precise32'...
==> default: Matching MAC address for NAT networking...
==> default: Setting the name of the VM: test_default_1431011744813_57334
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
default: Adapter 1: nat
==> default: Forwarding ports...
default: 80 => 8080 (adapter 1)
default: 22 => 2222 (adapter 1)
➜ ~ vagrant up
55. 55
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'precise32'...
==> default: Matching MAC address for NAT networking...
==> default: Setting the name of the VM: test_default_1431011744813_57334
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
default: Adapter 1: nat
==> default: Forwarding ports...
default: 80 => 8080 (adapter 1)
default: 22 => 2222 (adapter 1)
➜ ~ vagrant up
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "precise32"
config.vm.box_url = "http://files.vagrantup.com/precise32.box"
config.vm.network :forwarded_port, guest: 80, host: 8080
end
56. 56
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "precise32"
config.vm.box_url = "http://files.vagrantup.com/precise32.box"
config.vm.network :public_network
end
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'precise32'...
==> default: Matching MAC address for NAT networking...
==> default: Setting the name of the VM: test_default_1431012579630_44486
==> default: Clearing any previously set network interfaces...
==> default: Available bridged network interfaces:
1) en1: Wi-Fi (AirPort)
2) en0: Ethernet
3) p2p0
default: What interface should the network bridge to?
➜ ~ vagrant up
==> default: Preparing network interfaces based on configuration...
default: Adapter 1: nat
default: Adapter 2: bridged
==> default: Forwarding ports...
1
57. 57
➜ ~ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'precise32'...
==> default: Matching MAC address for NAT networking...
==> default: Setting the name of the VM: test_default_1431012579630_44486
==> default: Clearing any previously set network interfaces...
==> default: Available bridged network interfaces:
1) en1: Wi-Fi (AirPort)
2) en0: Ethernet
3) p2p0
default: What interface should the network bridge to?
==> default: Preparing network interfaces based on configuration...
default: Adapter 1: nat
default: Adapter 2: bridged
==> default: Forwarding ports...
1
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "precise32"
config.vm.box_url = "http://files.vagrantup.com/precise32.box"
config.vm.network :public_network
end
58. 58
➜ ~ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'precise32'...
==> default: Matching MAC address for NAT networking...
==> default: Setting the name of the VM: test_default_1431012579630_44486
==> default: Clearing any previously set network interfaces...
==> default: Available bridged network interfaces:
1) en1: Wi-Fi (AirPort)
2) en0: Ethernet
3) p2p0
default: What interface should the network bridge to?
==> default: Preparing network interfaces based on configuration...
default: Adapter 1: nat
default: Adapter 2: bridged
==> default: Forwarding ports...
1
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "precise32"
config.vm.box_url = "http://files.vagrantup.com/precise32.box"
config.vm.network "public_network", :bridge => 'en1: Wi-‐Fi (AirPort)'
end
74. Written in Ruby
Open source with enterprise revenue model
Similar features
Both have a standalone and server-side edition
Supported by a large community
Modularized components
Use packages for software installs
Use templating for custom files
Filesystem methods
and more…
Chef & Puppet
75. Chef Puppet
Modules Cookbooks Modules
Actions Recipes Manifests
Language Ruby extended with DSL DSL
Running order Sequential “Random”
Approach Define actions Define state
Programming style Procedural “OO-esque”
81. ...
group 'mysql' do
action :create
end
user 'mysql' do
comment 'MySQL Server'
gid 'mysql'
system true
home node['mysql']['data_dir']
shell '/sbin/nologin'
end
node['mysql']['server']['packages'].each do |name|
package name do
action :install
notifies :start, 'service[mysql]', :immediately
end
end
...
MySQL Server Recipe
91. Download modules
- https://forge.puppetlabs.com
Configure in Vagrantfile:
- puppet.module_path
- puppet.manifests_path
- puppet.manifest_file
Provisioning flow happens in the main manifest
Configure attributes with puppet.facter
Using Puppet Apply
92. Vagrantfile
config.vm.provision :puppet do |puppet|
puppet.manifests_path = "./tools/puppet/manifests"
puppet.module_path = "./tools/puppet/modules"
puppet.manifest_file = "init.pp"
puppet.options = ['--verbose']
end
init.pp
include mysql::server
class {
'::mysql::server' :root_password => 'foo'
}
106. Provisioning is often slow
Quality of public cookbooks/manifests
Support on cookbooks/manifests
Writing it yourself can be difficult
Distribution restrictions
108. Possible solution for slow provisioning
Is not the same as vagrant box repackage
Use exported box as new base box
No provisioning required on startup
Possibility of doing “light” provisioning instead
111. VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.provision "shell", inline: "/usr/bin/apt‐get update"
config.vm.box = "debian‐7.1.0"
config.vm.define "web", primary: true do |web|
web.vm.hostname = "web"
web.vm.network :private_network, ip: "192.168.33.10"
web.vm.synced_folder "htdocs/", "/var/www"
web.vm.provision :puppet do |puppet|
puppet.manifests_path = "./tools/puppet/manifests"
puppet.module_path = "./tools/puppet/modules"
puppet.manifest_file = "web.pp"
puppet.options = ['-‐verbose']
end
end
config.vm.define "db" do |db|
db.vm.hostname = "db"
db.vm.network :private_network, ip: "192.168.33.11"
db.vm.provision :puppet do |puppet|
puppet.manifests_path = "./tools/puppet/manifests"
puppet.module_path = "./tools/puppet/modules"
puppet.manifest_file = "db.pp"
puppet.options = ['-‐verbose']
puppet.facter = {
"root_password" => "foo",
}
end
end
112. VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.provision "shell", inline: "/usr/bin/apt‐get update"
config.vm.box = "debian‐7.1.0"
config.vm.define "web", primary: true do |web|
web.vm.hostname = "web"
web.vm.network :private_network, ip: "192.168.33.10"
web.vm.synced_folder "htdocs/", "/var/www"
web.vm.provision :puppet do |puppet|
puppet.manifests_path = "./tools/puppet/manifests"
puppet.module_path = "./tools/puppet/modules"
puppet.manifest_file = "web.pp"
puppet.options = ['-‐verbose']
end
end
config.vm.define "db" do |db|
db.vm.hostname = "db"
db.vm.network :private_network, ip: "192.168.33.11"
db.vm.provision :puppet do |puppet|
puppet.manifests_path = "./tools/puppet/manifests"
puppet.module_path = "./tools/puppet/modules"
puppet.manifest_file = "db.pp"
puppet.options = ['-‐verbose']
puppet.facter = {
"root_password" => "foo",
}
end
end
113.
114.
115. ➜ ~ vagrant up
➜ ~ vagrant destroy
➜ ~ vagrant ssh
➜ ~ vagrant up web
➜ ~ vagrant ssh web
➜ ~ vagrant destroy web
➜ ~ vagrant up db
➜ ~ vagrant ssh db
➜ ~ vagrant destroy db