Slide 1

Slide 1 text

FULL-STACK CAKEPHP DEPLOYMENT Pay attention to this corner

Slide 2

Slide 2 text

NOT MARKSTORY

Slide 3

Slide 3 text

SPONSORED BY

Slide 4

Slide 4 text

~WHOAMI • Jose Diaz-Gonzalez • Resident IRC Troll (savant) • Rants at http://josediazgonzalez.com • Harasses as @savant • Codes as josegonzalez on github • EMPLOYED at @seatgeek I’m also hot like sriracha sauce ➘ me ➘ not me

Slide 5

Slide 5 text

WHO IS THIS TALK FOR? • Devs/Sysadmins not afraid of Ruby • Developers who don’t have time to waste with sysops • Sysadmins who are looking to automate more of their workflow Also anyone who couldn’t get into Mark’s talk

Slide 6

Slide 6 text

WHY AM I SPEAKING ABOUT THIS? • I’m no Sysadmin; Sysadmining on half of the projects I’m on • Devs do servers wrong; Perhaps I do too • PHPNut Parole Policy (PPP) My Crime: The Patriot Ale House

Slide 7

Slide 7 text

WHAT THE HELL IS THIS • Being lazy • Deploying a SERVAR • CHARGING LAYSHURS • What about the app? ¡¡¡SHOOP DA WOOP!!!

Slide 8

Slide 8 text

IN THE BEGINNING There was PHPNut, and all was good

Slide 9

Slide 9 text

• Geared towards automated deployments of workstations, not servers • Convergence implies we may never be within compliance • Community maintained packages? #  Every  policy  must  have  a  bundlesequence body  common  control { bundlesequence    =>  {  "test"  }; inputs  =>  {  "cfengine_stdlib.cf"  }; } bundle  agent  test { files: #  This  is  a  throw-­‐away  comment,  below  is  a  full-­‐bodied  promise  "/tmp/testfile"                                            #  promiser      comment  =>  "This  is  for  keeps...",  #  Live  comment        create  =>  "true",                                  #  Constraint  1          perms  =>  m("612");                              #  Constraint  2,  rw-­‐-­‐-­‐x-­‐ w-­‐ } I love it when an automation tool makes a promise

Slide 10

Slide 10 text

THINGS WERE COMPLICATE @drunkhulk

Slide 11

Slide 11 text

MODULES AND CLASSES http://forge.puppetlabs.com/ #  ntp-­‐class1.pp class  ntp  {    case  $operatingsystem  {        centos,  redhat:  {              $service_name  =  'ntpd'            $conf_file        =  'ntp.conf.el'        }        debian,  ubuntu:  {              $service_name  =  'ntp'            $conf_file        =  'ntp.conf.debian'        }    }        package  {  'ntp':        ensure  =>  installed,    }        service  {  'ntp':        name            =>  $service_name,        ensure        =>  running,        enable        =>  true,        subscribe  =>  File['ntp.conf'],    }        file  {  'ntp.conf':        path        =>  '/etc/ntp.conf',        ensure    =>  file,        require  =>  Package['ntp'],        source    =>  "/root/learning-­‐manifests/${conf_file}",    } } Free beer to the first person to raise their hand

Slide 12

Slide 12 text

WE CAN DO BETTER If we couldn’t, this would be the end of my talk

Slide 13

Slide 13 text

now we’re cooking!

Slide 14

Slide 14 text

WHY CHEF? • Uses a Ruby DSL; Doesn’t re-invent the wheel • Officially-sanctioned Cookbooks • Community-supported Cookbooks • All the cool rails developers are using it • Awesome logo • Screams when things are broken • Extensive Documentation And the obvious Chef/CakePHP pun

Slide 15

Slide 15 text

HOW IS DEPLOYMENT FORMED? • Each server can have one or more cookbooks • Cookbooks are like plugins (nginx, apache, memcache) that can depend upon/require one another • Cookbooks have recipes, libraries, templates, definitions, files • Recipes are sets of instructions I vote we rename “plugins” to “recipes”

Slide 16

Slide 16 text

git  "#{node[:server][:production][:dir]}/#{hostname}/#{base}/public"  do    repository  info[:repository]    user  "deploy"    group  "deploy" end ➘ ➘ resource name of resource options WHAT’S IN A RESOURCE CALL? http://wiki.opscode.com/display/chef/Resources ➘ special node var ➘

Slide 17

Slide 17 text

ROLL YOUR OWN RESOURCES? Yo dawg, I hurd u liek yo yos so I gave yo dawg a yo yo so yo dawg can yo yo while yo dawg yo yos yo dawg yo

Slide 18

Slide 18 text

#  Definition define  :nginx_up,  :enable  =>  true  do    template  params[:name]  do        source  "html.erb"        owner  "deploy"        group  "deploy"        mode  0644        variables(params[:variables])    end    nginx_site  params[:hostname]  do        action  :enable    end end #  Usage nginx_up  "#{node[:nginx][:dir]}/sites-­‐available/#{hostname}.#{base}"  do    hostname  "#{info[:hostname]}.#{info[:base]}"    variables(info[:variables]) end “Fake” resources, for more info see http://wiki.opscode.com/display/chef/Providers Resources on the Cheap ➘ Just chain resources ➘ Fire at will

Slide 19

Slide 19 text

node[:static_applications].each  do  |hostname,  sites|    sites.each  do  |base,  info|        directory  "#{node[:server][:production][:dir]}/#{hostname}/#{base}"  do                owner  "deploy"                group  "deploy"                mode  "0755"                recursive  true        end        git  "#{node[:server][:production][:dir]}/#{hostname}/#{base}/public"  do            repository  info[:repository]            user  "deploy"            group  "deploy"        end        nginx_up  "#{node[:nginx][:dir]}/sites-­‐available/#{hostname}.#{base}"  do            hostname  "#{hostname}.#{base}"            variables(info[:variables])        end    end end ALL TOGETHER NOW Simplified version of something in production use

Slide 20

Slide 20 text

server  {    listen              80;    server_name    <%=  @subdomain  %><%=  @hostname  %>  www.<%=  @subdomain  %><%=  @hostname  %>;    root                  <%=  @root  %>;    index                index.html  index.htm;    error_page      500  501  502  503  504    /error_500.html;    charset            utf-­‐8;    access_log      <%=  @node[:nginx][:log_dir]  %>/<%=  @subdomain  %><%=  @hostname  %>-­‐access.log;    error_log        <%=  @node[:nginx][:log_dir]  %>/<%=  @subdomain  %><%=  @hostname  %>-­‐error.log;    #  remove  www  from  the  url    if  ($host  ~*  www\.(.*))  {        set  $host_without_www  $1;        rewrite  ^(.*)$  http://$host_without_www$1  permanent;    } } ^ FROM THIS ^ here it comes...

Slide 21

Slide 21 text

server  {    listen              80;    server_name    areyousmokingcrack.com  www.areyousmokingcrack.com;    root                  /apps/production/areyousmokingcrack.com/default;    index                index.html  index.htm;    error_page      500  501  502  503  504    /error_500.html;    charset            utf-­‐8;    access_log      /var/log/nginx/areyousmokingcrack.com-­‐access.log;    error_log        /var/log/nginx/areyousmokingcrack.com-­‐error.log;    #  remove  www  from  the  url    if  ($host  ~*  www\.(.*))  {        set  $host_without_www  $1;        rewrite  ^(.*)$  http://$host_without_www$1  permanent;    } } ^ TO THIS ^ this site actually exists

Slide 22

Slide 22 text

DEMO stop using the internet please

Slide 23

Slide 23 text

SERVER DNA • An instance is defined as a JSON DNA file • dna.json reference both recipes and configurations • Modifying DNA should reconfigure server • DNA can be versioned with the app You too can be a Geneticist

Slide 24

Slide 24 text

BACK TO CAKE? • Define one set of cookbooks, use everywhere • Share, collaborate, grow optimized server cookbooks • Define servers in terms of DNA files: lb.json, db.json, web.json, etc. • Automate server deployment: • server new 127.0.0.1 lb.json • CakePHP http://bit.ly/cakechef Contributions welcome, documentation being fleshed out

Slide 25

Slide 25 text

DEMO you can start using the internet now

Slide 26

Slide 26 text

WHAT ABOUT THE APP? what about it? INCEPTION

Slide 27

Slide 27 text

BASH • Usable everywhere • Easy to read/write • Everything is custom; Don’t be your own giant Have fun handling multiple server types

Slide 28

Slide 28 text

FREDISTRANO NO Never use something just because it’s written in CakePHP

Slide 29

Slide 29 text

PHING NO Yo dawg, I hurd u liek XML

Slide 30

Slide 30 text

ANT I’ll cut you So I put some RDFA in your XML so you can SPARQL while you parse

Slide 31

Slide 31 text

23 DEPLOYMENT TOOLS LATER It’s like deployment tools are project management software, sheesh

Slide 32

Slide 32 text

CAPISTRANO • MOAR Ruby • Similar in concept to Chef - has deployment strategies • Separates related tasks into namespaces (deploy, migration, etc.) • Easy to extend and manipulate • Docs are a bit hazy at the moment • Geared towards SCM users http://capistranorb.com

Slide 33

Slide 33 text

INSTALL • Install Ruby/RubyGems • gem install capistrano • cd path/to/local/app/repository • capify . the other 8 steps of the process involve alcohol

Slide 34

Slide 34 text

CAPIFY? • “capify .” creates a Capfile and a config/deploy.rb file • deploy.rb is by convention; we can move the contents to the Capfile if it bothers you • Capfile is necessary and proper; loads capistrano plugins

Slide 35

Slide 35 text

set  :application,  "set  your  application  name  here" set  :repository,    "set  your  repository  location  here" set  :scm,  :subversion #  Or:  `accurev`,  `bzr`,  `cvs`,  `darcs`,  `git`,  `mercurial`,  `perforce`,  `subversion`  or  `none` role  :web,  “your  web-­‐server  here”                                                    #  Your  HTTP  server,  Apache/etc role  :app,  “your  app-­‐server  here”                                                    #  This  may  be  the  same  as  your  `Web`  server role  :db,    “your  primary  db-­‐server  here”,  :primary  =>  true  #  This  is  where  Rails  migrations  will  run role  :db,    “your  slave  db-­‐server  here” ➘ ➘ ➘ ➘ <3 Perforce CakePHP is cool too Cause we’re all on failover servers, right? milliondollarapp.com deploy.rb

Slide 36

Slide 36 text

CUSTOMIZABLE • Set your own SCM, deploy paths, even callbacks • Define custom namespaces and tasks • Override core functionality

Slide 37

Slide 37 text

ENVIRONMENT HANDLING ##  Available  Environments task  :production  do    server                            $config[“servers”][“prod”][“server”],  :web,  :god    set  :application,      $config[“servers”][“prod”][“application”]    set  :deploy_to,          $config[“servers”][“prod”][“deploy_to”]    set  :branch,                :master end task  :staging  do    role  :web,                    $config[“servers”][“dev”][“server”]    set  :application,      $config[“servers”][“dev”][“application”]    set  :deploy_to,          $config[“servers”][“dev”][“deploy_to”]    set  :branch,                ENV[‘branch’]  if  ENV.has_key?(‘branch’)  &&  ENV[‘branch’]  =~  /[\w_-­‐]+/i end

Slide 38

Slide 38 text

CUSTOM TASKS ##  Tasks  involving  assets namespace  :asset  do    desc  "Clears  assets"    task  :clear  do        run  "cd  #{app_dir}  &&  ../cake/console/cake  -­‐app  #{app_dir}  asset_compress  clear"    end    desc  "Builds  all  assets"    task  :build  do        run  "cd  #{app_dir}  &&  ../cake/console/cake  -­‐app  #{app_dir}  asset_compress  build"    end    desc  "Builds  ini  assets"    task  :build_ini  do        run  "cd  #{app_dir}  &&  ../cake/console/cake  -­‐app  #{app_dir}  asset_compress  build_ini"    end    desc  "Rebuilds  assets"    task  :rebuild  do        run  "cd  #{app_dir}  &&  ../cake/console/cake  -­‐app  #{app_dir}  asset_compress  clear"        run  "cd  #{app_dir}  &&  ../cake/console/cake  -­‐app  #{app_dir}  asset_compress  build"    end end

Slide 39

Slide 39 text

CAP PROD ASSET:REBUILD

Slide 40

Slide 40 text

CAVEATS • Path to Cake Core may be incorrect - use -app flag • Takes some initial setup • Behaves funky with multiple concurrent deploys • Potentially slow with large deploys • Will murder your datacenter if deploying to hundreds of servers

Slide 41

Slide 41 text

CLAP Props to Michael D’Auria, Sysadmin extraordinaire

Slide 42

Slide 42 text

LINKS • CFEngine: • Puppet: http://puppetlabs.com • Chef: http://opscode.com/chef • CakePHP Chef Cookbooks: http://bit.ly/cakechef • Capistrano: http://capistranorb.com