•Environment per project •Dev ~= Test ~= Staging ~= Prod •Easy to define & transport •Easy to tear down •Provisionable: infrastructure as code •Versionable •Shared across the team
$
vagrant
Usage:
vagrant
[-‐v]
[-‐h]
command
[]
!
-‐v,
-‐-‐version
Print
the
version
and
exit.
-‐h,
-‐-‐help
Print
this
help.
! Available
subcommands:
box
destroy
halt
init
package
plugin
provision
reload
resume
ssh
ssh-‐config
status
suspend
up
•Select base box •Choose virtualization provider •Configure VM parameters •Configure networking •Tweak SSH settings •Mount local folders •Provision machine What does a Vagrantfile do?
$
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. #
-‐*-‐
mode:
ruby
-‐*-‐
#
vi:
set
ft=ruby
:
! Vagrant.configure("2")
do
|config|
config.vm.box
=
"base"
end
$
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. #
-‐*-‐
mode:
ruby
-‐*-‐
#
vi:
set
ft=ruby
:
! Vagrant.configure("2")
do
|config|
config.vm.box
=
"precise32"
config.vm.box_url
=
"http:// files.vagrantup.com/precise32.box"
end
$vagrant
up
Bringing
machine
'default'
up
with
'virtualbox'
provider...
[default]
Box
'precise32'
was
not
found.
Fetching
box
from
specified
URL
for
the
provider
'virtualbox'.
Note
that
if
the
URL
does
not
have
a
box
for
this
provider,
you
should
interrupt
Vagrant
now
and
add
the
box
yourself.
Otherwise
Vagrant
will
attempt
to
download
the
full
box
prior
to
discovering
this
error.
Downloading
or
copying
the
box...
Extracting
box...################################################################%
(Rate:
/s,
Estimated
time
remaining:
))
Successfully
added
box
'precise32'
with
provider
'virtualbox'!
[default]
Importing
base
box
'precise32'...
[default]
Matching
MAC
address
for
NAT
networking...
[default]
Setting
the
name
of
the
VM...
[default]
Clearing
any
previously
set
forwarded
ports...
[default]
Creating
shared
folders
metadata...
[default]
Clearing
any
previously
set
network
interfaces...
[default]
Preparing
network
interfaces
based
on
configuration...
[default]
Forwarding
ports...
[default]
-‐-‐
22
=>
2222
(adapter
1)
[default]
Booting
VM...
[default]
Waiting
for
VM
to
boot.
This
can
take
a
few
minutes.
[default]
VM
booted
and
ready
for
use!
[default]
Configuring
and
enabling
network
interfaces...
[default]
Mounting
shared
folders...
[default]
-‐-‐
/vagrant
$
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...
[default]
Clearing
any
previously
set
forwarded
ports...
[default]
Creating
shared
folders
metadata...
[default]
Clearing
any
previously
set
network
interfaces...
[default]
Preparing
network
interfaces
based
on
configuration...
[default]
Forwarding
ports...
[default]
-‐-‐
22
=>
2222
(adapter
1)
[default]
Booting
VM...
[default]
Waiting
for
VM
to
boot.
This
can
take
a
few
minutes.
[default]
VM
booted
and
ready
for
use!
[default]
Configuring
and
enabling
network
interfaces...
[default]
Mounting
shared
folders...
[default]
-‐-‐
/vagrant When VM doesn’t exist
! $
vagrant
up
Bringing
machine
'default'
up
with
'virtualbox'
provider...
[default]
VirtualBox
VM
is
already
running.
$
vagrant
status
Current
machine
states:
! default
running
(virtualbox) When VM exists & is running
$
vagrant
suspend
[default]
Saving
VM
state
and
suspending
execution...
$
vagrant
status
Current
machine
states:
! default
saved
(virtualbox)
$
vagrant
up
Bringing
machine
'default'
up
with
'virtualbox'
provider...
[default]
Resuming
suspended
VM...
[default]
Booting
VM...
[default]
Waiting
for
VM
to
boot.
This
can
take
a
few
minutes.
[default]
VM
booted
and
ready
for
use!
Suspend & resume
$
vagrant
halt
[default]
Attempting
graceful
shutdown
of
VM...
$
vagrant
status
Current
machine
states:
! default
poweroff
(virtualbox)
$
vagrant
up
Bringing
machine
'default'
up
with
'virtualbox'
provider...
[default]
Setting
the
name
of
the
VM...
[default]
Clearing
any
previously
set
forwarded
ports...
[default]
Creating
shared
folders
metadata...
[default]
Clearing
any
previously
set
network
interfaces...
[default]
Preparing
network
interfaces
based
on
configuration...
[default]
Forwarding
ports...
[default]
-‐-‐
22
=>
2222
(adapter
1)
[default]
Booting
VM...
[default]
Waiting
for
VM
to
boot.
This
can
take
a
few
minutes.
[default]
VM
booted
and
ready
for
use!
[default]
Configuring
and
enabling
network
interfaces...
[default]
Mounting
shared
folders...
[default]
-‐-‐
/vagrant
Stop & start
$
vagrant
destroy
Are
you
sure
you
want
to
destroy
the
'default'
VM?
[y/N]
y
[default]
Forcing
shutdown
of
VM...
[default]
Destroying
VM
and
associated
drives...
$
vagrant
status
Current
machine
states:
! default
not
created
(virtualbox) Destroy
$
vagrant
ssh
Linux
debian-‐7
3.2.0-‐4-‐amd64
#1
SMP
Debian
3.2.46-‐1
x86_64
! The
programs
included
with
the
Debian
GNU/Linux
system
are
free
software;
the
exact
distribution
terms
for
each
program
are
described
in
the
individual
files
in
/usr/share/doc/*/copyright.
! Debian
GNU/Linux
comes
with
ABSOLUTELY
NO
WARRANTY,
to
the
extent
permitted
by
applicable
law.
Last
login:
Mon
Jul
15
13:13:36
2013
from
10.0.2.2
[email protected]‐7:~$
sudo
su
[email protected]‐7:/home/vagrant No login or password required
You probably remember this one #
-‐*-‐
mode:
ruby
-‐*-‐
#
vi:
set
ft=ruby
:
! Vagrant.configure("2")
do
|config|
config.vm.box
=
"precise32"
config.vm.box_url
=
"http:// files.vagrantup.com/precise32.box"
end
shell $script
=
<echo
I
am
provisioning...
date
>
/etc/vagrant_provisioned_at
SCRIPT
! Vagrant.configure("2")
do
|config|
config.vm.provision
"shell",
inline:
$script
end Inject Ruby
shell Vagrant.configure("2")
do
|config|
config.vm.provision
"shell",
path:
"script.sh"
end Point to script in your current folder Vagrant.configure("2")
do
|config|
config.vm.provision
"shell",
path:
"https:// example.com/provisioner.sh"
end Point to external script
•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 •... Chef & Puppet
Chef vs Puppet 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-like”
•Download cookbooks (https://github.com/ opscode-cookbooks) •Configure chef.cookbooks_path in Vagrantfile •Add recipes using chef.add_recipe in Vagrantfile •Configure attributes with chef.json •Group custom actions in custom cookbook How to use Chef Solo
MySQL server recipe ...
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
...
[2013-‐10-‐21T10:37:22+00:00]
INFO:
***
Chef
11.4.4
***
[2013-‐10-‐21T10:37:22+00:00]
INFO:
Setting
the
run_list
to
["recipe[project]"]
from
JSON
[2013-‐10-‐21T10:37:22+00:00]
INFO:
Run
List
is
[recipe[project]]
[2013-‐10-‐21T10:37:22+00:00]
INFO:
Run
List
expands
to
[project]
[2013-‐10-‐21T10:37:22+00:00]
INFO:
Starting
Chef
Run
for
debian-‐7.1.0
[2013-‐10-‐21T10:37:22+00:00]
INFO:
Running
start
handlers
[2013-‐10-‐21T10:37:22+00:00]
INFO:
Start
handlers
complete.
[2013-‐10-‐21T10:37:24+00:00]
INFO:
Processing
package[mysql-‐server]
action
install
(project::default
line
1)
[2013-‐10-‐21T10:37:59+00:00]
INFO:
package[mysql-‐server]
sending
start
action
to
service[mysql]
(immediate)
[2013-‐10-‐21T10:37:59+00:00]
INFO:
Processing
service[mysql]
action
start
(project::default
line
10)
[2013-‐10-‐21T10:37:59+00:00]
INFO:
Processing
execute[assign-‐root-‐password]
action
run
(project::default
line
5)
[2013-‐10-‐21T10:37:59+00:00]
INFO:
execute[assign-‐root-‐password]
ran
successfully
[2013-‐10-‐21T10:37:59+00:00]
INFO:
Processing
service[mysql]
action
enable
(project::default
line
10)
[2013-‐10-‐21T10:37:59+00:00]
INFO:
Chef
Run
complete
in
37.208173462
seconds
[2013-‐10-‐21T10:37:59+00:00]
INFO:
Running
report
handlers
[2013-‐10-‐21T10:37:59+00:00]
INFO:
Report
handlers
complete Output
•Download modules (https://github.com/ puppetlabs/) •Configure puppet.module_path, puppet.manifests_path & puppet.manifest_file in Vagrantfile •Provisioning flow happens in the main manifest •Configure attributes with puppet.facter How to use Puppet Apply
[2013-‐10-‐21T10:37:22+00:00]
INFO:
***
Chef
11.4.4
***
[2013-‐10-‐21T10:37:22+00:00]
INFO:
Setting
the
run_list
to
["recipe[project]"]
from
JSON
[2013-‐10-‐21T10:37:22+00:00]
INFO:
Run
List
is
[recipe[project]]
[2013-‐10-‐21T10:37:22+00:00]
INFO:
Run
List
expands
to
[project]
[2013-‐10-‐21T10:37:22+00:00]
INFO:
Starting
Chef
Run
for
debian-‐7.1.0
[2013-‐10-‐21T10:37:22+00:00]
INFO:
Running
start
handlers
[2013-‐10-‐21T10:37:22+00:00]
INFO:
Start
handlers
complete.
[2013-‐10-‐21T10:37:24+00:00]
INFO:
Processing
package[mysql-‐server]
action
install
(project::default
line
1)
[2013-‐10-‐21T10:37:59+00:00]
INFO:
package[mysql-‐server]
sending
start
action
to
service[mysql]
(immediate)
[2013-‐10-‐21T10:37:59+00:00]
INFO:
Processing
service[mysql]
action
start
(project::default
line
10)
[2013-‐10-‐21T10:37:59+00:00]
INFO:
Processing
execute[assign-‐root-‐password]
action
run
(project::default
line
5)
[2013-‐10-‐21T10:37:59+00:00]
INFO:
execute[assign-‐root-‐password]
ran
successfully
[2013-‐10-‐21T10:37:59+00:00]
INFO:
Processing
service[mysql]
action
enable
(project::default
line
10)
[2013-‐10-‐21T10:37:59+00:00]
INFO:
Chef
Run
complete
in
37.208173462
seconds
[2013-‐10-‐21T10:37:59+00:00]
INFO:
Running
report
handlers
[2013-‐10-‐21T10:37:59+00:00]
INFO:
Report
handlers
complete Output
•Provisioning is often slow (especially when installing lots of packages) •Quality of public cookbooks/manifests •Support on cookbooks/manifests •Writing it yourself can be difficult •Some cookbooks/manifests only work on certain Linux distros Problems with provisioning
•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 Re-distribute current VM $
vagrant
package
$
vagrant
up
Bringing
machine
'web'
up
with
'virtualbox'
provider...
Bringing
machine
'db'
up
with
'virtualbox'
provider...
[web]
Importing
base
box
'debian-‐7.1.0'...
[web]
Matching
MAC
address
for
NAT
networking...
[web]
Setting
the
name
of
the
VM...
[web]
Clearing
any
previously
set
forwarded
ports...
[web]
Creating
shared
folders
metadata...
[web]
Clearing
any
previously
set
network
interfaces...
[web]
Preparing
network
interfaces
based
on
configuration...
[web]
Forwarding
ports...
[web]
-‐-‐
22
=>
2222
(adapter
1)
[web]
Booting
VM...
[web]
Waiting
for
VM
to
boot.
This
can
take
a
few
minutes.
[web]
VM
booted
and
ready
for
use!
[web]
Configuring
and
enabling
network
interfaces...
[web]
Mounting
shared
folders...
[web]
-‐-‐
/vagrant
[web]
-‐-‐
/var/www
[web]
-‐-‐
/tmp/vagrant-‐puppet/manifests
[web]
-‐-‐
/tmp/vagrant-‐puppet/modules-‐0
[web]
Running
provisioner:
shell...
[web]
Running:
inline
script
[web]
Running
provisioner:
puppet...
Running
Puppet
with
web.pp...
[db]
Importing
base
box
'debian-‐7.1.0'...
[db]
Matching
MAC
address
for
NAT
networking...
[db]
Setting
the
name
of
the
VM...
[db]
Clearing
any
previously
set
forwarded
ports...
[db]
Fixed
port
collision
for
22
=>
2222.
Now
on
port
2200.
[db]
Creating
shared
folders
metadata...
[db]
Clearing
any
previously
set
network
interfaces...
[db]
Preparing
network
interfaces
based
on
configuration...
[db]
Forwarding
ports...
[db]
-‐-‐
22
=>
2200
(adapter
1)
[db]
Booting
VM...
[db]
Waiting
for
VM
to
boot.
This
can
take
a
few
minutes.
[db]
VM
booted
and
ready
for
use!
[db]
Configuring
and
enabling
network
interfaces...
[db]
Mounting
shared
folders...
[db]
-‐-‐
/vagrant
[db]
-‐-‐
/tmp/vagrant-‐puppet/manifests
[db]
-‐-‐
/tmp/vagrant-‐puppet/modules-‐0
[db]
Running
provisioner:
shell...
[db]
Running:
inline
script
[db]
Running
provisioner:
puppet...
Running
Puppet
with
db.pp...
vagrant
up
vagrant
ssh
vagrant
destroy
vagrant
up
web
vagrant
ssh
web
vagrant
destroy
web
vagrant
up
db
vagrant
ssh
db
vagrant
destroy
db All VM’s Primary VM All VM’s