This talk is an exploration of how to build Chef Server 12 clusters with Chef Provisioning, including premium features like Chef Reporting and Chef Analytics. I will cover several new capabilities and tools in the Chef ecosystem that makes it easier than ever before to build and manage scalable Chef Server clusters.
https://youtu.be/HUQA1Ikm5Iw
Powerpoint exploring the locations used in television show Time Clash
Chef Provisioning a Chef Server Cluster - ChefConf 2015
1.
2.
3. Chef Provisioning a Chef Server Cluster
Joshua Timberman
joshua@chef.io
@jtimberman
https://www.flickr.com/photos/jamidwyer/2844765976
4. Before we begin, provisioning a Chef Server:
• Run chef-client...
• Which talks to a different Chef Server...
• Which downloads a recipe that...
• Creates machines that run chef-client...
• That install Chef Server packages...
• Which then run chef-server-ctl reconfigure...
• Which runs chef-solo to configure the Chef Server
10. Bootstrap a Chef Server with Chef Solo
sudo
chef-‐solo
-‐c
/etc/chef/solo.rb
-‐j
~/chef.json
-‐r
http://s3.amazonaws.com/chef-‐solo/bootstrap-‐latest.tar.gz
11. As it turns out...
This is a pretty good idea!
https://www.flickr.com/photos/nao904/6084536885
12. chef-server-ctl reconfigure
frontend-‐chef-‐server%
sudo
chef-‐server-‐ctl
reconfigure
Starting
Chef
Client,
version
11.18.0
Compiling
Cookbooks...
Recipe:
private-‐chef::default
....
Recipe:
private-‐chef::default
*
file[/etc/opscode/chef-‐server-‐running.json]
action
create
(up
to
date)
Running
handlers:
Running
handlers
complete
Chef
Client
finished,
7/228
resources
updated
in
7.282379304
seconds
opscode
Reconfigured!
13. omnibus-ctl reconfigure...
def
reconfigure(exit_on_success=true)
status
=
run_command(
"chef-‐solo
-‐c
#{base_path}/embedded/cookbooks/solo.rb
-‐j
#{base_path}/embedded/cookbooks/dna.json"
)
if
status.success?
log
"#{display_name}
Reconfigured!"
exit!
0
if
exit_on_success
else
exit!
1
end
end
14. Hosted Chef... is different (and that's the problem)
• Built using Chef cookbooks
• (yay! ...but)
• Many forked community cookbooks
• (before berkshelf/librarian)
• One cookbook per component/service
• (postgresql, erchef, authz, rabbitmq, solr, etc)
• Growth over time
• (over 10k commits)
• Not the same as what customers use
• (chef-server-ctl reconfigure vs "knife ssh and chef-client")
16. Chef Server 12
"There is One Chef Server,
and it is Open Source"
- Adam Jacob
https://www.chef.io/blog/2014/09/08/there-is-one-chef-server-and-it-is-open-source/
17. You've probably heard this by now...
• Multi-tenancy - required feature for Hosted Chef
• Chef Push Jobs is opened now
• Remove tension between Open Source Chef and
Enterprise Chef codebase
• Remove tension between Hosted Enterprise Chef
and Enterprise Chef code, too
18. Current state: Installing
Chef Server 12
Or, "this is how you do it manually per the
documentation at docs.chef.io"
http://docs.chef.io/server/install_server.html
19. Installing Chef Server 12
sudo
dpkg
-‐i
chef-‐server-‐core*.deb
sudo
vi
/etc/opscode/chef-‐server.rb
sudo
chef-‐server-‐ctl
reconfigure
20. Or there's a cookbook for that...
curl
-‐L
https://www.chef.io/chef/install.sh
|
sudo
bash
sudo
mkdir
-‐p
/var/chef/cache
/var/chef/cookbooks
wget
-‐qO-‐
https://supermarket.chef.io/cookbooks/chef-‐server/
download
|
sudo
tar
xvzC
/var/chef/cookbooks
wget
-‐qO-‐
https://supermarket.chef.io/cookbooks/chef-‐server-‐
ingredient/download
|
sudo
tar
xvzC
/var/chef/cookbooks
wget
-‐qO-‐
https://supermarket.chef.io/cookbooks/packagecloud/
download
|
sudo
tar
xvzC
/var/chef/cookbooks
sudo
chef-‐solo
-‐o
'recipe[chef-‐server::default]'
21. But if you want a cluster...
##
On
the
first
node
("bootstrap
backend")
sudo
dpkg
-‐i
chef-‐server-‐core*.deb
sudo
vi
/etc/opscode/chef-‐server.rb
##
manage
some
server
blocks
for
the
cluster
per
docs
sudo
chef-‐server-‐ctl
reconfigure
sudo
rsync
-‐avz
/etc/opscode
root@frontend.example.com:/etc
##
On
the
second
node
("frontend")
sudo
dpkg
-‐i
chef-‐server-‐core*.deb
sudo
chef-‐server-‐ctl
reconfigure
23. Wait. What was that?
##
On
the
first
node
("bootstrap
backend")
sudo
dpkg
-‐i
chef-‐server-‐core*.deb
sudo
vi
/etc/opscode/chef-‐server.rb
##
manage
some
server
blocks
according
to
docs.chef.io...
sudo
chef-‐server-‐ctl
reconfigure
sudo
rsync
-‐avz
/etc/opscode
root@frontend.example.com:/etc
##
On
the
second
node
("frontend")
sudo
dpkg
-‐i
chef-‐server-‐core*.deb
sudo
chef-‐server-‐ctl
reconfigure
29. What is Chef Provisioning?
• Previously known as "Chef Metal"
• Manage machines as Chef resources
• Various provisioners available
• several come with ChefDK, e.g., aws, azure
• Available as rubygems
• Makes it easy to reason about standing up a cluster
30. Chef Provisioning has `machine` resources
machine
'database'
do
recipe
'example-‐postgresql::server'
end
machine
'cache'
do
recipe
'example-‐memcached'
end
machine
'www1'
do
recipe
'example-‐nginx'
end
machine
'www2'
do
recipe
'example-‐nginx
end
31. Chef Provisioning extends Chef's Recipe DSL
#
AWS
EC2...
with_driver('aws::us-‐west-‐2')
with_machine_options(
:bootstrap_options
=>
{
:key_name
=>
'hc-‐metal-‐provisioner',
:image_id
=>
'ami-‐b99ed989',
:instance_type
=>
'm3.medium'
}
)
#
Microsoft
Azure...
with_driver('azure')
with_machine_options(
:image_id
=>
'Ubuntu-‐14_04_1-‐LTS-‐amd64-‐server-‐20140927-‐en-‐us-‐30GB',
:bootstrap_options
=>
{
:vm_size
=>
'Standard_D1',
:other_options
=>
'Slides
are
only
so
big...'
}
)
32.
33. Chef Provisioning a Chef Server Cluster
machine
'backend'
do
recipe
'chef-‐server-‐cluster::bootstrap-‐backend'
end
machine
'frontend'
do
recipe
'chef-‐server-‐cluster::frontend'
end
machine
'analytics'
do
recipe
'chef-‐server-‐cluster::analytics'
end
44. Checkpoint!
• ./.chef/config.rb for knife and chef-client
• Uploaded cookbooks (using Policyfiles*)
• Uploaded data bags
• AWS authentication credentials in ~/.aws/config
• SSH private key in ~/.ssh/keyname
* Due to time constraints, Policyfile discussion is not appearing in this talk
45. Provisioner node run list
%
knife
node
show
chefconf-‐provisioner
Node
Name:
chefconf-‐provisioner
Environment:
_default
FQDN:
IP:
10.13.37.102
Run
List:
recipe[chef-‐server-‐cluster::cluster-‐provision]
Roles:
Recipes:
chef-‐server-‐cluster::cluster-‐provision,
chef-‐server-‐
cluster::setup-‐provisioner,
chef-‐server-‐cluster::setup-‐ssh-‐keys
Platform:
mac_os_x
10.10.2
Tags:
55. Merge the configuration
#
Merge
the
attributes
with
the
data
bag
values,
and
the
search
#
results
for
other
servers.
node.default['chef-‐server-‐cluster'].merge!(chef_server_config)
56. Configuration template
template '/etc/opscode/chef-server.rb' do
source 'chef-server.rb.erb'
variables(:chef_server_config => node['chef-server-cluster'],
:chef_servers => chef_servers)
notifies :reconfigure, 'chef_server_ingredient[chef-server-core]'
end
61. Rendered: analytics
topology
'standalone'
analytics_fqdn
'analytics.jtimberman.name'
Analytics config for the Chef Server is in:
/etc/opscode/analytics/actions-source.json
63. Configuration template
template '/etc/opscode/chef-server.rb' do
source 'chef-server.rb.erb'
variables(:chef_server_config => node['chef-server-cluster'],
:chef_servers => chef_servers)
notifies :reconfigure, 'chef_server_ingredient[chef-server-core]'
end
What is chef_server_ingredient??
64. chef-server-ingredient cookbook
• What is an ingredient?
• Clever, what's an addon?
• What does the cookbook do?
• How does the resource work?
• Primitive resource for installing/managing Chef Server
add-ons
65. This automates these manual steps
%
sudo
chef-‐server-‐ctl
install
opscode-‐manage
%
sudo
opscode-‐manage-‐ctl
reconfigure
66. chef_server_ingredient resources...
chef_server_ingredient
'chef-‐server-‐core'
do
notifies
:reconfigure,
'chef_server_ingredient[chef-‐server-‐core]'
end
chef_server_ingredient
'opscode-‐reporting'
do
notifies
:reconfigure,
'chef_server_ingredient[opscode-‐reporting]'
end
chef_server_ingredient
'opscode-‐manage'
do
notifies
:reconfigure,
'chef_server_ingredient[opscode-‐manage]'
end
chef_server_ingredient
'opscode-‐analytics'
do
notifies
:reconfigure,
'chef_server_ingredient[opscode-‐analytics]'
end
69. chef_server_ingredient
action
:install
do
packagecloud_repo
'chef/stable'
do
type
value_for_platform_family(:debian
=>
'deb',
:rhel
=>
'rpm')
end
package
new_resource.package_name
do
options
new_resource.options
version
new_resource.version
end
end
action
:reconfigure
do
ctl_cmd
=
ctl_command
execute
"#{new_resource.package_name}-‐reconfigure"
do
command
"#{ctl_cmd}
reconfigure"
end
end
70. Omnibus package pattern is consistent:
• Install the package
• Write the configuration*
• Run the reconfigure command
• Configuration can happen first - and does with the
Chef Provisioning recipes
* or rsync it from a node, RIGHT?
71. Remember this?
sudo
rsync
-‐avz
/etc/opscode
root@frontend.example.com:/etc
Hint: No one wants to remember this
72. Hello, machine_file!
%w{
actions-‐source.json
webui_priv.pem
}.each
do
|analytics_file|
machine_file
"/etc/opscode-‐analytics/#{analytics_file}"
do
local_path
"/tmp/stash/#{analytics_file}"
machine
'bootstrap-‐backend'
action
:download
end
end
%w{
pivotal.pem
webui_pub.pem
}.each
do
|opscode_file|
machine_file
"/etc/opscode/#{opscode_file}"
do
local_path
"/tmp/stash/#{opscode_file}"
machine
'bootstrap-‐backend'
action
:download
end
end
73. And the 'files' property of machine resource
machine
'frontend'
do
recipe
'chef-‐server-‐cluster::frontend'
action
:converge
converge
true
files('/etc/opscode/webui_priv.pem'
=>
'/tmp/stash/webui_priv.pem',
'/etc/opscode/webui_pub.pem'
=>
'/tmp/stash/webui_pub.pem',
'/etc/opscode/pivotal.pem'
=>
'/tmp/stash/pivotal.pem')
end
machine
'analytics'
do
recipe
'chef-‐server-‐cluster::analytics'
action
:converge
converge
true
files('/etc/opscode-‐analytics/actions-‐source.json'
=>
'/tmp/stash/actions-‐source.json',
'/etc/opscode-‐analytics/webui_priv.pem'
=>
'/tmp/stash/webui_priv.pem')
end
74. Sure, we could rsync in the recipe...
• But then we have to setup SSH keys between the
nodes
• And all files in /etc/opscode, including ones put there
by someone that shouldn't be there...
75. chef-client on the provisioner
%
CHEF_NODE=chefconf-‐provisioner
chef-‐client
-‐c
.chef/config.rb
Starting
Chef
Client,
version
12.0.3
[2015-‐02-‐18T14:28:12-‐07:00]
WARN:
Using
experimental
Policyfile
feature
resolving
cookbooks
for
run
list:
["chef-‐server-‐cluster::cluster-‐
provision@0.0.9
(e1e803c)"]
Synchronizing
Cookbooks:
-‐
chef-‐server-‐ingredient
-‐
chef-‐server-‐cluster
-‐
apt
-‐
packagecloud
-‐
chef-‐vault
Compiling
Cookbooks...
...
SNIP
converging
3
machines
...
Chef
Client
finished,
11/16
resources
updated
in
1248.519725
seconds
76. machine resources converging
*
machine[bootstrap-‐backend]
action
converge
-‐
Create
bootstrap-‐backend
with
AMI
ami-‐b99ed989
in
us-‐west-‐2
-‐
create
node
bootstrap-‐backend
at
https://api.opscode.com/organizations/jtimberman-‐chefconf
-‐
update
run_list
from
[]
to
["recipe[chef-‐server-‐cluster::bootstrap]"]
-‐
waiting
for
bootstrap-‐backend
(i-‐553a519c
on
aws::us-‐west-‐2)
to
be
connectable
-‐
bootstrap-‐backend
is
now
connectable
-‐
generate
private
key
(2048
bits)
-‐
create
directory
/etc/chef
on
bootstrap-‐backend
-‐
write
file
/etc/chef/client.pem
on
bootstrap-‐backend
-‐
create
client
bootstrap-‐backend
at
clients
-‐
add
public_key
=
"-‐-‐-‐-‐-‐BEGIN
PUBLIC
KEY-‐-‐-‐-‐-‐n...SNIP...-‐-‐-‐-‐-‐END
PUBLIC
KEY-‐-‐-‐-‐-‐n"
-‐
Add
bootstrap-‐backend
to
client
read
ACLs
-‐
Add
bootstrap-‐backend
to
client
update
ACLs
-‐
create
directory
/etc/chef/ohai/hints
on
bootstrap-‐backend
-‐
write
file
/etc/chef/ohai/hints/ec2.json
on
bootstrap-‐backend
-‐
write
file
/etc/chef/client.rb
on
bootstrap-‐backend
-‐
write
file
/tmp/chef-‐install.sh
on
bootstrap-‐backend
-‐
run
'bash
-‐c
'
bash
/tmp/chef-‐install.sh''
on
bootstrap-‐backend
[bootstrap-‐backend]
Starting
Chef
Client,
version
12.1.1
Chef
Client
finished,
25/32
resources
updated
in
453.570204517
seconds
-‐
run
'chef-‐client
-‐l
auto'
on
bootstrap-‐backend
77. Create and connect to EC2 instance
*
machine[bootstrap-‐backend]
action
converge
-‐
Create
bootstrap-‐backend
with
AMI
ami-‐b99ed989
in
us-‐west-‐2
-‐
create
node
bootstrap-‐backend
at
https://api.opscode.com/
organizations/jtimberman-‐chefconf
-‐
update
run_list
from
[]
to
["recipe[chef-‐server-‐
cluster::bootstrap]"]
-‐
waiting
for
bootstrap-‐backend
(i-‐553a519c
on
aws::us-‐west-‐2)
to
be
connectable
-‐
bootstrap-‐backend
is
now
connectable
78. Create the API client and give permission
*
machine[bootstrap-‐backend]
action
converge
-‐
generate
private
key
(2048
bits)
-‐
create
directory
/etc/chef
on
bootstrap-‐backend
-‐
write
file
/etc/chef/client.pem
on
bootstrap-‐backend
-‐
create
client
bootstrap-‐backend
at
clients
-‐
add
public_key
=
"RSA
Public
key
content"
-‐
Add
bootstrap-‐backend
to
client
read
ACLs
-‐
Add
bootstrap-‐backend
to
client
update
ACLs
79. Bootstrap like you may have seen...
*
machine[bootstrap-‐backend]
action
converge
-‐
create
directory
/etc/chef/ohai/hints
on
bootstrap-‐backend
-‐
write
file
/etc/chef/ohai/hints/ec2.json
on
bootstrap-‐backend
-‐
write
file
/etc/chef/client.rb
on
bootstrap-‐backend
-‐
write
file
/tmp/chef-‐install.sh
on
bootstrap-‐backend
-‐
run
'bash
-‐c
'
bash
/tmp/chef-‐install.sh''
on
bootstrap-‐
backend
[bootstrap-‐backend]
Starting
Chef
Client,
version
12.1.1
Chef
Client
finished,
25/32
resources
updated
in
453.57
seconds
-‐
run
'chef-‐client
-‐l
auto'
on
bootstrap-‐backend
80. machine files
*
machine_file[/etc/opscode-‐analytics/actions-‐source.json]
action
download
-‐
download
file
/etc/opscode-‐analytics/actions-‐source.json
on
bootstrap-‐backend
to
/tmp/stash/actions-‐source.json
*
machine_file[/etc/opscode-‐analytics/webui_priv.pem]
action
download
-‐
download
file
/etc/opscode-‐analytics/webui_priv.pem
on
bootstrap-‐backend
to
/tmp/stash/webui_priv.pem
*
machine_file[/etc/opscode/pivotal.pem]
action
download
-‐
download
file
/etc/opscode/pivotal.pem
on
bootstrap-‐backend
to
/tmp/stash/pivotal.pem
*
machine_file[/etc/opscode/webui_pub.pem]
action
download
-‐
download
file
/etc/opscode/webui_pub.pem
on
bootstrap-‐backend
to
/tmp/stash/webui_pub.pem
...SNIP
-‐
upload
file
/tmp/stash/webui_priv.pem
to
/etc/opscode/webui_priv.pem
on
frontend
-‐
upload
file
/tmp/stash/webui_pub.pem
to
/etc/opscode/webui_pub.pem
on
frontend
-‐
upload
file
/tmp/stash/pivotal.pem
to
/etc/opscode/pivotal.pem
on
frontend
82. Wrap-up and takeaways
• Chef Server 12 is totally what you want to use
• Using Chef to build Chef is awesome
• Chef Provisioning makes deploying to EC2 easy
• chef-server-cluster is a full working example
• chef-server-ingredient is a lower level primitive
• (and used by chef-server cookbook, too!)
• Build your own with chef-server-ingredient