Talk given at ConFoo 2013 on February 28th, 2013.
Automateyour Infrastructurewith Chef
View Slide
cjoudrey @
c#
c#######in minutes
#d#dc#####din minutes
wManual setuptakestime
#ruby 1.9.3#ruby 1.9.2!=and error-prone
#ruby 1.9.3#ruby 1.9.2!=Oops!and error-prone
What is ?!Chef
1Manage serverswithruby code
instead of$ ssh [email protected]Last login: Thu Feb 28...# apt-get install nginx...# vim /etc/nginx/nginx.conf...# apt-get install ruby...
client server
#node#node#node#chef server(server1 to server3.example.com)(chef.example.com)knife!(local machine)
#node#node#node#chef serverchef-client(server1 to server3.example.com)knife!(local machine)
2terminologyChef
2recipeRuby file that contains Chefcommands
2cookbookCollection of Chef recipes
Getting startedwithChef2
git cloneopscode/chef-repohttps://github.com/opscode/chef-repo!
!$ ls confoo...cookbooks/data_bags/environments/roles/
Install Chef on localmachine!
!gem install chef
#Hosted* Chef serverfrom Opscode* free up to 5 nodes
#
Setup Knife on localmachine!
!$ ls confoo/.chefconfoo-demo-validator.pemconfoo-demo.pemknife.rbCopy files to REPO/.chef
!$ cd confoo$ knife user listconfoo-demoTest Knife
8Create your firstcookbook$ cd confoo$ knife cookbook createnginx
8$ ls cookbooks/nginx...attributes/providers/recipes/resources/templates/
package "nginx"cookbooks/nginx/recipes/default.rb
package installs usingsystem’s package mgr
cookbooks/nginx/recipes/default.rbpackage "nginx"service "nginx"
service defines anavailable service
cookbooks/nginx/recipes/default.rbpackage "nginx"service "nginx" dosupports :status => true,:restart => true,:reload => trueend
cookbooks/nginx/recipes/default.rbpackage "nginx"service "nginx" dosupports :status => true,:restart => true,:reload => trueaction [:enable, :start]end
:enable starton server boot
:start startwhen Chef runs
8Upload cookbook$ knife cookbook uploadnginxUploading nginx [0.1.0]
Let’s test iton a node#
!$ knife bootstrap \server1.example.comBootstrap a node
!
2run listOrdered list of recipes and rolesthat get run on the node
!$ knife node edit \server1.example.comEdit a node
{"name": "server1.example.com","run_list": []}
{"name": "server1.example.com","run_list": ["recipe[nginx::default]"]}
recipe[nginx::default]means default recipeof nginx cookbook
$ ssh server1.example.comserver1:~# chef-clientRun Chef on the node#
#Let’s configurenginx
copy from serverto nginx cookbooktemplates/default/nginx.conf.erb/etc/nginx/nginx.conf!
cookbooks/nginx/recipes/default.rbpackage "nginx"service "nginx" dosupports :status => true,:restart => true,:reload => trueaction [:enable, :start]endtemplate "/etc/nginx/nginx.conf" dosource "nginx.conf.erb"notifies :reload, "service[nginx]"end
!Upload the cookbookand run chef-clienton node
2Chef is idempotent
!What if we edittemplates/default/nginx.conf.erband run Chef
Let’s run Chefone more time#
2Attributes
nginx/templates/default/nginx.conf.erbuser www-data;worker_processes 2;pid /var/run/nginx.pid;...
nginx/attributes/nginx.rbdefault['nginx']['worker_processes'] = 2
nginx/templates/default/nginx.conf.erbuser www-data;worker_processes <%= node['nginx']['worker_processes'] %>;pid /var/run/nginx.pid;...
#Override fora specific node
{"name": "server1.example.com","normal": {"nginx": {"worker_processes": 4},},"run_list": ["recipe[nginx::default]"]}
2Roles
roles/app-server.rbname 'app-server'description 'app-server stuff'run_list('recipe[nginx::default]')override_attributes('nginx' => {'worker_processes' => 2})
!$ knife role from file \app-server.rbUpload a role
Apply therole on a node#
{"name": "server1.example.com","run_list": ["role[app-server]"]}
{"name": "server1.example.com","run_list": ["role[base]","role[app-server]"]}
2Environments
environments/production.rbname 'production'cookbook_versions 'nginx' => '= 0.1.0'
{"name": "server1.example.com","chef_environment": "production","run_list": ["recipe[nginx::default]"]}
!Searching for nodes$ knife search node \role:app-server
2
8Searching can bedone in recipes too!
8Searching can bedone in recipes too!OMFG!
backend appbalance roundrobinserver app1 10.10.0.1 check port 80server app2 10.10.0.2 check port 80server app3 10.10.0.3 check port 80
nodes = search(:node,'role:app-server')template "/etc/haproxy.conf" dosource "haproxy.conf.erb"variables :nodes => nodesend
backend wwwbalance roundrobin<% @nodes.each do |n| %>server<%= n[:hostname] %><%= n[:ipaddress] %>check port<% end %>
2Goodies
Automation isimportant
#staging/CI#production!development= =
Thanks!