Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Automate Your World (SFLiveBerlin2013 2013-11-07)

D6ccd6409910643d05ddaea3b2cd6f13?s=47 David Zuelke
November 07, 2013

Automate Your World (SFLiveBerlin2013 2013-11-07)

Presentation given at Symfony Live Berlin 2013 in Berlin, Germany.

D6ccd6409910643d05ddaea3b2cd6f13?s=128

David Zuelke

November 07, 2013
Tweet

Transcript

  1. AUTOMATE YOUR WORLD

  2. David Zülke

  3. None
  4. http://en.wikipedia.org/wiki/File:München_Panorama.JPG

  5. CTO

  6. None
  7. @dzuelke

  8. PART ONE Automate Your World

  9. None
  10. None
  11. AUTOMATE Your Development Environment :)

  12. YOUR OPTIONS For managing your development environments

  13. #1: Russian Roulette

  14. None
  15. None
  16. Not in 2013 anymore, please!

  17. #2: install everything locally on your computer

  18. “it works on my computer”

  19. “I can’t reproduce this”

  20. “Oh, your libunicorns doesn’t have farts enabled”

  21. Developing locally is fast

  22. Developing locally is brittle

  23. #3: all team members work on a test server

  24. None
  25. “I don’t know why it’s not working”

  26. Easy for developers

  27. Too easy for developers

  28. (and slow)

  29. #4: local Virtual Machines

  30. LOCAL VMS ON DEV BOXES • Awesome, because: • Easy

    to manage centrally • Master image, hand out updates • Developers can get up to speed very quickly • Difficult, because: • “I want to use VMware” • “Did you upgrade the machine image?” • “Oh, I think I just forgot to run migrations”
  31. Actual usage of VMs is nice and convenient

  32. “Why do I have to upgrade my VM yet again?”

  33. Management of VMs is hard

  34. ENTER: VAGRANT And all the pain will go away

  35. VAGRANT • Uses “boxes” as base images, provisions them for

    you • Supports Virtualbox, VMware, LXC, AWS, ... • Provision using Shell scripts, Puppet, Chef, ... • Vagrantfile is the recipe for what you’ve built • All developers can easily “vagrant up” the same environment
  36. $  vagrant  init  precise32  http://files.vagrantup.com/precise32.box $  vagrant  up ... $

     vagrant  ssh ... vagrant@precise32:~$
  37. $  vagrant  init $  vagrant  box  add  precise64  http://files.vagrantup.com/precise64.box $

     vagrant  box  add  precise64  http://files.vagrantup.com/precise64_vmware.box $  vagrant  up  -­‐-­‐provider  vmware_fusion ... $  vagrant  ssh ... vagrant@precise64:~$  exit $  vagrant  halt ... $  vagrant  up  -­‐-­‐provider  virtualbox ... $  vagrant  ssh ... vagrant@precise64:~$
  38. $  vagrant  init $  vagrant  box  add  precise64  http://files.vagrantup.com/precise64.box $

     vagrant  box  add  precise64  http://files.vagrantup.com/precise64_vmware.box $  vagrant  up  -­‐-­‐provider  vmware_fusion ... $  vagrant  ssh ... vagrant@precise64:~$  exit $  vagrant  halt ... $  vagrant  up  -­‐-­‐provider  virtualbox
  39. None
  40. None
  41. VAGRANT++ Some more advanced things...

  42. Provision with Chef or Puppet instead of Shell scripts

  43. Build specialized base boxes for faster startup

  44. Smart DNS/hostnames using mDNS/Bonjour with Avahi

  45. MULTIPLE VIRTUAL MACHINES • Run several virtual machines at once

    doing different things • Like you would in production • Example: two web servers, two database servers, one LB • Mimics production characteristics like firewalls and “latency” • Allows easy testing of distributed behavior • Practical limit is 4-6 VMs
  46. Nested VMs

  47. VMware inside VMware

  48. None
  49. Virtualbox inside Virtualbox

  50. None
  51. None
  52. Actually practical: LXC inside VMware!

  53. REAL LIFE An example Vagrantfile

  54. #  -­‐*-­‐  mode:  ruby  -­‐*-­‐ #  vi:  set  ft=ruby  :

    Vagrant.require_plugin('vagrant-­‐hostmanager') Vagrant.require_plugin('vagrant-­‐hostsupdater') $box_use  =  "wheezy" $synced_folder  =  "../" $box_url  =  "..." require  'pathname' if  !File.exists?("#{$synced_folder}")  then    puts  "There  is  no  '#{$synced_folder}'  directory.  Check  '$synced_folder'   setting!"    exit  1 end fox_boxes  =  {    :fox01  =>  {        :hostname  =>  "fox01",        :ipaddress  =>  "192.168.123.11",        :memory  =>  "512"    },    #  :fox02  =>  {    #      :hostname  =>  "fox02",    #      :ipaddress  =>  "192.168.123.13"    #  }, } app_boxes  =  {    :app01  =>  {        :hostname  =>  "app01",        :ipaddress  =>  "192.168.123.12",        :memory  =>  "512"
  55. Vagrant.configure("2")  do  |config|        config.vm.box  =  $box_use  

         config.vm.box_url  =  $box_url        config.vm.synced_folder  $synced_folder,  "/var/www",  :nfs  =>  (RUBY_PLATFORM   =~  /linux/  or  RUBY_PLATFORM  =~  /darwin/)        config.vm.provider  :virtualbox  do  |v,  override|                #  shared  folders  are  shitty  on  virtualbox                override.vm.synced_folder  $synced_folder,  "/var/www",  :nfs  =>   (RUBY_PLATFORM  =~  /linux/  or  RUBY_PLATFORM  =~  /darwin/)        end                config.hostmanager.enabled  =  true        config.hostmanager.manage_host  =  false                config.vm.define  "balancer"  do  |node|                node.vm.provider  "virtualbox"  do  |v|                        v.customize  ["modifyvm",  :id,  "-­‐-­‐memory",  "256"]                end                node.vm.provider  "vmware_fusion"  do  |v|                        v.vmx["memsize"]    =  "256"                end                node.vm.hostname  =  'balancer'                node.vm.network  :private_network,  ip:  "192.168.123.10"                node.hostmanager.aliases  =  ["kiveda.dev",  "www.kiveda.dev"]                node.hostsupdater.aliases  =  ["kiveda.dev",  "www.kiveda.dev"]                node.vm.provision  :puppet  do  |puppet|                        puppet.manifests_path  =  "../puppet-­‐manifests/manifests"                        puppet.module_path  =  "../puppet-­‐manifests/modules"                        puppet.manifest_file  =  "balancer.kiveda.dev.pp"                        puppet.facter  =  {                                "fqdn"  =>  "balancer.kiveda.dev",                                "co_fqdn"  =>  "balancer.kiveda.dev",                                "co_nginx_domain"  =>  "www.kiveda.dev",                                "project_repo_folder"  =>  "fox-­‐skeleton"
  56.        fox_boxes.each_pair  do  |boxname,  boxoptions|      

                 config.vm.define  boxname  do  |node|                    node.vm.provider  :virtualbox  do  |v|                            v.customize  ["modifyvm",  :id,  "-­‐-­‐memory",  boxoptions[:memory]]   unless  !boxoptions[:memory]                    end                    node.vm.provider  :vmware_fusion  do  |v|                            v.vmx["memsize"]    =  boxoptions[:memory]  unless  !boxoptions[:memory]                    end                    node.vm.hostname  =  boxname.to_s                    node.vm.network  :private_network,  ip:  boxoptions[:ipaddress]                    node.hostsupdater.aliases  =  [boxname.to_s+".kiveda.dev"]                    node.vm.provision  :puppet  do  |puppet|                            puppet.manifests_path  =  "../puppet-­‐manifests/manifests"                            puppet.module_path  =  "../puppet-­‐manifests/modules"                            puppet.manifest_file  =  boxname.to_s+".kiveda.dev.pp"                            puppet.facter  =  {                                    "fqdn"  =>  boxname.to_s+".kiveda.dev",                                    "co_fqdn"  =>  boxname.to_s+".kiveda.dev",                                    "co_nginx_domain"  =>  "www.kiveda.dev",                                    "project_repo_folder"  =>  "fox-­‐skeleton"                            }                            puppet.options  =  [  '-­‐-­‐verbose',  '-­‐-­‐debug'  ]                    end            end                end        app_boxes.each_pair  do  |boxname,  boxoptions|                    config.vm.define  boxname  do  |node|                    node.vm.provider  :virtualbox  do  |v|                            v.customize  ["modifyvm",  :id,  "-­‐-­‐memory",  boxoptions[:memory]]  
  57.        app_boxes.each_pair  do  |boxname,  boxoptions|      

                 config.vm.define  boxname  do  |node|                    node.vm.provider  :virtualbox  do  |v|                            v.customize  ["modifyvm",  :id,  "-­‐-­‐memory",  boxoptions[:memory]]   unless  !boxoptions[:memory]                    end                    node.vm.provider  :vmware_fusion  do  |v|                            v.vmx["memsize"]    =  boxoptions[:memory]  unless  !boxoptions[:memory]                    end                    node.vm.hostname  =  boxname.to_s                    if(boxname  ==  :app01)                            node.hostsupdater.aliases  =  [boxname.to_s+".kiveda.dev",   "master.kiveda.dev"]                    else                            node.hostsupdater.aliases  =  [boxname.to_s+".kiveda.dev"]                    end                    node.vm.network  :private_network,  ip:  boxoptions[:ipaddress]                    node.hostsupdater.aliases  =  [boxname.to_s+".kiveda.dev"]                    node.vm.provision  :puppet  do  |puppet|                            puppet.manifests_path  =  "../puppet-­‐manifests/manifests"                            puppet.module_path  =  "../puppet-­‐manifests/modules"                            puppet.manifest_file  =  boxname.to_s+".kiveda.dev.pp"                            puppet.facter  =  {                                    "fqdn"  =>  boxname.to_s+".kiveda.dev",                                    "co_fqdn"  =>  boxname.to_s+".kiveda.dev",                                    "co_apache_domain"  =>  "www.kiveda.dev",                                    "project_repo_folder"  =>  "fox-­‐skeleton"                            }                            puppet.options  =  [  '-­‐-­‐verbose',  '-­‐-­‐debug'  ]                    end            end                end
  58. None
  59. None
  60. “THE WORLD IS NOT ENOUGH”

  61. PART TWO Automate Your Universe

  62. None
  63. Just a few ideas, in no particular order:

  64. #1: goal: re-use puppet/chef from production

  65. #2: Manage staging env through Vagrant and LXC

  66. #3: run CI for your Vagrant boxes

  67. #4: build your own base boxes

  68. http://www.packer.io

  69. does all the heavy lifting, regardless of provider

  70. {    "provisioners":  [        {    

           "type":  "shell",            "scripts":  [                "scripts/update.sh",                "scripts/chef-­‐client.sh",                "scripts/vagrant.sh",                "scripts/networking.sh",                "scripts/sudoers.sh",                "scripts/additional-­‐packages.sh",                "scripts/cleanup.sh",                "scripts/minimize.sh"            ],            "override":  {                "virtualbox":  {                    "execute_command":  "echo  'vagrant'|sudo  -­‐S  bash  '{{.Path}}'"                }            }        }    ],    "post-­‐processors":  [        {            "type":  "vagrant",            "keep_input_artifact":  false        }    ],    "builders":  [        {            "type":  "virtualbox",            "boot_command":  [                "<esc><wait>",                "<esc><wait>",
  71.                "  fb=false<wait>",  

                 "  initrd=/install/initrd.gz<wait>",                "  kbd-­‐chooser/method=us<wait>",                "  keyboard-­‐configuration/layout=USA<wait>",                "  keyboard-­‐configuration/variant=USA<wait>",                "  locale=en_US<wait>",                "  netcfg/get_domain=vm<wait>",                "  netcfg/get_hostname=vagrant<wait>",                "  noapic<wait>",                "  preseed/url=http://{{  .HTTPIP  }}:{{  .HTTPPort  }}/preseed.cfg<wait>",                "  -­‐-­‐  <wait>",                "<enter><wait>"            ],            "boot_wait":  "10s",            "disk_size":  40960,            "guest_os_type":  "Ubuntu_64",            "http_directory":  "http",            "iso_checksum":  "2cbe868812a871242cdcdd8f2fd6feb9",            "iso_checksum_type":  "md5",            "iso_url":  "file:///Users/fh/isos/ubuntu-­‐12.04.3-­‐server-­‐amd64.iso",            "ssh_username":  "vagrant",            "ssh_password":  "vagrant",            "ssh_port":  22,            "ssh_wait_timeout":  "10000s",            "shutdown_command":  "echo  'shutdown  -­‐P  now'  >  shutdown.sh;  echo  'vagrant'| sudo  -­‐S  sh  'shutdown.sh'",            "guest_additions_path":  "VBoxGuestAdditions_{{.Version}}.iso",            "virtualbox_version_file":  ".vbox_version",            "vboxmanage":  [                [                    "modifyvm",                    "{{.Name}}",                    "-­‐-­‐memory",                    "384"                ],
  72. #5: quickly run load tests on AWS

  73. !e End

  74. THANK YOU! This was http://joind.in/9416 by @dzuelke. Questions: dzuelke@gmail.com