41
We’re all developers now Adventures in Infrastructure as Code Julian Simpson, The Build Doctor Ltd

Adventures in infrastructure as code

Embed Size (px)

DESCRIPTION

We're all developers now. Infrastructure as code is a new art and science, and we'd all better learn to get past hello world.

Citation preview

Page 1: Adventures in infrastructure as code

We’re all developers now

Adventures in Infrastructure as Code

Julian Simpson, The Build Doctor Ltd

Page 2: Adventures in infrastructure as code

Before we begin

•For gory detail, talk to me at the drinks

•Examples: http://github.com/builddoctor/infrastructure-as-code

•You can ask questions

Page 3: Adventures in infrastructure as code

Poll

•Are you using Puppet or Chef?

•What about Vagrant?

•Do you hate Ruby on Rails?

•Do you hate Apache Ant/NAnt?

Page 4: Adventures in infrastructure as code

Demo

QuickTime™ and aH.264 decompressor

are needed to see this picture.

Page 5: Adventures in infrastructure as code

What just happened?

•We spawned a fresh Ubuntu machine

•and mounted Puppet code

•and executed it

•and tested the desired state of the machine

Page 6: Adventures in infrastructure as code

Vagrant

Page 7: Adventures in infrastructure as code

Examples

Page 8: Adventures in infrastructure as code
Page 9: Adventures in infrastructure as code

Hello Puppet

1 #!/usr/bin/env puppet apply2 3file {4 '/tmp/PuppetHelloWorld':5

content => 'Hello Yow!\n'6 }

Page 10: Adventures in infrastructure as code

Hello Puppet

knox:puppet jsimpson$ ./manifests/classes/01_hello_world.pp warning: Could not retrieve fact fqdnnotice: /Stage[main]//File[/tmp/PuppetHelloWorld]/ensure: defined content as '{md5}54393566ca75844a50baf0c6bccd84b5'notice: Finished catalog run in 0.16 secondsknox:puppet jsimpson$ cat /tmp/PuppetHelloWorld Hello Yow!knox:puppet jsimpson$

Page 11: Adventures in infrastructure as code

Hello Chef

cat -n chef-repo/cookbooks/hello/recipes/default.rb 1 file "/tmp/Chef_Hello_World" do2 content "Hello, world!"3 end

Page 12: Adventures in infrastructure as code

Hello Chef

knox:chef-repo jsimpson$ ./go [Thu, 01 Dec 2011 14:26:46 +1100] INFO: *** Chef 0.10.4 ***[Thu, 01 Dec 2011 14:26:46 +1100] INFO: Setting the run_list to ["recipe[hello]"] from JSON[Thu, 01 Dec 2011 14:26:46 +1100] INFO: Run List is [recipe[hello]][Thu, 01 Dec 2011 14:26:46 +1100] INFO: Run List expands to [hello][Thu, 01 Dec 2011 14:26:46 +1100] INFO: Starting Chef Run for knox[Thu, 01 Dec 2011 14:26:46 +1100] INFO: Processing file[/tmp/Chef_Hello_World] action create (hello::default line 1)[Thu, 01 Dec 2011 14:26:47 +1100] INFO: file[/tmp/Chef_Hello_World] created file /tmp/Chef_Hello_World[Thu, 01 Dec 2011 14:26:47 +1100] INFO: Chef Run complete in 0.084655 seconds[Thu, 01 Dec 2011 14:26:47 +1100] INFO: Running report handlers[Thu, 01 Dec 2011 14:26:47 +1100] INFO: Report handlers complete

Page 13: Adventures in infrastructure as code

1 class nginx::install {2 3 package {4 'nginx':5 ensure => present;6 }7 8 file {9 'default web page':10 path => '/var/www/nginx-default/index.html',11 content => 'This page, courtesy of puppet',12 require => Package['nginx'];13 }14 15 service {16 'nginx':17 ensure => running,18 enable => true,19 hasstatus => true,20 require => [Package['nginx'], File['default web page']];21 }22 23 }24 25 node default {26 include nginx::install27 }

Page 14: Adventures in infrastructure as code

cat -n recipes/default.rb 1 require_recipe "apt"23 package "nginx" do4 action :install5 end6 7 service "nginx" do8 action [:enable, :start]9 end

cat -n config/node.json 1 {2 "run_list": [ 3 "recipe[nginx]"4 ]5 }6

Page 15: Adventures in infrastructure as code

30 class jetty::install {31 include ubuntu::common3233 package {34 'jetty':35 ensure => present,36 require => Class['ubuntu::common'];37 }3839 service {40 'jetty':41 ensure => running,42 enable => true,43 hasstatus => true,44 require => [Package['jetty'], File['/etc/default/jetty']];45 }4647 file {48 '/etc/default/jetty':49 ensure => present,50 content => "51 NO_START=052 VERBOSE=yes53 "54 }55 }

Page 16: Adventures in infrastructure as code

1 require_recipe "apt"2 3 package "jetty" do4 action :install5 end6 7 service "jetty" do8 action [:enable]9 end10 11 file "/etc/default/jetty" do12 mode "0644"13 content "NO_START=0\nVERBOSE=yes\n"14 notifies :restart, resources(:service => "jetty")15 end

Page 17: Adventures in infrastructure as code

1 class corporateapp::install {2 include jetty::install3 include nginx::install4 file {5 'corporate app':6 ensure => file,7 path => '/usr/share/jetty/webapps/app.war',8 source => 'puppet:///modules/corporateapp/app.war',9 require => [Class['jetty::install'], Class['nginx::install']],

notify => Exec['restart jetty'];10 }11 }

Page 18: Adventures in infrastructure as code

1 include_recipe "jetty"2 3 # We do it like this for the example...4 cookbook_file "/usr/share/jetty/webapps/app.war" do5 source "app.war"6 mode "0644"7 end8 9 # In real life I'd do something like...10 #remote_file "/usr/share/jetty/webapps/app.war" do11 # source node[:jetty][:deploy][:source]12 # checksum node[:jetty][:deploy][:checksum] if node[:jetty][:deploy][:checksum]13 # notifies :restart, "service[jetty]"14 #end

Page 19: Adventures in infrastructure as code

├── Gemfile├── Gemfile.lock├── Rakefile├── TODO├── Vagrantfile├── manifests│   ├── classes│   │   ├── 01_hello_world.pp│   │   ├── 02_installed_app_on_nginx.pp│   │   └── 03_installed_app_on_nginx_and_jetty.pp│   └── site.pp└── modules ├── corporateapp │   ├── files │   │   └── app.war │   └── manifests │   └── install.pp ├── jetty │   └── manifests │   └── install.pp ├── nginx │   ├── files │   │   └── nginx_www.corporateapp.com │   └── manifests │   └── install.pp ├── puppet │   └── manifests │   └── fudge.pp └── ubuntu └── manifests └── common.pp15 directories, 16 files

Page 20: Adventures in infrastructure as code
Page 21: Adventures in infrastructure as code

├── config│   ├── node.json│   └── solo.rb├── cookbooks│   ├── apt│   │   └── recipes│   │   └── default.rb│   ├── hello│   │   └── recipes│   │   └── default.rb│   ├── jetty│   │   ├── files│   │   │   └── default│   │   │   └── app.war│   │   └── recipes│   │   ├── default.rb│   │   └── deploy.rb│   └── nginx│   ├── attributes│   │   └── default.rb│   ├── recipes│   │   ├── default.rb│   │   └── loadbalancer.rb│   └── templates│   └── default│   └── lb.erb├── go└── roles └── corporateapp.rb

Page 22: Adventures in infrastructure as code

1 name "corporateapp"2 description "Corporate App Server"3 run_list(4 "recipe[jetty]", 5 "recipe[jetty::deploy]", 6 "recipe[nginx::loadbalancer]"7 )8 9override_attributes(10 "nginx" => {11 "loadbalancer" => {12 "name" => "corporateapp",13 "source" => "http://localhost:8080"14 }15 }, 16 "jetty" => {17 "deploy" => {18 "source" => "http://build-repository/build-number/app.war"19 }20 } 21 )22

Page 23: Adventures in infrastructure as code

History

Page 24: Adventures in infrastructure as code

This isn’t new

Page 25: Adventures in infrastructure as code

domain = ( sequenceapp.com )actionsequence = ( tidy disable resolve filesdirectories copy shellcommands linkseditfiles processes)################################################################################tidy:################################################################################$(sequenceetc) pattern=*.cfsaved age=0!cfmaster::# stops cfservd running on everything except master server/etc/rc2.d/ pattern=S97cfservd age=0# get rid of any hosts.equiv/etc pattern=hosts.equiv age=0 recurse=0homedirs::# no .rhosts files!Hr00::/export/home pattern=.rhosts age=0 recurse=inf

Page 26: Adventures in infrastructure as code

Overview

http://verticalsysadmin.com/blog/uncategorized/relative-origins-of-cfengine-chef-and-puppet

Page 27: Adventures in infrastructure as code

Differences

Page 28: Adventures in infrastructure as code

PuppetPuppet ChefChef

Ruby DSL Ruby DSL

Parsed Internal

Declarative* Imperative*

Configuration Convention

Convergent Congruent

Sysadmins* Developers*

*IMHO

Page 29: Adventures in infrastructure as code

Convergent vs Congruent

Page 30: Adventures in infrastructure as code

“if you want a tool to be congruent, you really have to never re-write history. You have to constantly apply every byte-for-byte change in the same order, on every system you build. Skip a step in history, and everything goes off-kilter”Adam Jacob, 4 Dec

Page 31: Adventures in infrastructure as code

Luke Kanies is here to present on “Essential Incompleteness in Program Modeling”, and starts by getting right into Godel’s Incompleteness Theorem. [it] says that for any system that attempts to model reality (“any sufficiently complex system”), it can never be both consistent and complete.

Page 32: Adventures in infrastructure as code

Declarativevs Imperative

• Declarative programming is a programming paradigm that expresses the logic of a computation without describing its control flow.

• Imperative programming is a programming paradigm that describes computation in terms of statements that change a program state ... imperative programs define sequences of commands for the computer to perform.

Page 33: Adventures in infrastructure as code

Cluster-wide facts

•Chef recipes can access attributes of other nodes

•Puppet can collect node info with stored config

•but ...

Page 34: Adventures in infrastructure as code

Nothing beats realtime

Page 35: Adventures in infrastructure as code

What about ...

Page 36: Adventures in infrastructure as code

Windows?ResourceResource PuppetPuppet ChefChef

File ✔ ✔User ✔ ✔

Group ✔ ✔Scheduled

Task✔ ✔

Service ✔ ✔Exec ✔ ✔Host ✔ ✔

Package(MSI)

✔ ✘

Powershell ✘ ✔

Page 38: Adventures in infrastructure as code

Validating

task :parse_pp do file = File.open("parseonly.pp","w+") Dir.glob('etc/puppet/**/*.pp').each do |manifest| file << "import '#{manifest}'\n"

end sh "bundle exec puppet parser validate parseonly.pp" end

Page 39: Adventures in infrastructure as code

Poll Results

•You might prefer Chef if you get annoyed by Ant’s ‘depends’ model

•You might prefer Puppet if you despise the magic of Ruby on Rails

Page 40: Adventures in infrastructure as code

Disclaimer

•I don’t endorse either tool - you’ll need to make your own decision

•You can really, really screw things up with these tools. Test twice, run once.

Page 41: Adventures in infrastructure as code

Thank you - questions?

•http://github.com/builddoctor/infrastructure-as-code

•@builddoctor

•Much thanks to @cread, @tastapod, @adamgibbins, @puppetmasterd, @adamhjk