A practical approach to chef (Using Vagrant)
Composed by Haggai Philip Zagury / @hagzag
"What we have to learn to do, we learn by doing." - Aristotle, Greek philosopher
Today we are SURE that we made the right decision, choosing Tikal
Guy Ben-Porat, Development Manager “ExLibris”
http://prezi.com/8zwcr5df9eno/chef-intro-chef-server-workflow
Lets go through this prezi together
We know what !
are
Let's write a simple cookbook ...
*git bash is also used in order to ssh
into a vagrant image on windows
Write a cookbook
Omnibus
installer will "figure out" your OS and install it
In
addition to an embedded version of chef
On *nix / MacOSX
curl -L https://www.opscode.com/chef/install.sh | sudo bash
/opt/opscode/...
On Windows [Download link]
https://opscode-omnibus-packages.s3.amazonaws.com/windows/2008r2/x86_64/chef-client-11.8.0-1.windows.msi
c:\opscode
We don't really need knife (at this stage), so we will just provide it with the defaults
Execute & Accept all defaults:
knife configure
WARNING: No knife configuration file found
Where should I put the config file? [/home/hagzag/.chef/knife.rb] y
Please enter the chef server URL: [https://:443]
Please enter an existing username or clientname for the API: [hagzag]
Please enter the validation clientname: [chef-validator]
Please enter the location of the validation key: [/etc/chef-server/chef-validator.pem]
...
*****
Configuration file written to /home/hagzag/.chef/knife.rb
knife cookbook create ntp -o .
We get:
attributes/
definitions/
files/
libraries/
metadata.rb
providers/
README.rdoc
recipes/
resources/
templates/
Shortcut => Get from git:
git clone git@github.com:tikalk-cookbooks/ntp-intro.git
git checkout -b 0.1.0
vim cookbooks/ntp/recipes/default.rb
package "ntp" do
action [:install]
end
yum install ntp
template "/etc/ntp.conf" do
source "ntp.conf.erb"
variables( :ntp_server => "time.nist.gov" )
notifies :restart, "service[ntpd]"
end
vim cookbooks/ntp/templates/default/ntp.conf.erb
restrict default kod nomodify notrap nopeer noquery
restrict -6 default kod nomodify notrap nopeer noquery
restrict 127.0.0.1
restrict -6 ::1
server <%= @ntp_server %>
server 127.127.1.0 # local clock
driftfile /var/lib/ntp/drift
keys /etc/ntp/keys
https://raw.github.com/tikalk-cookbooks/ntp-intro/0.1.0/templates/default/ntp.conf.erb
Similar to manually editing the /etc/ntp.conf
service "ntpd" do
action [:enable,:start]
end
chkconfig ntp on
What have we here ?
If yours differs - compare with:
https://github.com/tikalk-cookbooks/ntp-intro
use tag 0.1.0
Sharpen your knives => Improve the cookbook
vim ntp/attributes/default.rb
Use a case statement to differentiate between platforms
case x
when 1,2,3
puts "1, 2, or 3"
when 10
puts "10"
else
puts "Some other number"
end
Rubydoc case statement
case platform
when "redhat","centos","fedora","scientific"
default[:ntp][:service] = "ntpd"
when "ubuntu","debian"
default[:ntp][:service] = "ntp"
else
default[:ntp][:service] = "ntpd"
end
So now according to the
node['platform'] which chef "knows" during the chef run the service name will be
defined accordingly !
+ provide a default of
"ntpd" !
[1of3] on
github tag 0.1.1
In order to support more than 1 server
In this example add:
0.pool.ntp.org, 1.pool.ntp.org, 2.pool.ntp.org, 3.pool.ntp.org
We have 4 servers in out attributes file (but we might have 5 tomorrow ...)
0.pool.ntp.org, 1.pool.ntp.org, 2.pool.ntp.org, 3.pool.ntp.org
Our template file will is an erb file + loop over the servers array using the .each method
default[:ntp][:servers] = ["0.pool.ntp.org", "1.pool.ntp.org", "2.pool.ntp.org", "3.pool.ntp.org"]
# Generated by Chef for <%= node[:fqdn] %>
# node[:fqdn] = ohai data collected on node !
# Local modifications will be overwritten.
restrict -6 ::1
#server <%= @ntp_server %>
<% node[:ntp][:servers].each do |ntpsrv| -%>
server <%= ntpsrv %> iburst
restrict <%= ntpsrv %> nomodify notrap noquery
<% end -%>
# Generated by Chef for <%= node[:fqdn] %>
# node[:fqdn] = ohai data collected on node !
# Local modifications will be overwritten.
Re-arrange recipe
package "ntp" do
action [:install]
end
The package name is similar on all platforms
so there is no real change here ...
[3of3] on github tag 0.1.1
service node[:ntp][:service] do
service_name node[:ntp][:service]
action [:enable,:start,:restart]
end
Service declaration - the service name and it's implied location
/etc/init.d/ntp or /etc/init.d/ntpd
based on: service =>node[:ntp][:service]
[3of3] on
github tag 0.1.1
template "/etc/ntp.conf" do
source "ntp.conf.erb"
owner "root"
group "root"
mode 0644
notifies :restart, resources(:service => node[:ntp][:service])
end
This part is also the same as before just with a shift in it's location
[3of3] on
github tag 0.1.1
package "ntp" do
action [:install]
end
service node[:ntp][:service] do
service_name node[:ntp][:service]
action [:enable,:start,:restart]
end
template "/etc/ntp.conf" do
source "ntp.conf.erb"
owner "root"
group "root"
mode 0644
notifies :restart, resources(:service => node[:ntp][:service])
end
The service name comes
before the template which notifies
:service =>node[:ntp][:service]
[3of3] on
github tag 0.1.1
What have we here ?
If yours differs - compare with:
https://github.com/tikalk-cookbooks/ntp-intro
use tag 0.1.1
We want to test this cookbook & we need a server to test this on right ?
A good place to introduce
Use opscode's @ https://github.com/opscode-cookbooks/ntp
This one is just for play ;)
Vagrant provides easy to configure, reproducible, and portable work environments built on top of industry-standard technology and controlled by a single consistent work-flow to help maximize the productivity and flexibility of you and your team.
To achieve its magic, Vagrant stands on the shoulders of giants. Machines are provisioned on top of VirtualBox , VMware , AWS, or any other provider. Then, industry-standard provisioning tools such as shell scripts , Chef , or Puppet, can be used to automatically install and configure software on the machine.
Off-line copy is available with workshop materials
cd ~/My_Cool_Project
vagrant init My_Cool_Project http://shonky.info/centos64.box
So now you have a skeleton [ with good remarks ] of a Vagrantfile
Define a box & box url
config.vm.box = "CentOS 6.4 x86_64"
config.vm.box_url = "http://bit.ly/1aNaifu"
config.vm.network "private_network", ip: "192.168.56.80"
config.vm.network "public_network # will get DHCP from your LAN
NAME = "MyAwesomeVM"
config.vm.hostname = "#{NAME}"
Define your provisioner: shell/chef/puppet
shell example:
config.vm.provision :shell, :path => File.expand_path("../bootstrap.sh", __FILE__)
config.vm.provision :chef_solo do |chef|
chef.cookbooks_path = ["cookbooks", "site-cookbooks"]
chef.roles_path = ["roles"]
chef.log_level = ENV['CHEF_LOG'] ? ENV['CHEF_LOG'].to_sym : :info
chef.add_role "web"
# chef.add_recipe "nginx" => marked out but you can also add recipes ...
end
More about provisioner(s) here
Define your provider: virtualbox, aws, vmware fusion
Customize you virtualbox machine:
config.vm.provider :virtualbox do |vb|
# Don't boot with headless mode
# vb.gui = true
vb.customize [ "modifyvm", :id, "--memory", "512"]
vb.name = "#{NAME}"
end
Add some "juice" to your machine [if you need it]
More about providers here
First try virtual box unless --provider is specified
if --provider=aws ignore all vb customizations (or networking for that matter)
Look for a provisioner Chef / Shell / Salt / Other ..., more then one great !
config.vm.provision "shell",
inline: "[[ `which chef-solo` ]] || curl -L https://www.opscode.com/chef/install.sh | sudo bash"
config.vm.provision :chef_solo do |chef|
chef.cookbooks_path = ["cookbooks", "site-cookbooks"]
chef.roles_path = ["roles"]
chef.log_level = ENV['CHEF_LOG'] ? ENV['CHEF_LOG'].to_sym : :info
chef.add_role "web"
end
Work in the cloud - AWS example:
config.vm.provider :aws do |aws, override|
# Add aws tags
aws.tags = {
'vagrant' => 'true',
'environment' => 'devenv'
}
aws.access_key_id = ENV['AWS_ACCESS_KEY']
aws.secret_access_key = ENV['AWS_SECRET_KEY']
aws.keypair_name = "A_VAGRANT_KEYPAIR"
aws.security_groups = [ "MySecurotyGroupWithSSHOpen" ]
aws.region = "us-west-2"
aws.ami = "ami-myami"
end
In the example above set the AWS_ACCESS_KEY & AWS_SECRET_KEY
and executevagrant up --provider=aws
For example:
Easy as:
vagrant plugin install [plugin-name]
Use installer suitable for your platform from:
Virtualbox site
Offline copy is available with workshop materials
Offline copy is available with workshop materials
No extra configuration needed (at this point ...)
cd path/to/project
vagrant init
You should get a clean vagrant file
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "CentOS 6.5 x86_64"
config.vm.box_url = "http://bit.ly/1aNaifu"
In order to save time I have provided an offline copy of this box:
Add it by excuting the command Vagrant box add like so:
vagrant box add "CentOS 6.5 x86_64" file:///path/to/vbox/image-bundle.box
This command will add to your home folder ~/.vagrnat/boxes/CentOS 6.5 x86_64
vagrant box add "centos65-x86_65" /Volumes/TOSHIBADISK/Vagrant-Boxes/centos65-x86_64-20131205.box
Downloading box from URL: file:/Volumes/TOSHIBADISK/Vagrant-Boxes/centos65-x86_64-20131205.box
Extracting box...te: 245M/s, Estimated time remaining: --:--:--)
Successfully added box 'centos65-x86_65' with provider 'virtualbox'!
cd path/to/project
vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
[default] Importing base box 'CentOS 6.5 x86_64'...
[default] Matching MAC address for NAT networking...
[default] Setting the name of the VM...
[default] Clearing any previously set forwarded ports...
[default] Clearing any previously set network interfaces...
[default] Preparing network interfaces based on configuration...
[default] Forwarding ports...
[default] -- 22 => 2222 (adapter 1)
[default] Booting VM...
[default] Waiting for machine to boot. This may take a few minutes...
DL is deprecated, please use Fiddle
[default] Machine booted and ready!
[default] Mounting shared folders...
[default] -- /vagrant
Open Virtual box Manager ans see you have a box there, Then desory it ...
vagrant destroy -f
-f used for force ...
config.vm.provider "virtualbox" do |vb|
vb.gui = true
vb.customize ["modifyvm", :id, "--memory", 512]
vb.customize ["modifyvm", :id, "--ioapic", "on", "--cpus", 1]
end
Note the vb.gui = true option here,
in this case I would like the Virtualbox GUI to startup !
Is now
We cloud choose a vagran box with chef client installed ..., but where is the fun in that ?
config.vm.provision "shell",
inline: "[[ `which chef-solo` ]] || curl -L https://www.opscode.com/chef/install.sh | sudo bash"
Use chef to install our ntp cookbook from ex02
config.vm.provision :chef_solo do |chef|
chef.cookbooks_path = ["cookbooks" ]
chef.add_recipe "ntp"
end
Copy the ntp cookbook in to a directory called cookbooks
mkdir ./cookbooks
cp -R ntp cookbooks
Execute the vagrant provision
$ vagrant provision
[default] Running provisioner: shell...
[default] Running: inline script
[default] Running provisioner: chef_solo...
Generating chef JSON and uploading...
Vagrant is trigerring chef-solo ...
Running chef-solo...
[] INFO: Forking chef instance to converge...
[] INFO: *** Chef 11.10.0 ***
[] INFO: Chef-client pid: 1655
[] INFO: Setting the run_list to ["recipe[ntp]"] from JSON
[] INFO: Run List is [recipe[ntp]]
[] INFO: Run List expands to [ntp]
[] INFO: Starting Chef Run for vagrant-centos65
[] INFO: Running start handlers
[] INFO: Start handlers complete.
end of "compliation - begining of converge (execution)"
[] INFO: package[ntp] installing ntp-4.2.6p5-1.el6.centos from base repository
[] INFO: service[ntpd] enabled
[] INFO: service[ntpd] started
[] INFO: service[ntpd] restarted
[] INFO: template[/etc/ntp.conf] backed up to /var/chef/backup/etc/ntp.conf.chef-20130913144203.354529
[] INFO: template[/etc/ntp.conf] updated file contents/etc/ntp.conf
[] INFO: template[/etc/ntp.conf] sending restart actionto service[ntpd] (delayed)
[] INFO: service[ntpd] restarted
[] INFO: Chef Run complete in 87.127895456 seconds
[] INFO: Running report handlers
[] INFO: Report handlers complete
Connect to the machine
vagrant ssh
Is the rpm installed ?
rpm -qa | grep ntp
[vagrant@vagrant-centos65 ~]$ rpm -qa | grep ntp
ntpdate-4.2.6p5-1.el6.centos.x86_64
ntp-4.2.6p5-1.el6.centos.x86_64
Examine /etc/ntp.conf
[vagrant@vagrant-centos65 ~]$ cat /etc/ntp.conf
# Generated by Chef for
# node[:fqdn] = ohai data collected on node !
# Local modifications will be overwritten.
restrict -6 ::1
#server
server 0.pool.ntp.org iburst
restrict 0.pool.ntp.org nomodify notrap noquery
server 1.pool.ntp.org iburst
restrict 1.pool.ntp.org nomodify notrap noquery
server 2.pool.ntp.org iburst
restrict 2.pool.ntp.org nomodify notrap noquery
server 3.pool.ntp.org iburst
restrict 3.pool.ntp.org nomodify notrap noquery
restrict default kod nomodify notrap nopeer noquery
restrict -6 default kod nomodify notrap nopeer noquery
restrict 127.0.0.1
server 127.127.1.0 # local clock
driftfile /var/lib/ntp/drift
keys /etc/ntp/keys
Planned for next session
"What we have to learn to do, we learn by doing." - Aristotle, Greek philosopher
If you followed so far you should already have it all ...
knife cookbook create web
vim web/metadata.rb
depends 'nginx'
We will learn later on how this line
makes a difference ...
default['nginx']['port'] = '4000'
default['nginx']['listen_ports'] = %w[80, #{node['nginx']['port']}]
default['nginx']['vhost']['basedir'] = '/var/www/nginx'
default['nginx']['vhost']['demo'] = "#{node['nginx']['vhost']['basedir']}/demo"
use an attribute, for the directory name !
include_recipe "nginx"
#Create the runtime directory - using directory resource [ chef core resource provider ]
directory node[:nginx][:vhost][:demo] do
owner 'nginx'
group 'nginx'
recursive true
end
Use a template file ...
template "/etc/nginx/sites-available/demo-site" do # the "default" sites-available dir under nginx's run folder
source "demo-site.erb" # the template file to use
owner "root" # Owner of the file
group "root" # Group of the file
mode 0644 # Mode
notifies :restart, "service[nginx]" # Restart nginx upon configuration
end
Use a template file ...
# nginx virtual host template configured by chef on <%= node[:fqdn] %>
server {
listen <%= node[:nginx][:port] %> default;
server_name <%= node[:fqdn] %>;
root <%= node[:nginx][:vhost][:demo] %>;
}
Will evaluate to:
# nginx virtual host template configured by chef on chef-solo-demo
server {
listen 4000 default;
server_name chef-solo-demo;
root /var/www/nginx/demo;
}
# Create a website from template ...
template "#{node[:nginx][:vhost][:demo]}/index.html" do #index file location
source "index.html.erb" # now user
owner "nginx" # is nginx [ the user running the nginx server !]
group "nginx"
end
<html>
<head></head>
<body>
<center>
<h1>Demo site running on nginx <%= node[:fqdn] %></h1>
<div>
<img src="http://www.tikalk.com/files/devops-icons1.png" alt="DevOpsIcon"/>
</div>
<h1>And your'e a full stack developer !!!</h1>
</center>
</body>
</html>
nginx_site "demo-site" do # "nginx_ensite" see :: https://github.com/perusio/nginx_ensite
enable :true
notifies :restart, "service[nginx]"
end
# disable iptables ! => just for this demo :)
include_recipe "iptables::disabled"
name 'web'
maintainer 'Tikal Knowledge LTD'
maintainer_email 'c5191707@tikalk.com'
license 'Apache 2.0'
description 'Installs/Configures web'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version '0.1.0'
depends 'nginx'
depends 'iptables' # opend nginx port(S)
depends 'nginx'
depends 'iptables' # opend nginx port(S)
And know how to get these cookbooks - right ?
echo "cookbook 'nginx'" >> /path/to/Cheffile
Or
echo "cookbook 'nginx'" >> /path/to/Berksfile
Usually will find Berkshelf with a chef server environment and librarian with chef-solo
gem install berkshelf
Define your dependencies
site :opscode
cookbook 'mysql'
cookbook 'nginx', '~> 0.101.5'
cookbook 'web', path: '~/cookbooks/web'
cookbook 'lvm', git: 'git://github.com/opscode-cookbooks/lvm.git'
gem install librarian-chef
Define your dependencies
site "http://community.opscode.com/api/v1"
cookbook "ntp"
cookbook "timezone", "0.0.1"
cookbook "rvm",
:git => "https://github.com/fnichol/chef-rvm",
:ref => "v0.7.1"
cookbook "cloudera",
:path => "vendor/cookbooks/cloudera-cookbook"
Test our `web` cookbook
In order to do that we need:
You can use the Vagrant-box from last exercise (to save time)
cd path/to/project
vagrant init
You should get a clean vagrant file
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "CentOS 6.5 x86_64"
config.vm.box_url = "http://bit.ly/1aNaifu"
In order to save time I have provided an offline copy of this box:
Add it by excuting the command Vagrant box add like so:
vagrant box add "CentOS 6.5 x86_64" file:///path/to/vbox/image-bundle.box
This command will add to your home folder ~/.vagrnat/boxes/CentOS 6.5 x86_64
vagrant box add "centos65-x86_65" /Volumes/TOSHIBADISK/Vagrant-Boxes/centos65-x86_64-20131205.box
Downloading box from URL: file:/Volumes/TOSHIBADISK/Vagrant-Boxes/centos65-x86_64-20131205.box
Extracting box...te: 245M/s, Estimated time remaining: --:--:--)
Successfully added box 'centos65-x86_65' with provider 'virtualbox'!
librarian-chef init
create Cheffile
Add your dependency
vim Cheffile
cookbook 'nginx'
cookbook 'iptables'
librarian-chef config path ./chef/cookbooks --local
this will create .librarian/chef/config
cat .librarian/chef/config
---
LIBRARIAN_CHEF_PATH: ./chef/cookbooks
3 options
config.vm.provision "shell",
inline: "[[ `which chef-solo` ]] || curl -L https://www.opscode.com/chef/install.sh | sudo bash"
$ vagrant plugin install vagrant-omnibus
Configure vagrant to do it ...
Vagrant.configure("2") do |config|
config.omnibus.chef_version = :latest # or version: "11.4.0"
...
end
config.vm.provision :chef_solo do |chef|
chef.cookbooks_path = ["chef/cookbooks", "chef/site-cookbooks"]
chef.log_level = ENV['CHEF_LOG'] ? ENV['CHEF_LOG'].to_sym : :info
chef.add_role "web"
# You may also specify custom JSON attributes:
chef.json = { some_key: "value" }
end
please note:
you can control anything you can control in solo.rb ...
proxy configuration, log level, roles, attributes etc .
#Proxy support for chef-solo, else i.e. remote_file externally will do worklibr
# chef.http_proxy = ""
# chef.https_proxy = ""
# chef.no_proxy = ""
# chef.log_level = ENV['CHEF_LOG'] ? ENV['CHEF_LOG'].to_sym : :debug
place the web cookbook into the ./chef/site-cookbooks directory
mkdir ./chef/site-cookbooks
cp -R path/to/cookbook/web ./chef/site-cookbooks/
├── .librarian
│ └── chef
├── Cheffile
├── Vagrantfile
├── chef
│ └── site-cookbooks
│ └── web
we also want to add chef/cookbooks and tmp to .gitignore
so we don't submit dependencies to source control
echo -e "chef/cookbooks\ntmp\n" > .gitignore
librarian-chef install
*if you are using vagrant-librarian-chef skip this step
librarian-chef output:
Installing apt (2.3.8)
Installing rsyslog (1.11.0)
Installing bluepill (2.3.1)
Installing build-essential (1.4.2)
Installing iptables (0.12.0)
Installing ohai (1.1.12)
Installing yum (3.1.0)
Installing yum-epel (0.3.4)
Installing runit (1.5.8)
Installing nginx (2.2.2)
ls ./chef/cookbooks/
apt bluepill build-essential nginx ohai rsyslog runit yum yum-epel
Where did all that come from ?
Take a look @: ./chef/coobkooks/nginx/metadata.rb
vagrant up
Vagrant output -> standard stuff ...
vagrant provision
[default] Installing Chef cookbooks with Librarian-Chef...
[default] The cookbook path '/Users/c5191707/Projects/tikal/chef_workshop/excersizes/ex05/roles' doesn't exist. Ignoring...
[default] Running provisioner: shell...
[default] Running: inline script
[default] Running provisioner: chef_solo...
Generating chef JSON and uploading...
Running chef-solo...
[] INFO: Forking chef instance to converge...
[] INFO: *** Chef 11.10.4 ***
[] INFO: Chef-client pid: 3042
[] INFO: Setting the run_list to ["recipe[web]"] from JSON
[] INFO: Run List is [recipe[web]]
[] INFO: Run List expands to [web]
[] INFO: Starting Chef Run for ex05
[] INFO: Running start handlers
[] INFO: Start handlers complete.
[] INFO: ohai plugins will be at: /etc/chef/ohai_plugins
[] INFO: ohai[custom_plugins] reloaded
when using the vagrant librarian-chef plugin you will see:
[default] Installing Chef cookbooks with Librarian-Chef...
Vagrant output -> chef converge
[] INFO: package[nginx] installing nginx-1.0.15-5.el6 from epel repository
[] INFO: package[nginx] sending reload action to ohai[reload_nginx] (immediate)
[] INFO: ohai[reload_nginx] reloaded
[] INFO: service[nginx] enabled
[] INFO: directory[/var/log/nginx] mode changed to 755
[] INFO: directory[/etc/nginx/sites-available] created directory /etc/nginx/sites-available
[] INFO: directory[/etc/nginx/sites-available] owner changed to 0
[] INFO: directory[/etc/nginx/sites-available] group changed to 0
[] INFO: directory[/etc/nginx/sites-available] mode changed to 755
[] INFO: directory[/etc/nginx/sites-enabled] created directory /etc/nginx/sites-enabled
[] INFO: directory[/etc/nginx/sites-enabled] owner changed to 0
[] INFO: directory[/etc/nginx/sites-enabled] group changed to 0
[] INFO: directory[/etc/nginx/sites-enabled] mode changed to 755
[] INFO: execute[nxensite default] ran successfully
[] INFO: execute[nxensite default] not queuing delayed action reload on service[nginx] (delayed), as it's already been queued
[] INFO: service[nginx] started
[] INFO: directory[/var/www/nginx/demo] created directory /var/www/nginx/demo
[] INFO: directory[/var/www/nginx/demo] owner changed to 497
[] INFO: directory[/var/www/nginx/demo] group changed to 497
Note the "(delayed)" in the service restart
Notify immediately / delayed:
By default, notifications are :delayed, that is they are queued up as they are triggered, and then executed at the very end of a chef-client run. To run an action immediately, use :immediately:
[] INFO: template[/etc/nginx/sites-available/demo-site] created file /etc/nginx/sites-available/demo-site
[] INFO: template[/etc/nginx/sites-available/demo-site] updated file contents /etc/nginx/sites-available/demo-site
[] INFO: template[/etc/nginx/sites-available/demo-site] owner changed to 0
[] INFO: template[/etc/nginx/sites-available/demo-site] group changed to 0
[] INFO: template[/etc/nginx/sites-available/demo-site] mode changed to 644
[] INFO: template[/var/www/nginx/demo/index.html] created file /var/www/nginx/demo/index.html
[] INFO: template[/var/www/nginx/demo/index.html] updated file contents /var/www/nginx/demo/index.html
[] INFO: template[/var/www/nginx/demo/index.html] owner changed to 497
[] INFO: template[/var/www/nginx/demo/index.html] group changed to 497
[] INFO: execute[nxensite demo-site] ran successfully
[] INFO: execute[nxensite demo-site] not queuing delayed action reload on service[nginx] (delayed), as it's already been queued
[] INFO: service[iptables] disabled
[] INFO: template[nginx.conf] sending reload action to service[nginx] (delayed)
[] INFO: service[nginx] reloaded
[] INFO: template[/etc/nginx/sites-available/demo-site] sending restart action to service[nginx] (delayed)
[] INFO: service[nginx] restarted
[] INFO: Chef Run complete in 28.387247187 seconds
[] INFO: Running report handlers
[] INFO: Report handlers complete
Disabled iptables (just in case ...)
Reload nginx service
The long answer is it depends ...
Worth noting
Think of chef solo as the entire "chef-server" in a repository
.
├── README.md
├── centos_node
│ ├── Vagrantfile
│ └── bootstrap.sh
├── chef-server
│ ├── Vagrantfile
│ ├── bootstrap.sh
│ └── knife-config.sh
└── ubutnu_node
├── Vagrantfile
└── bootstrap.sh
Available @ chef_workshop
on Github
[ see chef_server_rotute directory ]
We will have a chef server + 2 nodes - 1 centos, 1 ubuntu all on VirtualBox
git clone git://github.com/opscode/chef-repo.git
Provides a directory layout to be used in conjunction with knife to:
pull down / upload cookbooks
Create nodes / roles / environments etc
see example in this workshop:
install from master using chef-solo ...
cd chef_workshop/chef_server_route/chef_server
vagrant up
In 3-5 minuets you have a chef server installed and chef_repo cloned under the root users directory !
The "magic" is in the ./bootstrap.sh & ./knife-config.sh files
# create required bootstrap dirs/files
mkdir -p /var/chef/cache /var/chef/cookbooks/chef-server
# pull down this chef-server cookbook
wget -qO- https://github.com/opscode-cookbooks/chef-server/archive/master.tar.gz | tar xvzC /var/chef/cookbooks/chef-server --strip-components=1
# install chef server with chef solo
chef-solo -o 'recipe[chef-server::default]'
Download the master bundle in to chef's
default directories and invoke chef-solo ...
In this workshop the chef workstation will reside on our chef server
#!/bin/bash
[[ -z "$DEBUG" ]] && set -x || set -e
# we need git on the image to set the cookbook path in knife.rb
[[ `which git` ]] || apt-get -y install git
# clone the repo ... [myself :)]
test -d /root/chef_repo || git clone https://github.com/tikalk-cookbooks/chef-intro-repo.git /root/chef_repo
cd /etc/bash_completion.d/
test -f knife.sh || wget https://gist.github.com/raw/1050685/23624fff40694d5ed5f55089774d13b1937bb37f/knife.sh
install git, checkout the chef-repo for this example
Manual instructions how to configure knife ...*
knife configure --admin-client-name admin --admin-client-key \
/etc/chef-server/admin.pem -i -r /root/chef_repo/ \
--validation-client-name chef-validator --validation-key \
/etc/chef-server/chef-validator.pem
This is relevant to our example, in most cases you will
knife configure -i
In a "real life" situation you will need a copy of the pem files
root@chef-srv:~# knife configure --admin-client-name admin --admin-client-key /etc/chef-server/admin.pem -i -r /root/chef_repo/ --validation-client-name chef-validator --validation-key /etc/chef-server/chef-validator.pem
WARNING: No knife configuration file found
Where should I put the config file? [/root/.chef/knife.rb]
Please enter the chef server URL: [https://chef-srv:443] https://192.168.56.101:443
Please enter a name for the new user: [vagrant]
Creating initial API user...
Please enter a password for the new user:
Created user[vagrant]
Configuration file written to /root/.chef/knife.rb
please use your ip int the chef server url "https://ipaddress:443"
log_level :info
log_location STDOUT
node_name 'vagrant'
client_key '/root/.chef/vagrant.pem'
validation_client_name 'chef-validator'
validation_key '/etc/chef-server/chef-validator.pem'
chef_server_url 'https://192.168.56.101:443'
syntax_check_cache_path '/root/.chef/syntax_check_cache'
cookbook_path [ '/root/chef_repo//cookbooks' ]
Provision a centos / ubuntu node via Vagrant ...
cd chef_workshop/chef_server_route/centos_node
vagrant up
cd chef_workshop/chef_server_route/ubutnu_node
vagrant up
once they are up and running connect to your chef workstation
root@chef-srv:~/chef_repo$ cat roles/base.json
{
"name": "base",
"description": "",
"json_class": "Chef::Role",
"default_attributes": {
},
"override_attributes": {
"chef_client": {
"server_url": "http://192.168.56.101:443"
}
},
"chef_type": "role",
"run_list": [
"recipe[ntp]",
"recipe[chef-client]",
"recipe[chef-client::delete_validation]"
],
"env_run_lists": {
}
}
sudo -i
cd ~/chef_repo
Upload role to server:
root@chef-srv:~/chef_repo$ knife role from file roles/base.json
Updated Role base!
list exiting roles on the server
root@chef-srv:~/chef_repo$ knife role list
base
Connect back to chef-server / workstation and provision nodes
# Bootstrap nodes
centos node ::
knife bootstrap 192.168.56.103 -x opencm -P opencm -r 'role[base]' --sudo
ubtunu node ::
knife bootstrap 192.168.56.104 -x opencm -P opencm -r 'role[base]' --sudo
opencm is a user defined on the nodes ...
(during vagrant provision)
scroll to view output ...
root@chef-srv:~/chef_repo# knife bootstrap 192.168.56.104 -x opencm -P opencm -r 'role[base]' --sudo
Bootstrapping Chef on 192.168.56.104
192.168.56.104 Starting Chef Client, version 11.10.4
192.168.56.104 resolving cookbooks for run list: ["ntp", "chef-client", "chef-client::delete_validation"]
192.168.56.104 Synchronizing Cookbooks:
192.168.56.104 - chef-client
192.168.56.104 - ntp
192.168.56.104 Compiling Cookbooks...
192.168.56.104 [2014-02-22T21:32:59+00:00] WARN: Chef::Mixin::Language is deprecated. Use either (or both)
192.168.56.104 Chef::DSL::PlatformIntrospection or Chef::DSL::DataQuery instead.
192.168.56.104
192.168.56.104 [2014-02-22T21:32:59+00:00] WARN: Called from:
192.168.56.104 /var/chef/cache/cookbooks/chef-client/libraries/helpers.rb:23:in `'
192.168.56.104 /var/chef/cache/cookbooks/chef-client/libraries/helpers.rb:22:in `'
192.168.56.104 /var/chef/cache/cookbooks/chef-client/libraries/helpers.rb:21:in `'
192.168.56.104 Converging 12 resources
192.168.56.104 Recipe: ntp::default
192.168.56.104 * package[ntp] action install
192.168.56.104 - install version 1:4.2.6.p3+dfsg-1ubuntu3.1 of package ntp
192.168.56.104
192.168.56.104 * service[ntp] action enable (up to date)
192.168.56.104 * service[ntp] action start (up to date)
192.168.56.104 * service[ntp] action restart
192.168.56.104 - restart service service[ntp]
192.168.56.104
192.168.56.104 * template[/etc/ntp.conf] action create
192.168.56.104 - update content in file /etc/ntp.conf from 4eb9a0 to a95b85
192.168.56.104 --- /etc/ntp.conf 2012-06-05 20:12:18.000000000 +0000
192.168.56.104 +++ /tmp/chef-rendered-template20140222-2637-u4910c 2014-02-22 21:33:04.957012896 +0000
192.168.56.104 @@ -1,56 +1,24 @@
192.168.56.104 -# /etc/ntp.conf, configuration for ntpd; see ntp.conf(5) for help
192.168.56.104 +# Generated by Chef for node2
192.168.56.104 +# node[:fqdn] = ohai data collected on node !
192.168.56.104 +# Local modifications will be overwritten.
192.168.56.104
192.168.56.104 -driftfile /var/lib/ntp/ntp.drift
192.168.56.104 +restrict -6 ::1
192.168.56.104 +#server
192.168.56.104
192.168.56.104 + server 0.pool.ntp.org iburst
192.168.56.104 + restrict 0.pool.ntp.org nomodify notrap noquery
192.168.56.104 + server 1.pool.ntp.org iburst
192.168.56.104 + restrict 1.pool.ntp.org nomodify notrap noquery
192.168.56.104 + server 2.pool.ntp.org iburst
192.168.56.104 + restrict 2.pool.ntp.org nomodify notrap noquery
192.168.56.104 + server 3.pool.ntp.org iburst
192.168.56.104 + restrict 3.pool.ntp.org nomodify notrap noquery
192.168.56.104
192.168.56.104 -# Enable this if you want statistics to be logged.
192.168.56.104 -#statsdir /var/log/ntpstats/
192.168.56.104 -
192.168.56.104 -statistics loopstats peerstats clockstats
192.168.56.104 -filegen loopstats file loopstats type day enable
192.168.56.104 -filegen peerstats file peerstats type day enable
192.168.56.104 -filegen clockstats file clockstats type day enable
192.168.56.104 -
192.168.56.104 -# Specify one or more NTP servers.
192.168.56.104 -
192.168.56.104 -# Use servers from the NTP Pool Project. Approved by Ubuntu Technical Board
192.168.56.104 -# on 2011-02-08 (LP: #104525). See http://www.pool.ntp.org/join.html for
192.168.56.104 -# more information.
192.168.56.104 -server 0.ubuntu.pool.ntp.org
192.168.56.104 -server 1.ubuntu.pool.ntp.org
192.168.56.104 -server 2.ubuntu.pool.ntp.org
192.168.56.104 -server 3.ubuntu.pool.ntp.org
192.168.56.104 -
192.168.56.104 -# Use Ubuntu's ntp server as a fallback.
192.168.56.104 -server ntp.ubuntu.com
192.168.56.104 -
192.168.56.104 -# Access control configuration; see /usr/share/doc/ntp-doc/html/accopt.html for
192.168.56.104 -# details. The web page
192.168.56.104 -# might also be helpful.
192.168.56.104 -#
192.168.56.104 -# Note that "restrict" applies to both servers and clients, so a configuration
192.168.56.104 -# that might be intended to block requests from certain clients could also end
192.168.56.104 -# up blocking replies from your own upstream servers.
192.168.56.104 -
192.168.56.104 -# By default, exchange time with everybody, but don't allow configuration.
192.168.56.104 -restrict -4 default kod notrap nomodify nopeer noquery
192.168.56.104 -restrict -6 default kod notrap nomodify nopeer noquery
192.168.56.104 -
192.168.56.104 -# Local users may interrogate the ntp server more closely.
192.168.56.104 +restrict default kod nomodify notrap nopeer noquery
192.168.56.104 +restrict -6 default kod nomodify notrap nopeer noquery
192.168.56.104 restrict 127.0.0.1
192.168.56.104 -restrict ::1
192.168.56.104
192.168.56.104 -# Clients from this (example!) subnet have unlimited access, but only if
192.168.56.104 -# cryptographically authenticated.
192.168.56.104 -#restrict 192.168.123.0 mask 255.255.255.0 notrust
192.168.56.104 -
192.168.56.104 -
192.168.56.104 -# If you want to provide time to your local subnet, change the next line.
192.168.56.104 -# (Again, the address is an example only.)
192.168.56.104 -#broadcast 192.168.123.255
192.168.56.104 -
192.168.56.104 -# If you want to listen to time broadcasts on your local subnet, de-comment the
192.168.56.104 -# next lines. Please do this only if you trust everybody on the network!
192.168.56.104 -#disable auth
192.168.56.104 -#broadcastclient
192.168.56.104 +server 127.127.1.0 # local clock
192.168.56.104 +driftfile /var/lib/ntp/drift
192.168.56.104 +keys /etc/ntp/keys
192.168.56.104
192.168.56.104 Recipe: chef-client::service
192.168.56.104 * directory[/var/run/chef] action create
192.168.56.104 - create new directory /var/run/chef
192.168.56.104 - change mode from '' to '0755'
192.168.56.104 - change owner from '' to 'root'
192.168.56.104 - change group from '' to 'root'
192.168.56.104
192.168.56.104 * directory[/var/cache/chef] action create
192.168.56.104 - create new directory /var/cache/chef
192.168.56.104 - change mode from '' to '0755'
192.168.56.104 - change owner from '' to 'root'
192.168.56.104 - change group from '' to 'root'
192.168.56.104
192.168.56.104 * directory[/var/lib/chef] action create
192.168.56.104 - create new directory /var/lib/chef
192.168.56.104 - change mode from '' to '0755'
192.168.56.104 - change owner from '' to 'root'
192.168.56.104 - change group from '' to 'root'
192.168.56.104
192.168.56.104 * directory[/var/log/chef] action create
192.168.56.104 - create new directory /var/log/chef
192.168.56.104 - change mode from '' to '0750'
192.168.56.104 - change owner from '' to 'root'
192.168.56.104 - change group from '' to 'root'
192.168.56.104
192.168.56.104 * directory[/etc/chef] action create (up to date)
192.168.56.104 * template[/etc/init.d/chef-client] action create
192.168.56.104 - create new file /etc/init.d/chef-client
192.168.56.104 - update content in file /etc/init.d/chef-client from none to 120a45
192.168.56.104 --- /etc/init.d/chef-client 2014-02-22 21:33:05.021019559 +0000
192.168.56.104 +++ /tmp/chef-rendered-template20140222-2637-1nzg8iy 2014-02-22 21:33:05.021019559 +0000
192.168.56.104 @@ -1 +1,186 @@
192.168.56.104 +#! /bin/sh
192.168.56.104 +### BEGIN INIT INFO
192.168.56.104 +# Provides: chef-client
192.168.56.104 +# Required-Start: $remote_fs $network
192.168.56.104 +# Required-Stop: $remote_fs $network
192.168.56.104 +# Default-Start: 2 3 4 5
192.168.56.104 +# Default-Stop: 0 1 6
192.168.56.104 +# Short-Description: Start a chef-client.
192.168.56.104 +### END INIT INFO
192.168.56.104 +#
192.168.56.104 +# Copyright (c) 2009-2010 Opscode, Inc,
192.168.56.104 +#
192.168.56.104 +# chef-client Startup script for chef-client.
192.168.56.104 +# chkconfig: - 99 02
192.168.56.104 +# description: starts up chef-client in daemon mode.
192.168.56.104 +
192.168.56.104 +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
192.168.56.104 +DAEMON=/usr/bin/chef-client
192.168.56.104 +NAME=chef-client
192.168.56.104 +DESC=chef-client
192.168.56.104 +PIDFILE=/var/run/chef/client.pid
192.168.56.104 +
192.168.56.104 +test -x $DAEMON || exit 1
192.168.56.104 +
192.168.56.104 +. /lib/lsb/init-functions
192.168.56.104 +
192.168.56.104 +[ -r /etc/default/$NAME ] && . /etc/default/$NAME
192.168.56.104 +
192.168.56.104 +if [ ! -d /var/run/chef ]; then
192.168.56.104 + mkdir /var/run/chef
192.168.56.104 +fi
192.168.56.104 +
192.168.56.104 +DAEMON_OPTS="-d -P $PIDFILE -L $LOGFILE -c $CONFIG -i $INTERVAL -s $SPLAY "
192.168.56.104 +
192.168.56.104 +running_pid() {
192.168.56.104 + pid=$1
192.168.56.104 + name=$2
192.168.56.104 + [ -z "$pid" ] && return 1
192.168.56.104 + [ ! -d /proc/$pid ] && return 1
192.168.56.104 + cmd=`awk '/Name:/ {print $2}' /proc/$pid/status`
192.168.56.104 + [ "$cmd" != "$name" ] && return 1
192.168.56.104 + return 0
192.168.56.104 +}
192.168.56.104 +
192.168.56.104 +running() {
192.168.56.104 + [ ! -f "$PIDFILE" ] && return 1
192.168.56.104 + pid=`cat $PIDFILE`
192.168.56.104 + running_pid $pid $NAME || return 1
192.168.56.104 + return 0
192.168.56.104 +}
192.168.56.104 +
192.168.56.104 +start_server() {
192.168.56.104 + if [ -z "$DAEMONUSER" ] ; then
192.168.56.104 + start_daemon -p $PIDFILE $DAEMON $DAEMON_OPTS
192.168.56.104 + errcode=$?
192.168.56.104 + else
192.168.56.104 + start-stop-daemon --start --quiet --pidfile $PIDFILE \
192.168.56.104 + --chuid $DAEMONUSER \
192.168.56.104 + --exec $DAEMON -- $DAEMON_OPTS
192.168.56.104 + errcode=$?
192.168.56.104 + fi
192.168.56.104 + return $errcode
192.168.56.104 +}
192.168.56.104 +
192.168.56.104 +stop_server() {
192.168.56.104 + if [ -z "$DAEMONUSER" ] ; then
192.168.56.104 + killproc -p $PIDFILE $DAEMON
192.168.56.104 + errcode=$?
192.168.56.104 + else
192.168.56.104 + start-stop-daemon --stop --quiet --pidfile $PIDFILE \
192.168.56.104 + --user $DAEMONUSER \
192.168.56.104 + --exec $DAEMON
192.168.56.104 + errcode=$?
192.168.56.104 + fi
192.168.56.104 + return $errcode
192.168.56.104 +}
192.168.56.104 +
192.168.56.104 +reload_server() {
192.168.56.104 + if [ -z "$DAEMONUSER" ] ; then
192.168.56.104 + killproc -p $PIDFILE $DAEMON -HUP
192.168.56.104 + errcode=$?
192.168.56.104 + else
192.168.56.104 + start-stop-daemon --stop --signal HUP --quiet --pidfile $PIDFILE \
192.168.56.104 + --user $DAEMONUSER \
192.168.56.104 + --exec $DAEMON
192.168.56.104 + errcode=$?
192.168.56.104 + fi
192.168.56.104 + return $errcode
192.168.56.104 +}
192.168.56.104 +
192.168.56.104 +force_stop() {
192.168.56.104 + [ ! -e "$PIDFILE" ] && return
192.168.56.104 + if running ; then
192.168.56.104 + /bin/kill -15 $pid
192.168.56.104 + sleep "$DIETIME"s
192.168.56.104 + if running ; then
192.168.56.104 + /bin/kill -9 $pid
192.168.56.104 + sleep "$DIETIME"s
192.168.56.104 + if running ; then
192.168.56.104 + echo "Cannot kill $NAME (pid=$pid)!"
192.168.56.104 + exit 1
192.168.56.104 + fi
192.168.56.104 + fi
192.168.56.104 + fi
192.168.56.104 + rm -f $PIDFILE
192.168.56.104 +}
192.168.56.104 +
192.168.56.104 +case "$1" in
192.168.56.104 + start)
192.168.56.104 + log_daemon_msg "Starting $DESC " "$NAME"
192.168.56.104 + if running ; then
192.168.56.104 + log_progress_msg "apparently already running"
192.168.56.104 + log_end_msg 0
192.168.56.104 + exit 0
192.168.56.104 + fi
192.168.56.104 + if start_server ; then
192.168.56.104 + [ -n "$STARTTIME" ] && sleep $STARTTIME # Wait some time
192.168.56.104 + if running ; then
192.168.56.104 + log_end_msg 0
192.168.56.104 + else
192.168.56.104 + log_end_msg 1
192.168.56.104 + fi
192.168.56.104 + else
192.168.56.104 + log_end_msg 1
192.168.56.104 + fi
192.168.56.104 + ;;
192.168.56.104 + stop)
192.168.56.104 + log_daemon_msg "Stopping $DESC" "$NAME"
192.168.56.104 + if running ; then
192.168.56.104 + errcode=0
192.168.56.104 + stop_server || errcode=$?
192.168.56.104 + log_end_msg $errcode
192.168.56.104 + else
192.168.56.104 + log_progress_msg "apparently not running"
192.168.56.104 + log_end_msg 0
192.168.56.104 + exit 0
192.168.56.104 + fi
192.168.56.104 + ;;
192.168.56.104 + force-stop)
192.168.56.104 + $0 stop
192.168.56.104 + if running; then
192.168.56.104 + log_daemon_msg "Stopping (force) $DESC" "$NAME"
192.168.56.104 + errcode=0
192.168.56.104 + force_stop || errcode=$?
192.168.56.104 + log_end_msg $errcode
192.168.56.104 + fi
192.168.56.104 + ;;
192.168.56.104 + restart|force-reload)
192.168.56.104 + log_daemon_msg "Restarting $DESC" "$NAME"
192.168.56.104 + errcode=0
192.168.56.104 + stop_server || errcode=$?
192.168.56.104 + [ -n "$DIETIME" ] && sleep $DIETIME
192.168.56.104 + start_server || errcode=$?
192.168.56.104 + [ -n "$STARTTIME" ] && sleep $STARTTIME
192.168.56.104 + running || errcode=$?
192.168.56.104 + log_end_msg $errcode
192.168.56.104 + ;;
192.168.56.104 + status)
192.168.56.104 + log_daemon_msg "Checking status of $DESC" "$NAME"
192.168.56.104 + if running ; then
192.168.56.104 + log_progress_msg "running"
192.168.56.104 + log_end_msg 0
192.168.56.104 + else
192.168.56.104 + log_progress_msg "apparently not running"
192.168.56.104 + log_end_msg 1
192.168.56.104 + exit 3
192.168.56.104 + fi
192.168.56.104 + ;;
192.168.56.104 + reload)
192.168.56.104 + if running; then
192.168.56.104 + log_daemon_msg "Reloading $DESC" "$NAME"
192.168.56.104 + errcode=0
192.168.56.104 + reload_server || errcode=$?
192.168.56.104 + log_end_msg $errcode
192.168.56.104 + fi
192.168.56.104 + ;;
192.168.56.104 + *)
192.168.56.104 + N=/etc/init.d/$NAME
192.168.56.104 + echo "Usage: $N {start|stop|force-stop|restart|force-reload|status}" >&2
192.168.56.104 + exit 1
192.168.56.104 + ;;
192.168.56.104 +esac
192.168.56.104 +
192.168.56.104 +exit 0
192.168.56.104 +
192.168.56.104 - change mode from '' to '0755'
192.168.56.104
192.168.56.104 * template[/etc/default/chef-client] action create
192.168.56.104 - create new file /etc/default/chef-client
192.168.56.104 - update content in file /etc/default/chef-client from none to 13b3d0
192.168.56.104 --- /etc/default/chef-client 2014-02-22 21:33:05.073020993 +0000
192.168.56.104 +++ /tmp/chef-rendered-template20140222-2637-tvy22g 2014-02-22 21:33:05.073020993 +0000
192.168.56.104 @@ -1 +1,5 @@
192.168.56.104 +LOGFILE=/var/log/chef/client.log
192.168.56.104 +CONFIG=/etc/chef/client.rb
192.168.56.104 +INTERVAL=1800
192.168.56.104 +SPLAY=20
192.168.56.104 - change mode from '' to '0644'
192.168.56.104
192.168.56.104 * service[chef-client] action enable
192.168.56.104 - enable service service[chef-client]
192.168.56.104
192.168.56.104 Recipe: chef-client::delete_validation
192.168.56.104 * file[/etc/chef/validation.pem] action delete
192.168.56.104 - delete file /etc/chef/validation.pem
192.168.56.104
192.168.56.104 Recipe: ntp::default
192.168.56.104 * service[ntp] action restart
192.168.56.104 - restart service service[ntp]
192.168.56.104
192.168.56.104 Recipe: chef-client::service
192.168.56.104 * service[chef-client] action restart
192.168.56.104 - restart service service[chef-client]
192.168.56.104
192.168.56.104
192.168.56.104 Running handlers:
192.168.56.104 Running handlers complete
192.168.56.104
192.168.56.104 Chef Client finished, 13/16 resources updated in 8.521233887 seconds
expect it to fail the first time see next slide ...
we didn't upload the cookbooks to our chef server
knife cookbook upload ntp
knife cookbook upload chef-client
output
root@chef-srv:~/chef_repo# knife cookbook upload ntp
Uploading ntp [0.1.1]
Uploaded 1 cookbook.
root@chef-srv:~/chef_repo# knife cookbook upload chef-client
Uploading chef-client [2.1.6]
Uploaded 1 cookbook.
Connect back to chef-server / workstation and provision nodes
# Bootstrap nodes
centos node ::
knife bootstrap 192.168.56.103 -x opencm -P opencm -r 'role[base]' --sudo
ubtunu node ::
knife bootstrap 192.168.56.104 -x opencm -P opencm -r 'role[base]' --sudo
opencm is a user defined on the nodes ...
(during vagrant provision)
.
├── README.md
├── centos_node
│ ├── Vagrantfile
│ └── bootstrap.sh
└── ubutnu_node
├── Vagrantfile
└── bootstrap.sh
Avialble @ chef_workshop
on Github
[ see chef_solo_route directory ]
Use anyone you like - ubuntu / cnetos
.
├── .chef/knife.rb
├── .git
├── .gitignore
├── Cheffile
├── Gemfile
├── README.md
├── nodes
├── roles
├── site-cookbooks
└── solo.rb
Provides a place for all chef objects [ nodes, roles, databags ]
base_dir = File.expand_path('../', __FILE__)
cookbook_path [File.join(base_dir, 'cookbooks'), File.join(base_dir, 'site-cookbooks')]
role_path File.join(base_dir, 'roles')
data_bag_path File.join(base_dir, 'data_bags')
file_cache_path file_cache_path File.join(base_dir, 'tmp')
# Default json
json_attribs File.join(base_dir, 'nodes', 'default.json')
Defines:
Looks familiar ?
Vagrant file creates the solo.rb configuration ...
config.vm.provision :chef_solo do |chef|
chef.cookbooks_path = ["cookbooks", "site-cookbooks"]
chef.roles_path = ["roles"]
chef.log_level = ENV['CHEF_LOG'] ? ENV['CHEF_LOG'].to_sym : :info
chef.add_role "web"
end
chef-solo -c <solo-config> -j node.json
Now in our case we used:
json_attribs File.join(base_dir, 'nodes', 'default.json')
So:
{
"run_list": [
"role[default]"
]
}
Will use:
name "default"
description "The basic stuff any server needs - rpm repos, users, etc etc ..."
run_list "recipe[yum::yum]", "recipe[base]"
override_attributes({
:yum => {
:repoforge_release => '0.5.3-1'
}
})
gem "knife-solo"
gem "librarian-chef"
gem "knife-solo_data_bag"
config.vm.provision "shell", inline: "[[ `which chef-solo` ]] || curl -L https://www.opscode.com/chef/install.sh | sudo bash"
config.vm.provision :chef_solo do |chef|
chef.cookbooks_path = ["cookbooks", "site-cookbooks"]
chef.roles_path = ["roles"]
chef.log_level = ENV['CHEF_LOG'] ? ENV['CHEF_LOG'].to_sym : :info
chef.add_role "web"
end
Two provisioners in this example:
Everything (including these slides) are on