Skip to content

This code is the result of the chef fundamentals course at Avenue Code

Notifications You must be signed in to change notification settings

voiski/chef-fundamentals

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

12 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Chef Fundamentals

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

Steps

1st Creating the project

  • 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

2nd Registering the node on chef

  • 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"

3rd Creating and applying the first cookbook

  • 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]/

4th Listing the result

  • 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

5ft Using attributes

  • 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]/

6th Creating new cookbooks

  • 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

7th Notifications

  • 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/

8th Queries

  • 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]"

9th User and groups

  • 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"

10th Role-based Attributes and Merge Order Precedence

  • 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 the apache
  • 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/

11th Environments

  • 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"

12th Chef Supermarket

  • 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

13th Working chef

Just read the pdf XD

Troubleshooting

  • 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

About

This code is the result of the chef fundamentals course at Avenue Code

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published