This article assumes that you are familiar with what is in the following list (or have read Part 1 of this series on Salt in the December 2014 edition of Open Source For You).
- Installing SaltStack
- Setting up master and minion
- Establishing a relationship between master and minion
In this column, we will look at how to actually use Salt to do some basic configuration management.
Basic Salt commands for documentation/help
Salt provides a wide range of system level documentation on how to use any of its modules.
salt * sys.doc (list all modules documentation for all minions) salt * sys.doc apache.fullversion (list module specific documentation for all minions)
It offers a minion availability test, as follows:
salt * test.ping (for all nodes) salt machine-name test.ping (for specific node)
* is the target, which specifies all minions. You must specify the minion id/hostname if you want to target a specific minion.
To install a package, type:
salt * pkg.install dialog
For user addition, type:
salt * user.add osfy
To query disk usage, type:
salt myminion disk.percent myminion: ---------- /: 31% /boot: 25% /dev/shm: 0% /tmp: 29% /var/log: 8%
Salt State is a component in SaltStack that holds the configuration data on the master, and which gets transferred to all minions, on demand.
The collection of state files makes up the State Tree. The Salt file server must be set up first. So, edit the master configuration file /etc/salt/master and uncomment the following lines:
file_roots: base: - /srv/salt
The data will be stored in a simple serialisation format (YAML) in a master file server. YAML stands for YAML Aint Markup Language.
We can set a different folder for the base in the master and also define separate folders under the base, depending on the environments that we support. For instance, if you have the dev, test and prod environments, then the directory structure might look like what is shown below:
file_roots: base: - /srv/salt dev: - /srv/salt/dev test: - /srv/salt/test prod: - /srv/salt/prod
We could keep common Salt States like user, group and sudo in the base structure, and other configurations, which might be specific to the environments, in their respective folders.
A Salt State consists of identifiers, as well as state module and function declarations. It might also include function parameters.
nginx: #Identifier pkg: #State Module - installed #State Function nginx: #Identifier pkg.installed #State Module and Function combined. /etc/nginx: file.directory: # State module and function - user:nginx #State function parameter
The top file
The top file contains the list of all the Salt States to be used. It maps the name with the SLS module that gets loaded on a certain minion via the state system. By default, it understands * as all minions. We can specify a set of minions or even a number of minions, using regular expressions or a grouping criterion, e.g., environment.
The file will be within the folder that we mark as base. We could also keep a top file within each environment and refer these top files within the base top file.
Lets prepare the SLS file to install the Nginx Web server. With the pkg module we can install packages using Salt. Create the nginx.sls file in the base folder as shown below.
/srv/salt/nginx.sls: nginx: pkg: - installed
If the top file were to use the above Nginx Salt State, then it would look like what follows:
/srv/base/top.sls: base: *: - nginx
Running the Salt State
A Salt State can be run in two ways.
- Salt Master could instruct the targeted minion to only run the selected module. The module is then downloaded, compiled and executed on the minion. Once completed, the minion will revert with a summary of all actions taken and all changes made.
salt myminion state.sls nginx (Flow: nginx)
- The master could instruct the targeted minion to run as state.highstate. When a minion executes a highstate call, it will download the top file and attempt to match the expressions within the top file. When it does match an expression, the modules listed for it will be downloaded, compiled and executed. Once completed, the minion will give a summary of all actions taken and all changes made.
salt myminion state.highstate (Flow: top -> nginx -> top)
The summary output looks like whats shown below:
Summary -------------- Succeeded: 1 Failed: 0 -------------- Total: 1
Note: Instead of nginx.sls, we can also use nginx/init.sls, if we have other modules common to the Nginx module and if we want to call all or some of those modules within init.
SLS namespace rules
Salt has defined a few simple rules for .sls files.
1. The .sls is discarded (i.e., nginx.sls becomes nginx).
2. A file called init.sls in a sub-directory is referred to by the path of the directory. So, nginx/init.sls is referred to as nginx.
3. Sub-directories can be used for better organisation.
a. Each sub-directory is represented by a dot.
b. nginx/dev.sls is referred to as nginx.dev.
4. If both nginx.sls and nginx/init.sls happen to exist, nginx/init.sls will be ignored, and nginx.sls will be preferred over nginx/init.sls and read as nginx.
To start a service, type:
/srv/salt/nginx/init.sls: nginx: pkg: - installed service: - running - require: - pkg: nginx
Now we have added a little more information about our preferences.
- A check is done whether a package named Nginx is installed or not. If not, it will be installed.
- If the package is installed, then a check is done to find out whether the Nginx service is running. If not, the service is started. For the service check to be done, the package installation is marked as a dependency. The word require, being a Requisite Statement, does just thatensuring that the pre-requisites are there.
To add users and groups, type:
nginx: pkg: - installed service: - running - enable: True - watch: - pkg: nginx - file: /etc/nginx/nginx.conf - user: nginx user.present: - uid: 151 - gid: 151 - home: /var/lib/nginx - shell: /bin/nologin - require: - group: nginx group.present: - gid: 151 - require: - pkg: nginx
Watch and require
We hope you noticed that we have used the watch word this time. The require word will make sure the user gets created after the group creation, which must happen only after the Nginx package is installed. The watch word checks for any changes to the watched states. The service state watcher will be activated in the following cases:
- When the package is updated
- When the configuration file is changed
- If the user ID gets modified
The service state watcher just restarts the service; so in this case, a change in the config file will also trigger a restart of the respective service.
Users and groups
User Nginx is created with:
- userid and groupid 151
- Home folder /var/lib/nginx
- No login shell
- Requires a group called nginx
Group Nginx is dependent on the package nginx being installed.
The Salt master could act as the repository for the Nginx configuration file. The file.managed module sends files to the minion and replaces the configuration file on the target system.
/etc/nginx/nginx.conf: file.managed: - source: salt://nginx/files/nginx.conf - user: root - group: root - mode: 644
The source file can be hosted either on the Salt master server or on a network accessible server. The file hosted on a network server (e.g., HTTP or FTP) requires the source_hash argument. We could also keep the data files along with init.sls but it is easier to maintain and manage these files if they are separated from the SLS configuration. If we do keep the data and configuration files within the same directory, the source statement and files could look like whats shown below:
nginx/init.sls nginx/nginx.conf - source: salt://nginx/nginx.conf
Once the rules in an SLS are ready, they should be tested to ensure they work properly. To invoke these rules, execute salt * state.highstate on the command line. If you get back only hostnames followed by a :, but no return, chances are that there is a problem with one or more of the SLS files. On the minion, use the command salt-call state.highstate -l debug to examine the output for errors. This should help to troubleshoot the issue. The minions can also be started in the foreground in debug mode: salt-minion -l debug.