1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
|
** tl;dr
I've been toying with [[http://vagrantup.com/][vagrant]] lately, and it
*really rocks*. You should definitly give it a try. If you're only
looking for some resources to get started with it, go there:
- [[http://docs.vagrantup.com/v2/why-vagrant/][introduction]]
- [[http://groups.google.com/group/vagrant-up][google group]]
** What is Vagrant
"Vagrant is a tool for building and distributing virtualized development
environments." This sentence summarizes perfectly the project.
The idea is to use [[http://www.opscode.com/chef][Chef]] on top of
[[http://www.virtualbox.org/][VirtualBox]] to deploy a VM like you would
deploy a server in your production environment.
I won't go into the details to describe Chef and VirtualBox, but here is
a quick reminder. Chef is a framework to deploy infrastructures. It's
written in ruby, it uses *cookbooks* to describe how to deploy stuff,
and VirtualBox is a virtualization software from Oracle.
#+BEGIN_QUOTE
A little disclaimer. I don't use Chef outside from vagrant, so I may
say/do some stupid things. The aim of this tutorial is not about
writing a recipe for Chef, but to show what you can do thanks to Chef.
So don't hesitate to correct me in the comments if I'm doing some
utterly stupid things.
#+END_QUOTE
** The basic
To install vagrant, you'll need ruby and virtualbox. You have the basic
instructions detailed
[[http://docs.vagrantup.com/v2/getting-started/][here]]. This will
explain how to install vagrant and how to fetch a *base* image.
*** Creating a first project
You'll probably want to start creating a new project now. For this
tutorial, I'll create an image for
[[https://github.com/franckcuny/presque][presque]].
#+BEGIN_SRC sh
% mkdir presque
% vagrant init
#+END_SRC
This will create a new image for your project, and create a new file in
your directory: *Vagrantfile*. Modify this file to make it look like
this:
#+BEGIN_SRC ruby
Vagrant::Config.run do |config|
config.vm.box = "base"
config.vm.provisioner = :chef_solo
config.chef.cookbooks_path = "cookbooks"
config.chef.add_recipe("vagrant_main")
config.vm.forward_port("web", 5000, 8080)
end
#+END_SRC
These instructions will:
- tell vagrant to use the image named *base* (a lucid32 image by
default)
- use chef in *solo* mode
- the recipes will be in a directory named *cookbooks*
- the main recipe will be named *vagrant\_main*
- forward local HTTP port 4000 to 5000 on the VM
*** My recipes
Now we need to create or use some recipes. First we create our
*cookbooks* directory:
#+BEGIN_SRC sh
% mkdir cookbooks
% mkdir -p cookbooks/vagrant_main/recipes
#+END_SRC
We need to add some cookbooks. You will find them on
[[https://github.com/opscode/cookbooks][GitHub]]. Copy the following
cookbooks inside the *cookbooks* repository:
- apt: instructions on how to use apt
- ubuntu: this one manages the sources and executes *apt-get update*
- build-essential: installs the build-essential package
- git: installs git
- perl: configures CPAN
- runit: will be used to monitor redis and our web application
Edit *vagrant\_main/recipes/default.rb* to add them:
#+BEGIN_SRC ruby
require_recipe "ubuntu"
require_recipe "git"
require_recipe "perl"
require_recipe "redis"
require_recipe "runit"
#+END_SRC
If the VM is already started, you can run =vagrant provision= or
=vagrant up=. This will deploy the previous cookbooks on the VM. When
it's done, you can log on the VM with =vagrant ssh=.
You'll need to additional recipes: one for redis; one for presque.
You'll find them on my
[[http://git.lumberjaph.net/chef-cookbooks.git/][GitHub account]]. Copy
the two recipes inside your cookbook directory, and execute
=vagrant provision= to install them.
If everything works fine, you should be able to start using presque.
Test this:
#+BEGIN_SRC sh
% curl http://localhost:8080/q/foo/
{"error":"no job"}
% curl -X POST -H "Content-Type: application/json" -d '{"foo":"bar"}' http://localhost:8080/q/foo/
% curl http://localhost:8080/q/foo/
{"foo":"bar"}
#+END_SRC
If everything is fine, you can shut down the VM with =vagrant halt=.
*** Mounting directories
Instead of pulling from github, you may prefer to mount a local
directory on the VM. For this, you'll need to modifiy the *Vagrantfile*
to add this:
#+BEGIN_SRC sh
config.vm.share_folder "v-code", "/deployment/code", "~/code/perl5"
config.vm.share_folder "v-data", "/deployment/data", "~/code/data"
#+END_SRC
This will mount your local directories *perl5* and *data* under
*/deployment/{code,data}* on the VM. So now you can edit your files
locally and they will be automagically updated on the VM at once.
** and now the awesome part
If you're like me, you may end up with the need to have multiple VMs
which will talk to each other. Common scenarios are a VM with the
website, and another one with the DB, or one VM with a bunch of API
webservices and another with Workers who need to interact with the VM.
Rejoice, this kind of stuff is also handled by vagrant!
Replace the content of the previous *Vagrantfile* with this:
#+BEGIN_SRC ruby
Vagrant::Config.run do |config|
config.vm.box = "base"
config.vm.provisioner = :chef_solo
config.chef.cookbooks_path = "cookbooks"
config.vm.define :presque do |presque_config|
presque_config.chef.add_recipe("vagrant_presque")
presque_config.vm.network("192.168.1.10")
presque_config.vm.forward_port("presque", 80, 8080)
presque_config.vm.customize do |vm|
vm.name = "vm_presque"
end
end
config.vm.define :workers do |workers_config|
workers_config.chef.add_recipe("vagrant_workers")
workers_config.vm.network("192.168.1.11")
workers_config.vm.customize do |vm|
vm.name = "vm_workers"
end
end
end
#+END_SRC
In this configuration, we're creating two VMs, *presque* and *workers*.
You'll need to create two new cookbooks, one for each new VM
(vagrant\_presque, with the same content as vagrant\_main, and
vagrant\_workers, with only the recipe for ubuntu and the instructions
to install curl). Once it's done, boot the two VMs:
#+BEGIN_SRC sh
% vagrant up presque
% vagrant up workers
#+END_SRC
Now let's log on the worker VM
#+BEGIN_SRC sh
% vagrant ssh workers
vagrant@vagrantup:~$ curl http://192.168.1.10:5000/q/foo
{"error":"no job"}
#+END_SRC
and voilà.
** Conclusion
I've started to use vagrant for all my new personal projects and for
most of my stuff at work. I really enjoy using this, as it's easy to
create a cookbook or add one, it's easy to setup a multi VM environment,
you can share a configuration amongst your coworkers, etc.
If you haven't started yet using a VM for your own projects, you really
should give it a try, or use a simple VirtualBox setup. If you want to
read more on the subject, these two blog posts may be relevant:
- [[http://morethanseven.net/2010/11/04/Why-you-should-be-using-virtualisation.html][Why
you should be using virtualisation]]
- [[http://blog.woobling.org/2010/10/headless-virtualbox.html][nothingmuch
setup]]
(oh, and BTW, did you notice that
[[http://search.cpan.org/perldoc?Dancer][Dancer 1.2]] is out ?)
|