Slide 1

Slide 1 text

Application Deployment A set of slides about application deployment with Chef

Slide 2

Slide 2 text

I'm sure most of those millions of pages are legitimate guides to app deployment....

Slide 3

Slide 3 text

Just push to Heroku. Not my problem now...

Slide 4

Slide 4 text

To the cloud!

Slide 5

Slide 5 text

Build your own • Let's be realistic. • You own your availability. There's a number of reasons why you might need to build your own. How many people were affected by the Amazon EC2 reboot crisis?

Slide 6

Slide 6 text

Maybe you want to run your "own heroku"

Slide 7

Slide 7 text

Just like you want to run your own EC2...

Slide 8

Slide 8 text

Now that's settled! Application Deployment approaches

Slide 9

Slide 9 text

how many people have done an application deploy with rsync? cgi-bin, whats up?

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

Package management • Rpm • Deb • Pkgsrc • Gems • Eggs • Not a solved problem. There's a million ways to build packages. It depends on your company's systems, of course, but what if that changes? Many times we just want to put the code on the boxes from the source repository. So why don't we just go directly from source control using a tag/branch?

Slide 12

Slide 12 text

svn up, right? No one ever did this in production

Slide 13

Slide 13 text

Capistrano

Slide 14

Slide 14 text

Which is basically, git clone... I mean, there's more to it than that, but seriously. The problem is this doesn't handle any other configuration that needs to happen. Until you write some code to do that... It also isn't aware of anything else in the infrastructure.

Slide 15

Slide 15 text

git "/srv/blog_app" do repository "git://github.com/me/blog_app.git" reference "master" action :sync end git "/srv/blog_app" do repository "git://github.com/me/blog_app.git" reference "v2.1.3" action :sync end This is a Chef resource for syncing a repository, on master or on a tag/branch reference

Slide 16

Slide 16 text

git "/srv/blog_app" do repository "git://github.com/me/blog_app.git" reference case node.chef_environment when "production" "v2.1.3" else "master" end action :sync end It's an internal Ruby DSL, so we can just use a case statement, too

Slide 17

Slide 17 text

chef-deploy Thanks, Ezra and Engine Yard! Ruby is handy, and makes it easy to extend Chef. Example, Chef deploy is a ruby gem that extended chef by adding a new resource

Slide 18

Slide 18 text

deploy_revision[/srv/blog_app] Later, the chef-deploy gem was ported to the Chef core client library itself. This does capistrano style deployment of the specified revision.

Slide 19

Slide 19 text

deploy_revision "/srv/blog_app" do revision "v2.1.3" repository "git://github.com/me/blog_app.git" user "blog_app" group "www-data" action :deploy end This is continuous deployment. Every time Chef runs, it will deploy the specified revision (say its a branch, or a tag). If the revision is already there, then it takes no further action, it is convergent.

Slide 20

Slide 20 text

application_ruby From Opscode's "application" and "application_ruby" cookbooks

Slide 21

Slide 21 text

application "blog_app" do path "/srv/blog_app" revision "v2.1.3" repository "git://github.com/me/blog_app.git" rails do database do database "blog_app" username "blog_app" password "awesome_password" end database_master_role "blog_app_database_master" end passenger_apache2 do end end Set up a rails app, complete with database.yml, and passenger config

Slide 22

Slide 22 text

application "blog_app" do path "/srv/blog_app" memcached do role "memcached_master" options do ttl 1800 memory 256 end end end Maybe your app needs memcached too?

Slide 23

Slide 23 text

Ad-Hoc Deployment • knife ssh • capistrano • fabric (with pychef) knife ssh "role:appserver" "sudo chef-client"

Slide 24

Slide 24 text

% query="role:blog_app AND chef_environment:production" % knife ssh "${query}" "sudo chef-client" we want to leverage the power of the Chef Server's search feature.

Slide 25

Slide 25 text

require 'chef/knife' require 'chef/search/query' Capistrano::Configuration.instance.load do Chef::Knife.new.configure_chef def chef_role(name, query = "*:*", options = {}) attr = options.delete(:attribute) || :ipaddress nodes = Chef::Search::Query.new.search(:node, query) [0].map {|n| n[attr] } role name, *nodes, options nodes end end https://github.com/cramerdev/capistrano-chef