GeekEvening 0x1E - How To Master Chef

Copyright (C) 2013 - Alca Società Cooperativa


http://learn.alcacoop.it/2013/chef
Copyright (C) 2013 - ALCA Società Cooperativa
GeekEvening 0x1E

Who:

Luca Greco

Where I work: http://alcacoop.it

Where I git push: http://github.com/rpl

What:

HOW TO MASTER

#system_automation

DEVOPS

## devops.rb
require "sysadmin/1.0"
require "sysadmin/2.0/virtualization"
require "sysadmin/2.0/automation"

DEVOPS

NON E' PROPRIO COSI' SEMPLICE...

DEVOPS

Share Coding Best Practices
DVCS, TDD, BDD, CI, ...

DEVOPS

Automated System Configuration
chef, puppet, cfengine, ...

DEVOPS

Automated Infrastructure
CLOUD (AWS, OpenStack, ...)

How to cook a Service

  • Prepare your kitchen
  • Chef Concepts/Patterns

Prepare your kitchen

$ wget [file URL da http://downloads.vagrantup.com]
$ sudo dpkg -i vagrant_1.2.2_x86_64.deb
...

Install VM Providers (VirtualBox)

Vagrant usa VirtualBox come provider multipiattaforma:

$ sudo apt-get install virtualbox

NOTA: virtualbox e kvm non vanno molto daccordo ;-)

Install VM Providers (LXC)

Su Linux è possibile far uso di un provider non ufficiale basato su LXC:

$ sudo apt-get install lxc
...
$ vagrant plugin install vagrant-lxc
...

Vagrantfile

Vagrant.configure("2") do |config|
  config.vm.define :raring64 do |raring_config|
    raring_config.vm.box     = 'raring64'
    raring_config.vm.hostname = "lab-raring64"
­
    raring_config.vm.provider 'virtualbox' do |vm|
      vm.box_url = "http://BOXURL.box"
      vm.customize ['modifyvm', :id, '--memory', '512']
      # vm.gui = true
    end
  end
end

Vagrantfile

Vagrant.configure("2") do |config|
  config.vm.define :raring64 do |raring_config|
    raring_config.vm.box     = 'raring64'
    raring_config.vm.hostname = "lab-raring64"
­
    raring_config.vm.provider 'lxc' do |vm|
      vm.box_url = "http://BOXURL.box"
      vm.customize 'cgroup.memory.limit_in_bytes', '512M'
    end
  end
end

vagrant cli

$ vagrant box add raring64 VBOX_BOX_URL
... # add base raring64 box (virtualbox)
­
$ vagrant box add raring64 LXC_BOX_URL
... # add base raring64 box (lxc)

vagrant cli /2

$ vagrant up raring64 [--provider=lxc]
... # create vm, run provision
­
$ vagrant ssh raring64
... # connect to the defined vm

Vagrantfile - provision shell

Vagrant.configure("2") do |config|
  config.vm.define :raring64 do |raring_config|
    ...
  end
  config.vm.provision :shell, :path => "./prepare.sh"
end

vagrant cli /3

$ vagrant provision raring64
... # rerun defined provisioners
­
$ vagrant reload raring64
... # restart vm and rerun defined provisioners

prepare.sh

which chef-solo || (sudo true && \
  curl -L https://www.opscode.com/chef/install.sh | \
  sudo bash)

prepare.sh

which chef-solo || (sudo true && \
  curl -L https://www.opscode.com/chef/install.sh | \
  sudo bash)

prepare.sh

which chef-solo || (sudo true && \
  curl -L https://www.opscode.com/chef/install.sh | \
  sudo bash)

Chef

  • Cookbook (es. my_project/):
    • Metadata (my_project/metadata.rb)
    • Recipes (my_project/recipes/*.rb)
    • Attributes (my_project/attributes/*.rb)
    • Files (my_project/files/**)
    • Templates (my_project/templates/**)

Cookbook metadata.rb

name         "my_project"
maintainer       "Luca Greco"
maintainer_email "luca.greco@alcacoop.it"
license          "GPLv3"
description      "my project cookbook"
long_description "..."
version      "0.0.1"

Cookbook Recipes

  • Cookbook Recipes:
    • my_project::www (my_project/recipes/www.rb)
    • my_project::db (my_project/recipes/db.rb)
    • my_project::mail (my_project/recipes/mail.rb)

Recipe DSL

  • Resources:
    • package
  • Providers:
    • apt_package
    • rpm_package
    • solaris_package

Recipe DSL /2

http://docs.opscode.com/chef/resources.html

package, script, template, file, cookbook_file, template_file, remote_file, directory, scm, git, subversion, service, mount, cron, ...

Recipe DSL /3

# Cookbook Name:: my_project
# Recipe:: www_dependencies
­
package 'ruby'
package 'rubygems'
­
gem_package 'bundler'

Recipe DSL /4

# Cookbook Name:: my_project
# Recipe:: www_deploy
­
bash 'my_project_bundle_install' do
  user 'root'
  pwd  '/srv/app_name'
  code <<-EOC
    bundle install
  EOC
  action :nothing
end
...

Recipe DSL /5

...
git "/srv/app_name" do
  repository node[:app_name][:git_repository]
  reference node[:app_name][:git_revision]
  action :sync
  notifies :run, "bash[my_project_bundle_install]"
end
...

Recipe DSL /6

...
cookbook_file "/etc/myapp-monitor/notifications.yml" do
  source "notifications.yml"
end
...
  • my_project/files/ubuntu-13.04/notifications.yml
  • my_project/files/ubuntu/notifications.yml
  • my_project/files/default/notifications.yml

Recipe DSL /7

...
template_file "/srv/app_name/config/database.yml" do
  source "database.yml.erb"
  variables(
   :db_address => node[:app_name][:db_address]
  )
end
...

Recipe DSL /7

  • my_project/templates/ubuntu-13.04/database.yml.erb
  • my_project/templates/ubuntu/database.yml.erb
  • my_project/templates/default/database.yml.erb

Template

production:
  adapter: mysql
  database: my_project
  host: <%= @db_address %>
  username: user
  password: ****
  pool: 5
  timeout: 5000

Cookbook Attributes

my_projects/attributes/www.rb:

default[:app_name][:db_address] = '127.0.0.1'
default[:app_name][:git_repository] = '...'
default[:app_name][:git_revision] = '...'

Chef-Solo vs. Chef-Client

Chef-Solo vs. Chef-Client

Vagrantfile - chef-solo provisioner

...
  config.vm.provision :chef_solo do |chef|
    chef.provisioning_path = '/etc/vagrant-chef'
    # chef.log_level         = :info
    chef.run_list = %w[
      my_project::www
      my_project::db
      my_project::email
    ]
...

Vagrantfile - chef-solo provisioner

...
    chef.json = {
      app_name: {
        git_repository: '...',
        git_revision: '...'
      }
    }
...

Berkshelf


Manage a Cookbook or an Application's Cookbook dependencies

Cookbook dependencies

name         "my_project"
maintainer       "Luca Greco"
maintainer_email "luca.greco@alcacoop.it"
license          "GPLv3"
description      "my project cookbook"
long_description "..."
version      "0.0.1"
­
depends 'apache2', "= 1.6.2"

Cookbook dependencies

Berksfile

site :opscode
­
### dependencies auto-recognized from metadata and
### downloaded by opscode community cookbooks site.
metadata
­
### or from a path / git repository:
# cookbook "apache2",
#          :path => '../my_temporary_apache2_fork'
# cookbook "apache2",
#          :git => "GIT REPO URL",
#          :branch => GIT_BRANCH_NAME"

Vagrant berkshelf plugin

$ vagrant plugin install vagrant-berkshelf
...
$ vagrant up --provider=lxc
[sudo] password for rpl:
Bringing machine 'raring64' up with 'lxc' provider...
[raring64] Importing base box 'raring64'...
[Berkshelf] Updating Vagrant's berkshelf: '~/.berkshelf...
[Berkshelf] Using minitest-handler (0.2.0)
[Berkshelf] Using my_project (0.0.1) at path: '/my_project'
[Berkshelf] Using chef_handler (1.1.4)
[Berkshelf] Using openssh (1.1.4)
...

Vagrant berkshelf plugin

...
[raring64] Setting up mount entries for shared folders...
[raring64] -- /vagrant
[raring64] -- /etc/vagrant-chef/chef-solo-1/cookbooks
[raring64] Starting container...
[raring64] Waiting for container to start. This should not...
...

Ricapitolando

  • Vagrant: automated crossplatform test/dev VM definitions

e dopo? molto molto altro

  • cookbook planning, development and testing
  • continuous integration/building
  • automated bootstrap
  • LWRP (lightweight resources & providers)
  • chef server management
  • automated infastructure / cloud
  • ligthweight system containers (e.g. LXC)

Happy Cooking with Chef!

http://learn.alcacoop.it/2013/chef

Copyright (C) 2013 - ALCA Società Cooperativa
Released under CC 3.0 by-nc-sa