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

Getting Started with Chef for Rails

Getting Started with Chef for Rails

Presentation given at the Northern Virginia Ruby Users Group.

Overview of Chef
Building a project in Chef
Provision a Server for Your Rails App
Additional resources

Avatar for Nathen Harvey

Nathen Harvey

January 29, 2013
Tweet

More Decks by Nathen Harvey

Other Decks in Technology

Transcript

  1. The Joy of Cooking: Whip up a Rails Environment with

    Chef Nathen Harvey @nathenharvey Northern Virginia Ruby Users Group
  2. Nathen • Technical Community Manager, Opscode • Co-organizer • DevOpsDC

    • MongoDC • Formerly - Web Operations at CustomInk
  3. Agenda • Overview of Chef • Building a project in

    Chef • Provision a Server for Your Rails App • Additional resources • Obligatory Shameless Plugs • Please Ask Questions Along the Way
  4. Evolution of Configuration Management • Just build it • Keep

    notes in server.txt • Move notes to the wiki • Custom scripts (in scm?!) • Configuration Management framework
  5. Collection of Resources • Nodes • Networking • Files •

    Directories • Symlinks • Mounts • Routes • Users • Groups • Tasks • Packages • Software • Services • Configurations • Stuff http://www.flickr.com/photos/stevekeys/3123167585/
  6. App LB App Servers App DB Cache App DBs Floating

    IP? Your Infrastructure is a snow flake
  7. App LBs App Servers NoSQL DB slaves Cache DB Cache

    DBs Complexity increases quickly
  8. Golden Images are not the answer • Gold is heavy

    • Hard to transport • Hard to mold • Easy to lose configuration detail http://www.flickr.com/photos/garysoup/2977173063/
  9. Rails App Memcache Postgres Slaves Postgres Master New Compliance Mandate

    Nagios Graphite • Move SSH off port 22 • Lets put it on 2022
  10. Rails App Memcache Postgres Slaves Postgres Master 6 Golden Image

    Updates Nagios Graphite • edit /etc/ssh/sshd_config 1 2 3 4 5 6
  11. Rails App Memcache Postgres Slaves Postgres Master 12 Instance Replacements

    Nagios Graphite • Delete, launch 1 2 3 4 5 6 7 8 9 10 11 12 • Repeat • Typically manually
  12. Done in Maintenance Windows • Don’t break anything! • Bob

    just got fired =( 5 Rails App Memcache Postgres Slaves Postgres Master Nagios Graphite 1 2 4 5 6 7 8 9 10 11 12 3
  13. • Generate configurations directly on nodes • Reduce management complexity

    • Version control the programs http://www.flickr.com/photos/ssoosay/5126146763/ Programs!
  14. Declarative Interface to Resources • Define policy • Say what,

    not how • Pull not Push http://www.flickr.com/photos/bixentro/2591838509/
  15. Chef is Infrastructure as Code http://www.flickr.com/photos/louisb/4555295187/ • Programmatically provision and

    configure • Treat like any other code base • Reconstruct business from code repository, data backup, and bare metal resources.
  16. package "ntp" do action :install end service "ntpd" do action

    [:enable,:start] end template "/etc/ntpd.conf" do source "ntpd.conf.erb" owner "root" group "root" mode 0644 action :create variables(:time_server => “time.example.com”) notifies :restart, “service[ntpd]” end That looks like this
  17. Nagios Graphite Count the resources Rails App Memcache Postgres Slaves

    • Load balancer config • Nagios host ping • Nagios host ssh • Nagios host HTTP • Nagios host app health • Graphite CPU • Graphite Memory • Graphite Disk • Graphite SNMP • Memcache firewall • Postgres firewall • Postgres authZ config • 12+ resource changes for 1 node addition
  18. Building a Project in Chef OK, so how do I

    build something with Chef?
  19. Building a Chef Project • First, come up with your

    policy / specification • Abstract the resources in your spec
  20. Resources package "tmux" do action :install end directory "/u/apps/awesome" do

    owner "apache" group "apache" action :create recursive true end
  21. Building a Chef Project • First, come up with your

    policy / specification • Abstract the resources in your spec • Write recipes
  22. Recipe include_recipe "app_user" app_name = node["app_name"] app_user = node["app_user"] app_group

    = node["app_group"] %w(releases shared).each do |dir| directory "/u/apps/#{app_name}/#{dir}" do mode "0755" owner app_user group app_group recursive true end end
  23. Building a Chef Project • First, come up with your

    policy / specification • Abstract the resources in your spec • Write recipes • Package recipes in cookbooks
  24. Cookbooks |-- ldirectord | |-- README.md | |-- attributes |

    | `-- default.rb | |-- metadata.rb | |-- recipes | | `-- default.rb | `-- templates | `-- default | `-- site.cf.erb
  25. Cookbooks |-- monit | |-- README.md | |-- attributes |

    | `-- default.rb | |-- files | | `-- ubuntu | | `-- monit.default | |-- metadata.rb | |-- recipes | | `-- default.rb | `-- templates | `-- default | `-- monitrc.erb
  26. Recipes and Cookbooks • Recipes are collections of Resources •

    Cookbooks contain recipes, templates, files, custom resources, etc • Code re-use and modularity http://www.flickr.com/photos/shutterhacks/4474421855/
  27. Building a Chef Project • First, come up with your

    policy / specification • Abstract the resources in your spec • Write recipes • Package recipes in cookbooks • Apply recipes to nodes
  28. Nodes • Representation of a host • runs the Chef

    client • has attributes • has a list of recipes to be applied
  29. Building a Chef Project • First, come up with your

    policy / specification • Abstract the resources in your spec • Write recipes • Package recipes in cookbooks • Apply recipes to nodes • Group things into roles
  30. Roles • mechanism for easily composing sets of functionality •

    have attributes and a list of recipes to be applied
  31. Run Lists Server Server Server Server chef-server API chef-client “role[base]”,

    “role[my_awesome_app]” node ntp default.rb sudo default.rb rails_app default.rb
  32. Server Server Server Server chef-server API chef-client “role[webserver]” node ntp

    client.rb openssh server.rb apache default.rb rails_app default.rb Roles chef-client “role[database]” node ntp client.rb openssh server.rb postgresql server.rb
  33. Roles name "base" description "Base of all nodes" default_attributes( "newrelic"

    => { "license_key" => "cbb1f5..." } ) run_list( "recipe[base_config]", "recipe[users]", "recipe[groups]", "recipe[sudo]" )
  34. Building a Chef Project • First, come up with your

    policy / specification • Abstract the resources in your spec • Write recipes • Package recipes in cookbooks • Apply recipes to nodes • Group things into roles
  35. © Opscode, 2011 – Confidential – DO NOT DISTRIBUTE Chef

    Provides a Model for Reuse That Works 64 700+ Cookbooks “Yesterday we started open sourcing some of our Opscode Chef work created at bestbuy.com; bit.ly/ yDV9Hl #Splunk #opschef #expectmor”
  36. Knife • Chef’s secret weapon • Command-line interface for interacting

    with • Chef Server API • Local Chef Repository • Community Site • and more...
  37. Create a Cookbook $ knife cookbook create rails_app ** Creating

    cookbook rails_app ** Creating README for cookbook: rails_app ** Creating CHANGELOG for cookbook: rails_app ** Creating metadata for cookbook: rails_app
  38. Application Recipe • Set-up some directories %w(releases shared shared/system shared/pids

    shared/logs shared/config).each do |dir| directory "#{deploy_to}/#{app_name}/#{dir}" do action :create owner app_user group app_group mode "0664" recursive true end end
  39. Application Recipe • Configure Apache / Passenger web_app app_name do

    docroot "#{deploy_to}/current/public" server_name "#{app_name}.#{node["domain"]}" server_aliases [ app_name, "localhost", node["hostname"] ] rails_env "production" end
  40. node[“domain”] • cookbook • default[“domain”] = “localhost” • environments •

    test •“domain” : “test.awesomeco.com” • production •“domain” : “awesomeco.com"
  41. "memory": { "swap": { "cached": "0kB", "total": "4128760kB", "free": "4128760kB"

    }, "total": "2055676kB", "free": "1646524kB", "buffers": "35032kB", "cached": "210276kB", "active": "125336kB", "inactive": "142884kB", "dirty": "8kB", "writeback": "0kB", "anon_pages": "22976kB", "mapped": "8416kB", "slab": "121512kB", "slab_reclaimable": "41148kB", "slab_unreclaim": "80364kB", "page_tables": "1784kB", "nfs_unstable": "0kB", "bounce": "0kB", "commit_limit": "5156596kB", "committed_as": "74980kB", "vmalloc_total": "34359738367kB", "vmalloc_used": "274512kB", "vmalloc_chunk": "34359449936kB" }, Ohai! "block_device": { "ram0": { "size": "32768", "removable": "0" }, "ram1": { "size": "32768", "removable": "0" }, "ram2": { "size": "32768", "removable": "0" }, "hostname": "server-1", "fqdn": "server-1.example.com", "domain": "example.com", "network": { "interfaces": { "eth0": { "type": "eth", "number": "0", "encapsulation": "Ethernet", "addresses": { "00:0C:29:43:26:C5": { "family": "lladdr" }, "192.168.177.138": { "family": "inet", "broadcast": "192.168.177.255", "netmask": "255.255.255.0" }, "fe80::20c:29ff:fe43:26c5": { "family": "inet6", "prefixlen": "64", "scope": "Link" } },
  42. Database Recipe mysql_connection_info = { :host => "localhost", :username =>

    'root', :password => node['mysql']['server_root_password'] } mysql_database app_name do connection mysql_connection_info action :create end
  43. Create Roles • mechanism for easily composing sets of functionality

    • have attributes and a list of recipes to be applied • Define as Ruby or JSON • base-ubuntu • rails-web • rails-database
  44. Role as JSON { "name": "rails-web", "description": "Web Server for

    our Rails App", "default_attributes": { }, "run_list": [ "recipe[rails_app::web]" ] }
  45. Run Chef Client Server Server Server Server chef-server API chef-client

    “role[base-ubuntu]”, “role[rails-web]” node apt default.rb build-essential default.rb rails-app web.rb
  46. Review • Server provisioned and communicating with Chef Server API

    • Apache & Passenger installed with a default configuration • MySQL installed and running
  47. Capistrano + Chef webservers = [] web_query = Chef::Search::Query.new web_query.search(:node,

    'role:dcrug_web') do |h| webservers << h["fqdn"] end role :web, *webservers
  48. But wait, there’s more! • Encrypted Data Bags • Environments

    • Lightweight Resources and Providers • Exception and Report Handlers