This training is about the basics of the chef. Considering the bellow inputs:
- ip
192.168.3.xx
- mask
255.255.252.0
At any error check if exist some tip on the Troubleshooting at the end of the page
- 1st Creating the project
- 2nd Registering the node on chef
- 3rd Creating and applying the first cookbook
- 4th Listing the result
- 5ft Using attributes
- 6th Creating new cookbooks
- 7th Notifications
- 8th Queries
- 10th Role-based Attributes and Merge Order Precedence
- 11th Environments
- 12th Chef Supermarket
- 13th Working chef
- node π² vagrant init centos/7
- node π² vagrant up --provider virtualbox
- node π² [manual] Change Vagrantfile to use the given ip/mask and to be public
config.vm.network "public_network", ip: "[ip]", netmask: "[mask]"
- node π² [manual] Change Vagrantfile to disable selinux, it will avoid problems with ports
config.vm.provision "shell", inline: <<-SHELL
sudo setenforce 0
sudo sed -i 's/SELINUX=\(enforcing\|permissive\)/SELINUX=disabled/g' /etc/selinux/config
SHELL
- chef πͺ [manual] Create a account at chef.io
- chef πͺ [manual] Download the skeleton project
- node π² vagrant destroy
- node π² vagrant up
- node π² vagrant ssh
- node π² ip addr list
- chef πͺ knife list
- chef πͺ knife client list
- node π² new_ip=$(vagrant ssh -c "ip address show eth1 | grep 'inet ' | sed -e 's/^.inet //' -e 's//.$//'")
- chef πͺ knife bootstrap $new_ip --sudo -x vagrant -P vagrant -N "node1"
- node π² vagrant ssh -c "sudo sed -i '$ a log_level :info' /etc/chef/client.rb"
- chef πͺ knife cookbook create apache
- chef πͺ [manual] Edit apache/recipes/default.rb
package 'httpd' { action :install }
service 'httpd' { action [ :enable, :start ] }
cookbook_file '/var/www/html/index.html' do
source 'index.html'
mode '0644'
end
- chef πͺ [manual] Create apache/files/default/index.html with some html content
- chef πͺ knife cookbook upload apache
- chef πͺ knife node run_list add node1 "recipe[apache]"
- node π² vagrant ssh -c "sudo chef-client"
Then check the result on the browser: http://[ip]/
- chef πͺ knife node list
- chef πͺ knife node show node1
- node π² vagrant ssh -c "ohai" | less
- chef πͺ knife node show node1 -l
- chef πͺ knife node show node1 -a fqdn
- chef πͺ knife search node ':' -a fqdn
- chef πͺ [manual] Create apache/attributes/default.rb
default['apache']['indexfile'] = 'index1.html'
- chef πͺ [manual] Clone the index.html to index1.html and add something
- chef πͺ [manual] Change the default recipe to use the new property
...
cookbook_file '/var/www/html/index.html' do
source node['apache']['indexfile']
...
- chef πͺ knife cookbook upload apache
- node π² vagrant ssh -c "sudo chef-client"
Then check the result on the browser: http://[ip]/
- chef πͺ knife cookbook create motd
- chef πͺ echo "default['motd']['company'] = 'Chef'" >> cookbooks/motd/attributes/default.rb
- chef πͺ [manual] Add a template to the recipe
template '/etc/motd' do
source 'motd.erb'
mode '0644'
end
- chef πͺ [manual] Create motd/template/default/motd.erb
This server is property of <%= node['motd']['company'] %>
<% if node['pci']['in_scope'] -%>
This server is in-scope for PCI compliance
<% end -%>
- chef πͺ knife cookbook upload motd
- chef πͺ knife cookbook create pci
- chef πͺ echo "default['pci']['in_scope'] = true" >> cookbooks/pci/attributes/default.rb
- chef πͺ knife cookbook upload pci
- chef πͺ knife node run_list add node1 "recipe[motd]"
- node π² vagrant ssh -c "sudo chef-client"
This will fail because the pci is not associated to motd
- chef πͺ echo "depends 'pci'" >> cookbooks/motd/metadata.rb
- chef πͺ knife cookbook upload motd
- node π² vagrant ssh -c "sudo chef-client"
Run
vagrant ssh
to see the message after the login
- chef πͺ echo "default['apache']['sites']['clowns'] = { 'port' => 80 }" >> cookbooks/apache/attributes/default.rb
- chef πͺ echo "default['apache']['sites']['bears'] = { 'port' => 81 }" >> cookbooks/apache/attributes/default.rb
- chef πͺ [manual] Disable the default virtual host at apache/recipes/default.rb
# Disable the default virtual host
execute 'mv /etc/httpd/conf.d/welcome.conf /etc/httpd/conf.d/welcome.conf.disable' do
only_if do
File.exist? '/etc/httpd/conf.d/welcome.conf'
end
notifies :restart, 'service[httpd]'
end
- chef πͺ [manual] Remove the cookbook_file block from apache/recipes/default.rb
- chef πͺ [manual] Add the new sites in apache/recipes/default.rb
# Iterate over the apache sites
node['apache']['sites'].each do |site_name,site_data|
# Set the document root
document_root = "/var/www/html/#{site_name}"
template "/etc/httpd/conf.d/#{site_name}.conf" do
source 'custom.erb'
mode '0644'
variables(
document_root: document_root,
port: site_data['port']
)
notifies :restart, 'service[httpd]'
end
directory document_root do
mode '0755'
recursive true
end
template "#{document_root}/index.html" do
source 'index.html.erb'
mode '0644'
variables(
site_name: site_name,
port: site_data['port']
)
end
end
- chef πͺ [manual] Create template apache/templates/default/custom.rb from gist 8955103
- chef πͺ [manual] Create template apache/templates/default/index.html.rb from gist 8955080
- chef πͺ knife cookbook upload apache
- node π² vagrant ssh -c "sudo chef-client"
This will fail because the custom.rb has a tag without end
- chef πͺ [manual] Fix the template apache/templates/default/custom.rb
...
<Directory <%= @document_root %> >
...
- chef πͺ knife cookbook upload apache
- node π² vagrant ssh -c "sudo chef-client"
This will fail because start service is before the template render
- chef πͺ [manual] Move the service block to the end of the file at apache/recipe/default.rb
...
node['apache']['sites'].each do |site_name,site_data|
...
end
# Service need to start after all the configurations
service 'httpd' do
action [ :enable, :start ]
end
- chef πͺ knife cookbook upload apache
- node π² vagrant ssh -c "sudo chef-client"
Then check the result on the browser: http://[ip]:80/ and http://[ip]:81/
- chef πͺ knife node show node1 -a fqdn -a ipaddress
- chef πͺ knife search node 'ipaddress:10* and platform_family:rhe1'
- chef πͺ [manual] Create recipe apache/recipes/ip-logger.rb
search('node', 'platform:centos').each do |server|
log "The CentOS servers in your organization have the following FQDN/IP Addresses:- #{server['fqdn']}/#{server['ipaddress']}"
end
- chef πͺ knife cookbook upload apache
- chef πͺ knife node run_list add node1 "recipe[apache::ip-logger]"
- node π² vagrant ssh -c "sudo chef-client"
The log will print the message
- chef πͺ knife node run_list remove node1 "recipe[apache::ip-logger]"
- chef πͺ mkdir -p data_bags/users
- chef πͺ knife data_bag create users
- chef πͺ Create the file data_bags/users/bobo.json
{
"id": "bobo",
"comment": "Bobo T. Chown",
"uid": 2000,
"gid": 0,
"home": "/home/bobo",
"shell": "/bin/bash"
}
- chef πͺ knife data_bag from file users bobo.json
- chef πͺ Create the file data_bags/users/frank.json
{
"id": "frank",
"comment": "Frank Belson",
"uid": 2001,
"gid": 0,
"home": "/home/frank",
"shell": "/bin/bash"
}
- chef πͺ knife data_bag from file users frank.json
- chef πͺ knife search users ':'
- chef πͺ knife search users 'id:bobo' -a shell
- chef πͺ mkdir -p data_bags/groups
- chef πͺ knife data_bag create groups
- chef πͺ Create the file data_bags/groups/clowns.json
{
"id": "clowns",
"gid": 3000,
"members": ["bobo","frank"]
}
- chef πͺ knife data_bag from file groups clowns.json
- chef πͺ knife search groups ':'
- chef πͺ knife cookbook create users
- chef πͺ [manual] Edit the recipe users/recipes/default.rb
search('users', '*:*').each do |user_data|
user user_data['id'] do
comment user_data['comment']
uid user_data['uid']
gid user_data['gid']
home user_data['home']
shell user_data['shell']
end
end
include_recipe 'users::groups'
- chef πͺ [manual] Create a new recipe users/recipes/groups.rb
search('groups', '*:*').each do |group_data|
group group_data['id'] do
gid group_data['gid']
members group_data['members']
end
end
- chef πͺ knife cookbook upload users
- chef πͺ knife node run_list add node1 "recipe[users]"
- node π² vagrant ssh -c "sudo chef-client"
- node π² vagrant ssh -c "cat /etc/group | grep clowns"
- node π² vagrant ssh -c "cat /etc/passwd | grep 200"
- node π² vagrant ssh -c "setenforce 0;sed -i 's/SELINUX=(enforcing|permissive)/SELINUX=disabled/g' /etc/selinux/config"
I updated the 1st part, you can put this command on the vagrantfile to avoid do it manual and also to avoid problems if you need to recreate the node from scratch
- node π² vagrant reload
- chef πͺ [manual] Create new role file roles/webserver.rb
name 'webserver'
description 'web Server'
run_list 'recipe[apache]'
default_attributes({
apache: {
sites: {
admin: {
port: 8000
},
bears: {
port: 8001
}
}
}
})
- chef πͺ knife role from file webserver.rb
- chef πͺ knife role show webserver
- chef πͺ [manual] Go on the manager server at Nodes > Edit Run List
- chef πͺ [manual] Drag
webserver
to the run list and remove theapache
- node π² vagrant ssh -c "sudo chef-client"
Then check the result on the browser: http://[ip]:8000/ and http://[ip]:8001/
- chef πͺ [manual] Create new role file roles/base.rb
name 'base'
description 'Base Server Role'
run_list 'recipe[motd]', 'recipe[users]'
- chef πͺ knife role from file base.rb
- chef πͺ [manual] Edit roles/webserver.rb
...
run_list 'role[base]','recipe[apache]'
...
- chef πͺ knife role from file webserver.rb
- chef πͺ knife node run_list remove node1 "recipe[motd]"
- chef πͺ knife node run_list remove node1 "recipe[users]"
- node π² vagrant ssh -c "sudo chef-client"
Then check the result on the browser: http://[ip]:8000/ and http://[ip]:8001/
- chef πͺ mkdir environments
- chef πͺ [manual] Create the environment file environments/dev.rb
name 'dev'
description 'For developers!'
cookbook 'apache', '= 0.2.0'
- chef πͺ knife environment from file dev.rb
- chef πͺ knife environment show dev
- chef πͺ [manual] Go on the manager server at Nodes
- chef πͺ [manual] Change the enviroment of the node1 to use
dev
- chef πͺ [manual] Create the environment file environments/production.rb
name 'production'
description 'For prods!'
cookbook 'apache', '= 0.1.0'
override_attributes({
pci: {
in_scope: true
}
})
- chef πͺ knife environment from file production.rb
- chef πͺ knife node environment_set node1 production
- node π² vagrant ssh -c "sudo chef-client"
- chef πͺ [manual] Go to supermarket
- chef πͺ [manual] Search
chef-client
You will see all the information about this cookbook and others
- chef πͺ knife cookbook site search chef-client
- chef πͺ knife cookbook site show chef-client
Like the browser, a command way to search for new cookbooks
- chef πͺ knife cookbook site download chef-client
- chef πͺ tar -zxvf chef-client*.tar.gz -C cookbooks
- chef πͺ [manual] Check the file chef-client/recipes/delete_validation.rb
- chef πͺ [manual] Edit the role roles/base.rb
...
run_list "recipe[chef-client::delete_validation]", "recipe[motd]", "recipe[users]"
- chef πͺ knife role from file base.rb
- chef πͺ [manual] Check the file chef-client/recipes/default.rb
This class is just the default call and will delegate to the service recipe
- chef πͺ [manual] Check the file chef-client/recipes/service.rb
- chef πͺ knife cookbook upload chef-client
Will fail with dependence to cron
- chef πͺ [manual] knife cookbook site download cron
- chef πͺ [manual] tar -zxvf cron*.tar.gz -C cookbooks
- chef πͺ knife cookbook upload cron
- chef πͺ knife cookbook upload chef-client
Will fail with dependence to log rotate
- chef πͺ knife cookbook site download logrotate
- chef πͺ tar -zxvf logrotate*.tar.gz -C cookbooks
- chef πͺ knife cookbook site download windows
- chef πͺ tar -zxvf windows*.tar.gz -C cookbooks
- chef πͺ knife cookbook site download chef_handler
- chef πͺ tar -zxvf chef_handler*.tar.gz -C cookbooks
- chef πͺ knife cookbook upload logrotate
- chef πͺ knife cookbook upload chef_handler
- chef πͺ knife cookbook upload windows
- chef πͺ knife cookbook upload chef-client
- node π² vagrant ssh -c "sudo chef-client"
Finally, it will delete the validation pem
- chef πͺ knife cookbook site download ntp
- chef πͺ tar -zxvf ntp*.tar.gz -C cookbooks/
- chef πͺ knife cookbook upload ntp
- chef πͺ [manual] Edit the role roles/base.rb
...
run_list "recipe[chef-client::delete_validation]", "recipe[chef-client]", "recipe[motd]", "recipe[users]"
- chef πͺ knife role from file base.rb
- node π² vagrant ssh -c "sudo chef-client"
Cool, finally done
Just read the pdf XD
- To solve the clock problem that happens on Mac, put this line in the Vagrantfile.
config.vm.provision :shell, :inline => "sudo rm /etc/localtime && sudo ln -s /usr/share/zoneinfo/America/Sao_Paulo /etc/localtime", run: "always"
-
To solve the problem with the kitchen about the conflicts of gems, just drop the file ~/.checfdk2.
-
If you need to destroy and create again
-
node π² vagrant destroy
-
node π² vagrant up
-
node π² new_ip=$(vagrant ssh -c "ip address show eth1 | grep 'inet ' | sed -e 's/^.inet //' -e 's//.$//'")
-
node π² ssh-keygen -R ${new_ip//[^([:alnum:]|\.)]/}
-
chef πͺ knife node delete node1
-
chef πͺ (cd ../chef-repo;knife bootstrap $new_ip --sudo -x vagrant -P vagrant -N "node1")
-
chef πͺ knife node run_list add node1 "role[webserver]"
-
node π² vagrant ssh -c "sudo sed -i '$ a log_level :info' /etc/chef/client.rb"
-
node π² vagrant ssh -c "sudo chef-client"
You can use the script at node/recreate.sh
- node π² sh recreate.sh