-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
executable file
·849 lines (731 loc) · 33.6 KB
/
index.html
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
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>bitHound</title>
<meta name="description" content="">
<meta name="author" content="bitHound">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<link rel="icon" href="img/symbol_colour.png" type="image/x-icon">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="stylesheet" href="css/reveal.min.css">
<link rel="stylesheet" href="css/theme/bithound.css" id="theme">
<!-- For syntax highlighting -->
<link rel="stylesheet" href="lib/css/zenburn.css">
<!-- If the query includes 'print-pdf', use the PDF print sheet -->
<script>
document.write( '<link rel="stylesheet" href="css/print/' + ( window.location.search.match( /print-pdf/gi ) ? 'pdf' : 'paper' ) + '.css" type="text/css" media="print">' );
</script>
<script src="http://localhost:35729/livereload.js?snipver=1"></script>
<!--[if lt IE 9]>
<script src="lib/js/html5shiv.js"></script>
<![endif]-->
</head>
<body>
<div class="reveal">
<!-- Any section element inside of this container is displayed as a slide -->
<div class="slides">
<section class="main-title" data-background="img/symbol_reversed.svg" data-background-size="150%">
<img src="img/fulllogo_reversed.svg" class="simple-img full-logo" />
<h3>The other side of DevOps:</h3>
<h3>Virtualization to support JavaScript Developers</h3>
<p>
<small>Presented by Tony Thompson</small><br />
<a href="https://www.bithound.io">www.bithound.io</a> / <a href="http://twitter.com/bithoundio">@bithoundio</a>
</p>
</section>
<!--
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h2>Who am I?</h2>
<h3><a href="https://www.bithound.io">www.bithound.io</a></h3>
<br>
</section>
-->
<section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h2>DevOps</h2>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>Missing the point...</h3>
<img src="img/devopsjob.png">
<aside class="notes">
I've heard some people describe DevOps as 'sysadmins who program'. And that's
not entirely true. This is from a random devops job posting I found on craigslist.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>DevOps has been around since 1987?</h3>
<img src="img/perl.png">
<aside class="notes">
Sysadmins have been programming since dinosaurs roamed the machine room. Who do you think uses languages like bash or perl or awk?
Either, DevOps has been around since 1987, or it means something more.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<img src="img/catalog.png">
<aside class="notes">
In the 'bad old days', a dev team would finish up, toss a product over the wall to the systems team
who then would then have the curse of deploying it.
<br>
Kind of like acme. Poor Wile E Coyote never knows what he's <em>really</em> going to get next.
<br>
It's not the worst ad. There are plenty of 'Give us the devops. No, we won't
change our procedure' type jobs out there, where the 'hopeful' employer thinks
that devops is just some bandaid they can apply to their current (broken)
process to make it better.
</aside>
</section>
<section data-background="img/dark.gif">
<aside class="notes">
So I guess what I'm trying to say, is that as a DevOps guy, if a dev team comes
to me with a product and says 'deploy this!', it's already too late. We're
going to miss the deadline. This is especially true for node.js/io.js.
Apache/nginx support for js is pretty primitive, and OS distributions lag
badly.
<br>
As somebody with fifteen years of sysadmin experience, I <em>hate</em> running
software that's not well maintained upstream.
<br>
DevOps is a wholistic approach. The goal is to get ahead of mere 'sysadmin'
concerns. And that's not just a matter of applying developer tools to
operations; it's also important to bring operations tools and culture into the
developer world, early in the development process.
</aside>
</section>
</section>
<section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h2>Tools</h2>
<aside class="notes">
We've all gone to a talk about vagrant that ends in "And now you never have to say 'but it runs on my machine'".
<br>
This is not that talk.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<img src="img/acme.jpg">
<aside class="notes">
Really, what you want in a virtualizer from Ops perspective is really the same thing you want in any other software
There's nothing in this talk that couldn't be done in puppet. Or powershell. Or as grunt scripts.
bitHound tends to be a mac/linux shop, and bash is a cheap / fast / universal tool for us.
<br>
I like using tools that let me duct tape together other tools. So bash it is.
<br>
Bash is the Cowbell of DevOps
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<blockquote>
“The only DevOps tool is someone with the title ‘Director of DevOps’.”
<br>
<br>
<div style="float:right">
-- @nathenharvey
</div>
<div style="clear: both"></div>
</blockquote>
<aside class="notes">
At it's heart, DevOps is an approach; a culture. To really do devops right,
your entire organization has to be geared towards building deployable software.
The entire point of DevOps is to not to have silos; there really aren't any
software tools that are DevOps specific. You shouldn't choose new tools
because they are more devops-y. And if your under pressure to use a given tool
'because devops', then something isn't right.
<br>
There is no tool that "gives you devops". However, vagrant and bash are a good place to start.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<ul>
<li>Vagrant</li>
<li>Docker</li>
<li>VirtualBox</li>
<li>VMware</li>
<li>AWS?</li>
</ul>
<aside class="notes">
Really, what you want in a virtualizer from Ops perspective is really the same thing you want in any other software
from a devs perspective. You want something that can be scripted, and is supported in your organization.
</aside>
</section>
</section>
<section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h2>Challenge 1:<br>Virtualization is Slow!</h2>
</section>
<section data-background="img/slow.gif">
<aside class="notes">
Define slow.
<br>
But 'slow' is a pretty vague term. Is it CPU, Network, Storage, Memory constraint.
<br>
I'm going to talk about speed here, but it's a little like talking about the
top speed of a family minivan -- it's missing the point. Ultimately, Speed
isn't the point. Consistency and convention are the points.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<img src="img/64kb.png" alt="">
<a class="small" href="http://mitchellh.com/comparing-filesystem-performance-in-virtual-machines">http://mitchellh.com/comparing-filesystem-performance-in-virtual-machines</a>
<aside class="notes">
Bigger is better. So here you can see that for small files, NFS outperforms VirtualBox native filesystems. And that's actually operating system specific. In our in-house tests, we found we were getting seeing linear performance with file size on linux, and roughly constant time with file size on OS X.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<img src="img/64kb_write.png" alt="">
<a class="small" href="http://mitchellh.com/comparing-filesystem-performance-in-virtual-machines">http://mitchellh.com/comparing-filesystem-performance-in-virtual-machines</a>
<aside class="notes">
But NFS doesn't outperform native when it comes to writes.
So running a virtualized filestem, NFS, or through your virtualizer to the host VM all have different types of performance.
<br>
For example, we have our code mounted in via NFS, but our app's scratch space is on a virtual HD that is not available to the host.
<br>
Benchmark, benchmark, benchmark. Your app is a unique snowflake. Y'know how I know your app is a beautiful unique snowflake?
It's written in javascript, and best practices for deploying javascript are still emerging.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>Some tasks can run on the host</h3>
<pre>
#!/bin/bash
nodemon \
-e js,html,css \
--exec "bash ./restart.sh"
</pre>
<aside class="notes">
Also, it's possible to work around some of these issues. For example, we know file reads are slow, right?
That makes it things like <code>nodemon</code> also very slow.
But we don't have to run it inside the VM. It's not part of our production setup! There's no reason we can't take
that and run it in the host environment. I'll get into where we'd stash this in the next section.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>Tweak your virtualizer</h3>
<pre>
Vagrant.configure(2) do |config|
config.vm.provider :virtualbox do |vb|
vb.cpus = 3
vb.memory = 2048
vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
vb.customize ["modifyvm", :id, "--natdnsproxy1", "on"]
end
end
</pre>
<aside class="notes">
Most VMs can be tuned to meet your needs. Vagrant defualt is (I htink) 512MB of RAM and a single CPU.
<br>
This kind of tuning helps, but regardless, your app will not be as fast inside a virtualizer -- no matter
which one -- as it is on bare metal. But keep in mind, you're almost certainly deploying to a virtualized
environment. Unless you own your own hardware.
</aside>
</section>
</section>
<section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h2>Challenge 2:<br>Virtualization is <em>Not</em> Transparent to Developers</h2>
<aside class="notes">
Not if you have to run scripts inside the environment.
</aside>
</section>
<section data-background="img/popup.gif">
<aside class="notes">
If your app is virtualized, as a dev, you are (naturally) separated from your running code.
Vagrant actually gets us about halfway there -- mounting in <code>/vagrant</code> by default
was a brilliant design decision. It effectively uncouples your editing environment from your
execution environment. You can do that in every other virutalizer, too. But setting
it up takes <em>work</em>.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>Lay out your project</h3>
<pre>
|-- Vagrantfile
|-- Dockerfile
|-- <span style="color: red">app</span>
|-- <em>bin</em>
| |-- start.sh
| +-- stop.sh
|-- etc
+-- <em>scripts</em>
|-- provision.sh
|-- deploy.sh
+-- scripts.sh
</pre>
<aside class="notes">
We actually have two separate places where we keep scripts. Our main repo looks something like this:
<br>
And just to make things difficult, we keep our systems level code in a seperate repo from our actual app.
We include the app as a submodule.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>Lay out your project</h3>
<pre>
|-- Vagrantfile
|-- Dockerfile
|-- app
| |-- <em>bin</em>
| | |-- start.sh
| | +-- stop.sh
| +-- <em>scripts</em>
| +-- migrate.sh
|-- <em>bin</em>
| |-- start.sh
| +-- stop.sh
|-- etc
+-- <em>scripts</em>
|-- provision.sh
|-- deploy.sh
+-- scripts.sh
</pre>
<aside class="notes">
If we pull in that submodule, our directory path looks like this. So scripts
that are in 'app/bin' handle regular operation (e.g. starting, stopping) our
app within the vim. 'bin' handles the same, but from the host. 'bin/scripts'
holds our app specific management scripts and 'scripts' holds our system wide,
common scripts.
<br>
This is our convention. There are many like it, but this works for us at
bitHound. So depending on your path, you can tell if you are trying to
interact from inside or outside the guest.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>Starting and stopping</h3>
<pre>
#!/bin/bash
#start app
vagrant ssh --command "cd /vagrant/app && ./bin/cli server start"
</pre>
<aside class="notes">
So here's a really naive way of starting an app in a vagrant box. This runs, but never comes back.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>Starting and stopping</h3>
<pre>
#!/bin/bash
#start app
vagrant ssh --command "cd /vagrant/app && ./bin/cli server start &"
</pre>
<hr>
<pre>
#!/bin/bash
#start app
vagrant ssh --command "cd /vagrant/app && ./bin/cli server start" &
</pre>
<aside class="notes">
So we can push it into the background, either on the guest or the host, but we don't have a handle or a way to stop or restart the app.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>Starting and stopping</h3>
<pre>
#!/bin/bash
#start app
vagrant ssh --command "cd /vagrant/app; forever --uid 'app' -a start ./bin/cli server start"
</pre>
<hr>
<pre>
#!/bin/bash
#stop app
vagrant ssh --command "forever stop app"
<pre>
<aside class="notes">
And here's a version using 'forever'. It's a JS tool that's a lot like supervisor. It's built to manage
long running processes. E.g.: start, stop, restart. Here, it's running inside the guest, but we're managing it
from the host.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>Passing parameters</h3>
<pre>
#!/bin/bash
vagrant ssh --command "cd /vagrant/app && ./bin/bithound.js $*"
</pre>
<aside class="notes">
Utility / proxy scripts to interact with your project inside the VM. You could call this a trampoline or a thunk, uh,
if you lived through the win16 to win32 transition. (I didn't, but I was just after that and still had to deal
with old developer documentation.
<br>
$* is just the parameter list that this program has been called with itself.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<img src="img/ssh.gif">
<aside class="notes">
So that call took about three seconds to connect to the vagrant guest. And this varies. Docker is pretty much
instantaneous. Most of our tasks are CPU bound, so this usually isn't a critical amount of overhead.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
Vagrant files in particular are just ruby!
<pre>
unless Vagrant.has_plugin?('vagrant-s3auth')
# Attempt to install ourself. Bail out on failure so we don't get
# stuck in an infinite loop.
system('vagrant plugin install vagrant-s3auth') || exit!
# Relaunch Vagrant so the plugin is detected.
# Exit with the same status code.
exit system('vagrant', *ARGV)
end
</pre>
</section>
</section>
<section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h2>Challenge 3:<br>Production <em>will</em> differ</h2>
<aside class="notes">
Different deployment locations in the filesystem. Different users. Different security contexts. Different environments.
</aside>
</section>
<section data-background="img/fridgeski.gif">
<aside class="notes">
Virtualization as tool can give your dev team an approximation of production. It's up to your ops team to make
that approximation as close as possible.
<br>
Ultimately, there is no good answer. Vagrant isn't quite what it says on the label -- you have to be aware of the ways
in which your vagrant environment differs from your production environment.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>Multiple servers</h3>
<pre>
Vagrant.configure(2) do |config|
config.vm.define "app" do |app|
app.vm.box = "trusty64"
app.vm.provision "shell", path: "scripts/provision_app.sh"
app.vm.network "private_network", ip: "10.10.11.11"
end
config.vm.define "worker1" do |worker|
worker.vm.box = "trusty64"
worker.vm.provision "shell", path: "scripts/provision_worker.sh"
worker.vm.network "private_network", ip: "10.10.11.12"
end
config.vm.define "worker2" do |worker|
worker.vm.box = "trusty64"
worker.vm.provision "shell", path: "scripts/provision_worker.sh"
worker.vm.network "private_network", ip: "10.10.11.13"
end
end
</pre>
<aside class="notes">
So if you are building a distributed system, develop on a distributed system! Almost all virtualization environments
right now allow you define multiple VMs and private networks.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>Multiple servers</h3>
<pre>
#!/bin/bash
#start app
vagrant ssh app --command "cd /vagrant/app; forever --uid 'app' -a start ./bin/cli server start"
#start workers
vagrant ssh worker1 --command "cd /vagrant/app; forever --uid 'worker' -a start ./bin/bithound.js worker 10.10.11.11"
vagrant ssh worker2 --command "cd /vagrant/app; forever --uid 'worker' -a start ./bin/bithound.js worker 10.10.11.11"
</pre>
<aside class="notes">
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>SSL</h3>
<pre>
## Do we need fake SSL keys?
ssl_pem=/etc/ssl/private/www_bithound_io.pem
ssl_key=/etc/ssl/private/www_bithound_io.key
ssl_crt=/etc/ssl/private/www_bithound_io.crt
if [ ! -e $ssl_pem ]; then
# No PEM.
if [ ! -e $ssl_key ] || [ ! -e $ssl_crt ]; then
# No keys.
country=CA
state=Ontario
locality=Kitchener
organization=bitHound
name=app.bithound.io
openssl req -x509 \
-newkey rsa:2048 \
-subj "/C=$country/ST=$state/L=$locality/O=$organization/CN=$name" \
-keyout $ssl_key \
-out $ssl_crt \
-days 90 \
-nodes
fi
cat $ssl_crt $ssl_key > $ssl_pem
fi
</pre>
<aside class="notes">
We also deliver everything over SSL. So we do that on our dev boxes too. We autogenerate
SSL certs if there isn't one present already.
<br>
This is useful in other places too. We use Amazon S3 for file storage in production.
We do static analysis of code and generate a lot of data. In development, we use an S3 simulater
called 's3rver' to stand in for S3. Cause it's cheaper to not send that data out
if we don't have to.
</aside>
</section>
</section>
<section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h2>Challenge 4:<br>Provisioning is hard</h2>
</section>
<section data-background="img/paint.gif">
<aside class="notes">
The learning curve for any given configuration management tool is massive.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>Provisioners</h3>
<ul>
<li>Chef</li>
<li>Puppet</li>
<li>Ansible</li>
<li>CFEngine</li>
<li>Cobbler</li>
<li>SaltStack</li>
<li>...</li>
</ul>
<aside class="notes">
Chef, Puppet or Ansible are all pretty heavy for small projects.
If you're already using one, great! Keep it! Don't change unless there's a damn good reason.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>Provisioner features</h3>
<ul>
<li>Configuration Management</li>
<li>Orchestration</li>
<li>Verification / Auditing</li>
</ul>
<aside class="notes">
We only really care about the configuration management part. Our VM environment handles orchestration. And we really
don't care about verification. We're taking a very
If there are changes to the environment that are permanent, they <em>must be scripted and committed</em>. The configuration
as present in version control is the gold standard.
So if you suspect that your dev environment has gone off the rails, but you do have a good provisioning script, don't bother
auditing. Just nuke it from orbit, and create a new one.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>Provisioner features</h3>
<ul>
<li>Configuration Management</li>
<li><strike>Orchestration</strike></li>
<li><strike>Verification / Auditing</strike></li>
</ul>
<aside class="notes">
As long as your provisioner is idempotent, you can provision with just about any tool.
Don't try to modify config files in place. Just check 'em in, and copy them into place.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>Provisioning with bash</h3>
<pre>
#!/bin/bash
BASE='/vagrant'
apt-get update
apt-get install -y build-essential curl git mongodb-clients nginx tmux vim
cp "$BASE/etc/nginx/nginx.conf" /etc/nginx/nginx.conf
/etc/init.d/nginx restart
npm -g install forever
npm -g install nodemon
</pre>
<aside class="notes">
Here's a really early version of our provision script.
<br>
We don't need to template our nginx config because it's pretty simple. Chef recipes
and puppet rules tend to be written to be flexible and generic. And that's
great if your maintaining hundreds of servers each configured slightly differently.
<br>
If you want to configure your servers <em>identically</em> just blind copying a file
is much simpler.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>Provisioning with bash</h3>
<pre>
Vagrant.configure(2) do |config|
config.vm.provision "shell", path: "scripts/provision.sh"
end
</pre>
<aside class="notes">
And then calling a shell provisioner is really simple.
<br>
In real life, we have parameters that we can pass to our provisioning script. We can tell it
what user our app will run as, and what the source and destination paths actually are.
<br>
We actually use the same scripts to provision our dev machines and our production machines.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>Provisioning with bash</h3>
<pre>
FROM ubuntu:1404
RUN scripts/provision.sh
ADD app /app
RUN cd /app && npm install
CMD ["/app/scripts/entrypoint.sh"]
</pre>
<aside class="notes">
Incidently, then you can use the same bash file with Docker.
</aside>
</section>
</section>
<section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h2>Challenge 5:<br>Keeping it going.</h2>
<aside class="notes">
We don't need maintenance because devs regularly destroy and rebuild their vagrant environments, right?
</aside>
</section>
<section data-background="img/catapult.gif">
<aside class="notes">
Just because you've built a virtual dev environment, doesn't mean it will stay
in sync. Your upstream images may change. There will be security updates.
Your own application may change. If you don't regularly rebuild your dev
environment, You will be surprised.
<br>
And that's the best case. If you do a lot of work in a particular guest, your
dev evnironment as running may no longer match your dev environment as spec'd.
If you don't reprovision regularly, you will drift out of sync and lose many of
the benefits of virtualization.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>Why people don't reprovision:</h3>
<ul>
<li>It takes too long.</li>
<li>Reprovisioning fails.</li>
<li>Data loss.</li>
</ul>
<aside class="notes">
You may have to push your developers to remain in sync. They'll probably push back.
Why don't people stay in sync? It takes time. If your provisioning process takes two hours, that's two hours of lost
productivity. If it takes any longer than a coffee break, developers will resist reprovisioning.
Even if it _only_ takes a coffee break, there still will be resistance.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>Why people don't reprovision:</h3>
<ul>
<li>It takes too long.</li>
<li>Reprovisioning fails.</li>
<li><strike>Data loss.</strike></li>
</ul>
<aside class="notes">
We've already talked about data loss... Anything that affects the state of the guest should be checked in.
Fixtures, for example. It's also possible to copy database dumps in and out of a VM.
<br>
I haven't had anybody do this to me about production data yet, it's usually about reproducing test cases.
So 'build fixtures' is usually a reasonable answer.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>Improving provision speed</h3>
<ul>
<li>Examine your provisioner.</li>
<li>Package your code.</li>
<li>Create custom images.</li>
</ul>
<aside class="notes">
Again, benchmark!<br>
We've tested out building custom base boxes in Varnish, and thus far it doesn't seem to help;
We're trading off the time it takes to provision the box against the time it takes to download.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>Reducing failures</h3>
<ul>
<li>Eat your own dogfood.</li>
<li>Provision regularly.</li>
<li>Watch for bitrot.</li>
</ul>
<aside class="notes">
I maintain our dev environment. So whenever I make a new branch, I reprovision. That's at least once a
day, usually two or three times. Part of the job; that could also very easily be automated.
<br>
I have worked with projects where the vagrantfile is poorly maintained. I've even seen some that ship
with a readme file that suggests you run the vagrant file, and then gives a list of manual tasks you
need to complete provisioning.
<br>
Devs need to trust their dev environment.
</aside>
</section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h3>Nag your users</h3>
<img src="img/tests.gif">
<aside class="notes">
On the other hand, trust but verify. It helps to have scripts that check on the host
machine. This one, for example, will not start if the systems code is obviously too old.
Okay, there's a <code>-f</code> option, but my point still stands.
</aside>
</section>
</section>
<section>
<section data-background="img/symbol_reversed.svg" data-background-size="70%" data-background-position="120%">
<h2>Does it work?</h2>
</section>
<section data-background="img/justchecking.gif">
<aside class="notes">
it does for us. this january, we hired two new staff members.
we're a startup. we don't really have a staff onboarding process. it's pretty informal.
so we had brand new still-shrinkwrapped macbook pros. and using the tools that i've outlined in this
talk, both people had a complete -- functional -- dev environment, and had both made (trivial) commits
to our codebase before lunch. including code reviews.
<br>
So it takes time up front. And it you spend a little more time on each pageload in a dev environment.
But what you get for that, is _vastly_ reduced time building dev environments, and easier production.
<br>
You don't get this stuff out of the box by just using Vagrant.
</aside>
</section>
</section>
<section class="main-title" data-background="img/symbol_reversed.svg" data-background-size="150%">
<img src="img/fulllogo_reversed.svg" class="simple-img full-logo" />
<h2>Thank you!</h2>
<h3><a href="https://www.bithound.io">www.bithound.io</a></h3>
<ul>
<li>Tony Thompson (<a href="http://twitter.com/tonious">@tonious</a>)</li>
<li><a href="http://bithound.github.io/2015-jsDay/">http://bithound.github.io/2015-jsDay/</a></li>
</ul>
</br>
</br>
<p>
<small><a href="https://www.bithound.io">www.bithound.io</a> / <a href="http://twitter.com/bithoundio">@bithoundio</a></small>
</p>
</section>
</div>
</div>
<div class="footer">
<!--<img src="img/wordmark_grey_reversed.svg" class="simple-img wordmark" />-->
</div>
<script src="lib/js/head.min.js"></script>
<script src="js/reveal.min.js"></script>
<script>
// Full list of configuration options available here:
// https://github.com/hakimel/reveal.js#configuration
Reveal.initialize({
controls: true,
progress: true,
history: true,
center: true,
theme: Reveal.getQueryHash().theme, // available themes are in /css/theme
transition: Reveal.getQueryHash().transition || 'default', // default/cube/page/concave/zoom/linear/fade/none
// Parallax scrolling
// parallaxBackgroundImage: 'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg',
// parallaxBackgroundSize: '2100px 900px',
// Optional libraries used to extend on reveal.js
dependencies: [
{ src: 'lib/js/classList.js', condition: function() { return !document.body.classList; } },
{ src: 'plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: 'plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: 'plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
{ src: 'plugin/zoom-js/zoom.js', async: true, condition: function() { return !!document.body.classList; } },
{ src: 'plugin/notes/notes.js', async: true, condition: function() { return !!document.body.classList; } }
]
});
</script>
<!-- Live reload -->
</body>
</html>