I’m an intermediate/advanced chef user. My main usage has been as a client of the services that chef provides, and not operating the server. My comfort zone is that I am very happy to write and hack on fairly complicated chef cookbooks, LWRPs, and chef-solo work, but I don’t work much with the chef server - I’ve opted to use the hosted service in the past, and very much enjoyed the service.
I’m interested in saltstack. When I first started working with chef in 2011, saltstack was very new, so I learned chef, as the more mature option (though it was still fairly new). Now salt is in a fairly mature phase where it seems to be able to handle the same classes of installation and configuration management that I’ve seen chef work with in the past. This impression is backed up by users of Salt who are clearly using it in their day-to-day operations. So I’m trying it out.
-
Setting up a server (vs. hosted chef)
-
Setting up a client
-
A first run
-
Automating the first run
-
-
What is a chef role in salt
-
What is a chef environment in salt
-
Discovering node data ala ohai : grains
-
Custom attributes of ohai vs. grains
-
-
List registered OS instances
-
Query richer data from registered OS instances.
-
Search for nodes interactively
-
Perform runs (chef) and run sub-sections of a full run (salt)
Saltstack can be installed from a saltstack ppa. This is routine stuff for a ubuntu system.
Once the server packages were installed, I created the default directories:
# mkdir -p /srv/salt
Once this is installed, the top
salt state should be created to provide a default action as a first test. I’ll work off an example that installs emacs by default.
base:
'*':
- emacs.install
emacs:
pkg.installed
Instead of a starting json document per chef, the highstate is run in order to determine, server-side, what actions will be run on the client.
The chef server instructions are at the chef docs site. Since I’m not familiar with operating the chef server, and haven’t done anything with the modern erchef server (the erlang implementation of the server) I’m not going to write any further about this.
Install the client via adding a ppa:
# add-apt-repository ppa:saltstack/salt # apt-get --yes -q update [...] # apt-get --yes install salt-minion
Then replace the default master info with that of the master you’ve actually got and run the minion, e.g.:
# sed -i 's/#master: salt/master: 10.0.2.4/' /etc/salt/minion # service salt-minion restart
Then on the master, list the keys, then accept the key:
salt-master# salt-key -L Accepted Keys: salt-master Unaccepted Keys: trusty-saltclient1 Rejected Keys: salt-master# salt-key -a trusty-saltclient1 The following keys are going to be accepted: Unaccepted Keys: trusty-saltclient1 Proceed? [n/Y] Y Key for minion trusty-saltclient1 accepted. salt-master#
Until this is accepted, the minion will sit and re-try every 10 seconds. Once this is accepted the minion will run in the background.
Chef provides what are called "omnibus" installations, where they provide a package/packages that cover the installation of not only the chef code, but of the ruby runtime and required gems, which they curate. The installation can be done in a slightly simpler manner if you’re willing to do a curl url | sh
invocation. Not everyone is comfortable with that.
With chef, adding a node is normally done by copying the validator key to /etc/chef/validator.pem
, creating /etc/chef/client.rb
and defining the first run with e.g. /etc/chef/first-run.json
though the location could be anywhere.
After setting up the pieces, the node can be registered with a first run with chef-client -j /etc/chef/first-run.json
To automate running the appropriate action for a new installation, saltstack has reactors - that is, the default action for a newly connected system is not to do anything specific. This can be changed via the reactor system, which can instruct a new system to run a set of tasks.
Chef will normally be run as part of a workflow where the chef client will run, and if the client’s pem file doesn’t exist to authenticate it, it will attempt to create a new client for itself, and use the new client for a first run.
Once the client is created, the first run will proceed with the new node being created empty (on the server) and automatic data populated on the client.