Automate your Infrastructure with Chef

Automate your Infrastructure with Chef

Talk given at ConFoo 2013 on February 28th, 2013.

85b03650a2ec5235376b0b983a49511a?s=128

Christian Joudrey

February 28, 2013
Tweet

Transcript

  1. Automate your Infrastructure with Chef

  2. cjoudrey   @

  3. None
  4. c #

  5. c # # # # # # # in minutes

  6. # d # d c # # # # #

    d in minutes
  7. w Manual setup takes time

  8. # ruby 1.9.3 # ruby 1.9.2 != and error-prone

  9. # ruby 1.9.3 # ruby 1.9.2 != Oops! and error-prone

  10. What is ?! Chef

  11. 1 Manage servers with ruby code

  12. instead of $ ssh root@app1 Last login: Thu Feb 28

    ... # apt-get install nginx ... # vim /etc/nginx/nginx.conf ... # apt-get install ruby ...
  13. client server

  14. # node # node # node # chef server (server1

    to server3.example.com) (chef.example.com) knife ! (local machine)
  15. # node # node # node # chef server (server1

    to server3.example.com) (chef.example.com) knife ! (local machine)
  16. # node # node # node # chef server (server1

    to server3.example.com) (chef.example.com) knife ! (local machine)
  17. # node # node # node # chef server chef-client

    (server1 to server3.example.com) knife ! (local machine)
  18. 2terminology Chef

  19. 2recipe Ruby file that contains Chef commands

  20. 2cookbook Collection of Chef recipes

  21. Getting started with Chef 2

  22. git clone opscode/chef-repo https://github.com/opscode/chef-repo !

  23. ! $ ls confoo ... cookbooks/ data_bags/ environments/ roles/

  24. Install Chef on local machine !

  25. ! gem install chef

  26. # Hosted* Chef server from Opscode * free up to

    5 nodes
  27. #

  28. #

  29. Setup Knife on local machine !

  30. # node # node # node # chef server (server1

    to server3.example.com) (chef.example.com) knife ! (local machine)
  31. ! $ ls confoo/.chef confoo-demo-validator.pem confoo-demo.pem knife.rb Copy files to

    REPO/.chef
  32. ! $ cd confoo $ knife user list confoo-demo Test

    Knife
  33. 8 Create your first cookbook $ cd confoo $ knife

    cookbook create nginx
  34. 8 $ ls cookbooks/nginx ... attributes/ providers/ recipes/ resources/ templates/

  35. package "nginx" cookbooks/nginx/recipes/default.rb

  36. package installs using system’s package mgr

  37. cookbooks/nginx/recipes/default.rb package "nginx" service "nginx"

  38. service defines an available service

  39. cookbooks/nginx/recipes/default.rb package "nginx" service "nginx" do supports :status => true,

    :restart => true, :reload => true end
  40. cookbooks/nginx/recipes/default.rb package "nginx" service "nginx" do supports :status => true,

    :restart => true, :reload => true action [:enable, :start] end
  41. :enable start on server boot

  42. :start start when Chef runs

  43. 8 Upload cookbook $ knife cookbook upload nginx Uploading nginx

    [0.1.0]
  44. Let’s test it on a node #

  45. ! $ knife bootstrap \ server1.example.com Bootstrap a node

  46. !

  47. 2run list Ordered list of recipes and roles that get

    run on the node
  48. ! $ knife node edit \ server1.example.com Edit a node

  49. { "name": "server1.example.com", "run_list": [ ] }

  50. { "name": "server1.example.com", "run_list": [ "recipe[nginx::default]" ] }

  51. recipe[nginx::default] means default recipe of nginx cookbook

  52. $ ssh server1.example.com server1:~# chef-client Run Chef on the node

    #
  53. #

  54. #

  55. # Let’s configure nginx

  56. copy from server to nginx cookbook templates/default/nginx.conf.erb /etc/nginx/nginx.conf !

  57. cookbooks/nginx/recipes/default.rb package "nginx" service "nginx" do supports :status => true,

    :restart => true, :reload => true action [:enable, :start] end template "/etc/nginx/nginx.conf" do source "nginx.conf.erb" notifies :reload, "service[nginx]" end
  58. cookbooks/nginx/recipes/default.rb package "nginx" service "nginx" do supports :status => true,

    :restart => true, :reload => true action [:enable, :start] end template "/etc/nginx/nginx.conf" do source "nginx.conf.erb" notifies :reload, "service[nginx]" end
  59. cookbooks/nginx/recipes/default.rb package "nginx" service "nginx" do supports :status => true,

    :restart => true, :reload => true action [:enable, :start] end template "/etc/nginx/nginx.conf" do source "nginx.conf.erb" notifies :reload, "service[nginx]" end
  60. cookbooks/nginx/recipes/default.rb package "nginx" service "nginx" do supports :status => true,

    :restart => true, :reload => true action [:enable, :start] end template "/etc/nginx/nginx.conf" do source "nginx.conf.erb" notifies :reload, "service[nginx]" end
  61. ! Upload the cookbook and run chef-client on node

  62. #

  63. 2 Chef is idempotent

  64. ! What if we edit templates/default/nginx.conf.erb and run Chef

  65. #

  66. #

  67. #

  68. Let’s run Chef one more time #

  69. #

  70. 2Attributes

  71. nginx/templates/default/nginx.conf.erb user www-data; worker_processes 2; pid /var/run/nginx.pid; ...

  72. nginx/attributes/nginx.rb default['nginx']['worker_processes'] = 2

  73. nginx/templates/default/nginx.conf.erb user www-data; worker_processes <%= node['nginx'] ['worker_processes'] %>; pid /var/run/nginx.pid;

    ...
  74. # Override for a specific node

  75. { "name": "server1.example.com", "run_list": [ "recipe[nginx::default]" ] }

  76. { "name": "server1.example.com", "normal": { "nginx": { "worker_processes": 4 },

    }, "run_list": [ "recipe[nginx::default]" ] }
  77. 2Roles

  78. roles/app-server.rb name 'app-server' description 'app-server stuff' run_list( 'recipe[nginx::default]' ) override_attributes(

    'nginx' => { 'worker_processes' => 2 } )
  79. ! $ knife role from file \ app-server.rb Upload a

    role
  80. Apply the role on a node #

  81. { "name": "server1.example.com", "run_list": [ "role[app-server]" ] }

  82. #

  83. { "name": "server1.example.com", "run_list": [ "role[base]", "role[app-server]" ] }

  84. 2 Environments

  85. environments/production.rb name 'production' cookbook_versions 'nginx' => '= 0.1.0'

  86. { "name": "server1.example.com", "chef_environment": "production", "run_list": [ "recipe[nginx::default]" ] }

  87. ! Searching for nodes $ knife search node \ role:app-server

  88. 2

  89. 8 Searching can be done in recipes too!

  90. 8 Searching can be done in recipes too! OMFG!

  91. backend app balance roundrobin server app1 10.10.0.1 check port 80

    server app2 10.10.0.2 check port 80 server app3 10.10.0.3 check port 80
  92. nodes = search( :node, 'role:app-server' ) template "/etc/haproxy.conf" do source

    "haproxy.conf.erb" variables :nodes => nodes end
  93. backend www balance roundrobin <% @nodes.each do |n| %> server

    <%= n[:hostname] %> <%= n[:ipaddress] %> check port <% end %>
  94. 2Goodies

  95. None
  96. None
  97. None
  98. None
  99. None
  100. Automation is important

  101. # staging/CI # production ! development = =

  102. Thanks!

  103. cjoudrey   @