In my last blog post I mentioned that SaltStack is a fully featured configuration management solution, but we never looked into using the tool in that way. Today we will begin to explore some basic examples of configuration management with SaltStack. We will look at two aspects of configuration management, installing a package, and will manage a service.
A great repeatable task which can be automated with configuration management, and one which is faced by many systems administrators is having to add more capacity to an existing front end webserver pool.
Without a configuration management solution, you generally have to rely on an install document that is maintained by your systems administration team. One of those admins gets the job of preparing the new box, and follows the steps in that document to install all of the required packages and configure all of the required services to make that box a “webserver”
This method introduces a high potential for human error. The person following the document might miss step #17 on page 3, and you end up with a webserver in the pool that delivers content to your users in a strange and inconsistent way. Depending on the maturity of your infrastructure, you also may or may not have the tools in place to even identify that the webserver is acting strangely due to this misconfiguration until clients begin to complain that your service delivers an unreliable experience.
From a resourcing point of view, this task can tie up 2 resources. The person doing the box install, and a second person you need to “QA” the box after the install is done to catch the fact that the first person missed step #17 on page 3.
Using a configuration management tool you define what your box should look like (a model) at a higher, abstracted level and the tool knows what is required to bring the server in line with it’s desired state. The tool does not need to be told that on a RedHat based system you use “yum” to install a package and on Debian systems you use “apt” as the operator you just say that the systems needs to have the package and the tool takes it from there.
By modelling your systems the tool can then provide accurate repeatability of the task of bringing your systems into line with the defined specifications of the model. And while this does shift the responsibility of eliminating any human error within the model itself, once it has been tested and validated the result is that each subsequent execution will be done programmatically without error.
Using SaltStack to install a package and manage a service
The first thing that we will need to do is tell the salt master that we would like to start using it for configuration management. We do this by uncommenting, or adding the following to our /etc/salt/master config:
file_roots: base: - /srv/salt
in the /srv directory as root make a “salt” subdir.
mkdir -p /srv/salt
Everything else, from this point forward will be written under the assumption that you are working in the /srv/salt dir.
In SALT the set of instructions, or “model” that you define is known as a formula. Salt uses PyYALM as it’s configuration syntax. The first thing that we need to defile a base formula called “top.sls”
base: '*': - motd 'web*': - apache - webserver
This tells salt that all boxes should have the motd formula and that minions with hostnames starting with “web” should also get the apache formula.
Our Apache formula (apache.sls) is very basic for the purposes of this post:
httpd: pkg: - installed service: - running - require: - pkg: httpd
This tells the minion that it needs to install the package named httpd (remember the minion knows how to do this) and that the service should be running and that the service has a dependency on the package being installed. That is to say, you can’t manage the service unless the package that provides that server also is there.
When we apply the formula you can see that the minion receives the instruction. The minion installs the package and it’s dependant packages. Then it starts the service.
[[email protected] salt]# salt '*' state.sls apache ip-10-0-0-171.ec2.internal: ---------- ID: httpd Function: pkg.installed Result: True Comment: The following packages were installed/updated: httpd. Changes: ---------- apr: ---------- new: 1.5.0-2.11.amzn1 old: apr-util: ---------- new: 1.4.1-4.14.amzn1 old: apr-util-ldap: ---------- new: 1.4.1-4.14.amzn1 old: httpd: ---------- new: 2.2.27-1.2.amzn1 old: httpd-tools: ---------- new: 2.2.27-1.2.amzn1 old: mailcap: ---------- new: 2.1.31-2.7.amzn1 old: ---------- ID: httpd Function: service.running Result: True Comment: Started Service httpd Changes: ---------- httpd: True Summary ------------ Succeeded: 2 Failed: 0 ------------ Total: 2
On subsequent runs, you can see that the package is already installed and the service is already running.
[[email protected] salt]# salt '*' state.sls apache ip-10-0-0-171.ec2.internal: ---------- ID: httpd Function: pkg.installed Result: True Comment: Package httpd is already installed Changes: ---------- ID: httpd Function: service.running Result: True Comment: The service httpd is already running Changes: Summary ------------ Succeeded: 2 Failed: 0 ------------ Total: 2
If either was not true, if I were to go onto the box and stop the service:
[[email protected] ~]# service httpd stop Stopping httpd: [ OK ] [[email protected] ~]#
The next salt run would start the service again bringing the box back into compliance with my defined model.
ip-10-0-0-171.ec2.internal: ---------- ID: httpd Function: pkg.installed Result: True Comment: Package httpd is already installed Changes: ---------- ID: httpd Function: service.running Result: True Comment: Started Service httpd Changes: ---------- httpd: True Summary ------------ Succeeded: 2 Failed: 0 ------------ Total: 2 [[email protected] ~]# service httpd status httpd (pid 2493) is running... [[email protected] ~]#
This becomes a powerful auditing tool which can allow you to quickly ensure that all boxes of a specific type match each other, and eliminates the above mentioned problem of missing step #17 on page 3 of your install doc. With the heavy lifting of this task moved from human operators to the tool, and knowing that each node will be built identical to the others you can now scale up much quicker in response to your changing business needs, a task which previously could take a few days is now done in minutes.