Chef Logo

Cooking With Chef

Dan Shultz • OverDrive, Inc

@danshultz

Who Am I

  • 8 Years Writing Web Applications
  • Teacher
  • Write Lots of JavaScript
  • ...and Ruby
  • ...and Python
  • ...occassionaly .NET
  • Server Jugler/Cloud Rider

Do You Server?

Things work in dev but not production?

Abusive by infrastructure team?

Infrastructure upgrades go like this?

Think the cloud will make things better?

to the cloud
Houston, we've got a problem
  • Developers Need to Create Environments
  • Configuration as Documentation
  • Infrastructure as Code
  • Reproducible and Predictible
  • Fast and Responsive

Chef

South Park Chef

System and Cloud Infrastructure Automation Framework

...that makes it easy to deploy servers and applications to any physical, virtual or cloud location, no matter the size of the infrastructure.

Why Chef

Idempotence

Recipe runs of the same configuration always produce the same resolution across systems and chef runs where nothing has changed, take no actions

Reasonable Run Ordering

Chef order is declarative and recipes are run in the order they are declared. Within a recipe, resources are applied in the order they are declared. There is no dependency management system. If you add a new cookbook/recipe at the end of your run list, the run order doesn't change

Easy Configuration/Sane Defaults

Generic Cookbooks work with little or no configuration. Attributes are easily changed and assigned

Extendable

  • Resource
  • Recipe DSLs
  • Light Weight Resource Providers

Getting to Know Chef

Chef Architecture

Chef Server

  • Keeps track of your nodes
  • Serves cookbooks
  • Allows you to search across your nodes
  • Manages node data
Chef Architecture

Chef Client

  • Runs on your nodes
  • Communicates to Chef Server
  • Compiles and Executes Cookbooks
Chef Architecture

Chef Solo

  • Like chef client but...
  • Does not use chef server
  • Does not provide environments
  • It's up to you to get your cookbooks and data to the server

Cookbooks

                % tree cookbooks/mycookbook
    cookbooks/mycookbook
    ├── README.md
    ├── attributes
    ├── definitions
    ├── files
    │   └── default
    ├── libraries
    ├── metadata.rb
    ├── providers
    ├── recipes
    │   └── default.rb
    ├── resources
    └── templates
        └── default
            
          

Recipes

Scripts to install/configure servers and define services

            	package node['nginx']['package_name']

template "nginx.conf" do
  path "#{node['nginx']['dir']}/nginx.conf"
  source "nginx.conf.erb"
  owner "root"
  group "root"
  mode 00644
  notifies :reload, 'service[nginx]'
end

service 'nginx' do
  supports :status => true, :restart => true, :reload => true
  action :enable
end

            

Attributes

Configuration for recipes

              default['nginx']['version'] = "1.2.6"
default['nginx']['package_name'] = "nginx"
default['nginx']['dir'] = "/etc/nginx"
default['nginx']['log_dir'] = "/var/log/nginx"
default['nginx']['binary'] = "/usr/sbin/nginx"
            

The Tools

  • VirtualBox
  • Vagrant
  • Capistrano
  • Community Cookbooks
  • Berkshelf
  • Chef-Solo

Chef Server Need Not Apply

  • Keep Things Simple
  • One Less Dependency
  • Decentralized Server Management

Vagrant for Development

Development environments made easy.

Vagrant for Development

  • Create Local VMs
  • Test Deployments
  • Configured Similar to Production

Installation

  1. Visit Vagrant Website and download vagrant
  2. Install
  3. run `vagrant init`
  4. Update created Vagrantfile
  5. run `vagrant up`

Bootstrap With Capistrano

config/recipes/chef.rb

          	$ cap chef deploy:setup
          

Build on Community Cookbooks

Opscode Community

Cookbooks Are Basic

  • Data/Attribute Driven
  • Basic Case
  • Work out of the box

Create Wapper Cookbooks

  • Don't Fork and Modify Community Cookbooks for Concrete Usage
  • Cookbooks can be versioned, Roles Can't
  • Create App Specific Cookbooks

Rails App Wrapper Cookbook

              % tree rails_app/
rails_app/
├── attributes
├── definitions
├── libraries
├── metadata.rb
├── providers
├── recipes
│   ├── app.rb
│   ├── database.rb
│   ├── default.rb
│   └── web.rb
├── resources
└── templates
    └── default
            └── pg_hba.conf.erb
          	

Example Recipe

          	include_recipe("postgresql")
include_recipe("postgresql::server")
include_recipe("postgresql::ruby")

# use a custom hba_config
hba_conf = resources("template[#{node['postgresql']['dir']}/pg_hba.conf]")
hba_conf.source("pg_hba.conf.erb")
hba_conf.cookbook("rails_app")


postgresql_connection_info = {
  :host => "localhost",
  :port => node['postgresql']['config']['port'],
  :username => 'postgres',
  :password => node['postgresql']['password']['postgres']
}
          
rails_app/recipes/database.rb

Berkshelf to Create Cookbook Scaffolding

            	$ berks cookbook rails_app
            

Berkshelf to Resolve Cookbook Dependencies

Berksfile

              site :opscode
              
cookbook('nginx', '~> 1.7.0')
cookbook('postgresql', '~> 3.0.2')
cookbook('ssh-keys')
cookbook('rails_app', :path => './chef/cookbooks/rails_app')
            

Configure with Chef-Solo

Using Capistrano

              set(:chef_attributes) { File.join('/etc/chef', "attributes.json") }

find_servers.each { |server|
  json = JSON.pretty_generate(server.options[:chef_attributes])
  put(json, chef_attributes, :hosts => server.host)
}
sudo("chef-solo -j #{chef_attributes}")
              
            

config/recipes/chef.rb

Configure with Chef-Solo

Using Capistrano

              $ cap chef deploy
            
Chef Logo

Thank you

Dan Shultz • OverDrive, Inc

@danshultz