mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 17:09:03 +00:00
323 lines
9.7 KiB
ReStructuredText
323 lines
9.7 KiB
ReStructuredText
=================
|
|
State Enforcement
|
|
=================
|
|
|
|
Salt offers an optional interface to manage the configuration or "state" of the
|
|
Salt minions. This interface is a fully capable mechanism used to enforce the
|
|
state of systems from a central manager.
|
|
|
|
The Salt state system is made to be accurate, simple, and fast. And like the
|
|
rest of the Salt system, Salt states are highly modular.
|
|
|
|
State management
|
|
================
|
|
|
|
State management, also frequently called software configuration management
|
|
(SCM), is a program that puts and keeps a system into a predetermined state. It
|
|
installs software packages, starts or restarts services, or puts configuration
|
|
files in place and watches them for changes.
|
|
|
|
Having a state management system in place allows you to easily and reliably
|
|
configure and manage a few servers or a few thousand servers. It allows you to
|
|
keep that configuration under version control.
|
|
|
|
Salt States is an extension of the Salt Modules that we discussed in the
|
|
previous :doc:`remote execution </topics/tutorials/modules>` tutorial. Instead
|
|
of calling one-off executions the state of a system can be easily defined and
|
|
then enforced.
|
|
|
|
Understanding the Salt State System Components
|
|
==============================================
|
|
|
|
The Salt state system is comprised of a number of components. As a user, an
|
|
understanding of the SLS and renderer systems are needed. But as a developer,
|
|
an understanding of Salt states and how to write the states is needed as well.
|
|
|
|
|
|
|
|
Salt SLS System
|
|
---------------
|
|
|
|
.. glossary::
|
|
|
|
SLS
|
|
The primary system used by the Salt state system is the SLS system. SLS
|
|
stands for **S**\ a\ **L**\ t **S**\ tate.
|
|
|
|
The Salt States are files which contain the information about how to
|
|
configure Salt minions. The states are laid out in a directory tree and
|
|
can be written in many different formats.
|
|
|
|
The contents of the files and they way they are laid out is intended to
|
|
be as simple as possible while allowing for maximum flexibility. The
|
|
files are laid out in states and contains information about how the
|
|
minion needs to be configured.
|
|
|
|
SLS File Layout
|
|
```````````````
|
|
|
|
SLS files are laid out in the Salt file server. A simple layout can look like
|
|
this:
|
|
|
|
.. code-block:: yaml
|
|
|
|
top.sls
|
|
ssh.sls
|
|
sshd_config
|
|
users/init.sls
|
|
users/admin.sls
|
|
salt/init.sls
|
|
salt/master.sls
|
|
|
|
This example shows the core concepts of file layout. The top file is a key
|
|
component and is used with Salt matchers to match SLS states with minions.
|
|
The ``.sls`` files are states. The rest of the files are seen by the Salt
|
|
master as just files that can be downloaded.
|
|
|
|
The states are translated into dot notation, so the ``ssh.sls`` file is
|
|
seen as the ssh state, the ``users/admin.sls`` file is seen as the
|
|
users.admin states.
|
|
|
|
The init.sls files are translated to be the state name of the parent
|
|
directory, so the ``salt/init.sls`` file translates to the Salt state.
|
|
|
|
The plain files are visible to the minions, as well as the state files. In
|
|
Salt, everything is a file; there is no "magic translation" of files and file
|
|
types. This means that a state file can be distributed to minions just like a
|
|
plain text or binary file.
|
|
|
|
SLS Files
|
|
`````````
|
|
|
|
The Salt state files are simple sets of data. Since the SLS files are just data
|
|
they can be represented in a number of different ways. The default format is
|
|
yaml generated from a Jinja template. This allows for the states files to have
|
|
all the language constructs of Python and the simplicity of yaml. State files
|
|
can then be complicated Jinja templates that translate down to yaml, or just
|
|
plain and simple yaml files!
|
|
|
|
The State files are constructed data structures in a simple format. The format
|
|
allows for many real activates to be expressed in very little text, while
|
|
maintaining the utmost in readability and usability.
|
|
|
|
Here is an example of a Salt State:
|
|
|
|
.. code-block:: yaml
|
|
|
|
vim:
|
|
pkg:
|
|
- installed
|
|
|
|
salt:
|
|
pkg:
|
|
- latest
|
|
service.running:
|
|
- require:
|
|
- file: /etc/salt/minion
|
|
- pkg: salt
|
|
- names:
|
|
- salt-master
|
|
- salt-minion
|
|
- watch:
|
|
- file: /etc/salt/minion
|
|
|
|
/etc/salt/minion:
|
|
file.managed:
|
|
- source: salt://salt/minion
|
|
- user: root
|
|
- group: root
|
|
- mode: 644
|
|
- require:
|
|
- pkg: salt
|
|
|
|
This short stanza will ensure that vim is installed, Salt is installed and up
|
|
to date, the salt-master and salt-minion daemons are running and the Salt
|
|
minion configuration file is in place. It will also ensure everything is
|
|
deployed in the right order and that the Salt services are restarted when the
|
|
watched file updated.
|
|
|
|
The Top File
|
|
````````````
|
|
|
|
The top file is the mapping for the state system. The top file specifies which
|
|
minions should have which modules applied and which environments they should
|
|
draw the states from.
|
|
|
|
The top file works by specifying the environment, containing matchers with
|
|
lists of Salt states sent to the matching minions:
|
|
|
|
.. code-block:: yaml
|
|
|
|
base:
|
|
'*':
|
|
- salt
|
|
- users
|
|
- users.admin
|
|
'saltmaster.*':
|
|
- match: pcre
|
|
- salt.master
|
|
|
|
This simple example uses the base environment, which is built into the default
|
|
Salt setup, and then all minions will have the modules salt, users and
|
|
users.admin since '*' will match all minions. Then the regular expression
|
|
matcher will match all minions' with an id matching saltmaster.* and add the
|
|
salt.master state.
|
|
|
|
Renderer System
|
|
---------------
|
|
|
|
The Renderer system is a key component to the state system. SLS files are
|
|
representations of Salt "high data" structures. All Salt cares about when
|
|
reading an SLS file is the data structure that is produced from the file.
|
|
|
|
This allows Salt states to be represented by multiple types of files. The
|
|
Renderer system can be used to allow different formats to be used for SLS
|
|
files.
|
|
|
|
The available renderers can be found in the renderers directory in the Salt
|
|
source code:
|
|
|
|
:blob:`salt/renderers`
|
|
|
|
By default SLS files are rendered using Jinja as a templating engine, and yaml
|
|
as the serialization format. Since the rendering system can be extended simply
|
|
by adding a new renderer to the renderers directory, it is possible that any
|
|
structured file could be used to represent the SLS files.
|
|
|
|
In the future XML will be added, as well as many other formats.
|
|
|
|
|
|
Reloading Modules
|
|
-----------------
|
|
|
|
Some salt states require specific packages to be installed in order for the
|
|
module to load, as an example the :mod:`pip <salt.states.pip_state>` state
|
|
module requires the `pip`_ package for proper name and version parsing. On
|
|
most of the common cases, salt is clever enough to transparently reload the
|
|
modules, for example, if you install a package, salt reloads modules because
|
|
some other module or state might require just that package which was installed.
|
|
On some edge-cases salt might need to be told to reload the modules. Consider
|
|
the following state file which we'll call ``pep8.sls``:
|
|
|
|
.. code-block:: yaml
|
|
|
|
python-pip:
|
|
cmd:
|
|
- run
|
|
- cwd: /
|
|
- name: easy_install --script-dir=/usr/bin -U pip
|
|
|
|
pep8:
|
|
pip.installed
|
|
requires:
|
|
- cmd: python-pip
|
|
|
|
|
|
The above example installs `pip`_ using ``easy_install`` from `setuptools`_ and
|
|
installs `pep8`_ using :mod:`pip <salt.states.pip_state>`, which, as told
|
|
earlier, requires `pip`_ to be installed system-wide. Let's execute this state:
|
|
|
|
.. code-block:: bash
|
|
|
|
salt-call state.sls pep8
|
|
|
|
The execution output would be something like:
|
|
|
|
.. code-block:: text
|
|
|
|
----------
|
|
State: - pip
|
|
Name: pep8
|
|
Function: installed
|
|
Result: False
|
|
Comment: State pip.installed found in sls pep8 is unavailable
|
|
|
|
Changes:
|
|
|
|
Summary
|
|
------------
|
|
Succeeded: 1
|
|
Failed: 1
|
|
------------
|
|
Total: 2
|
|
|
|
|
|
If we executed the state again the output would be:
|
|
|
|
.. code-block:: text
|
|
|
|
----------
|
|
State: - pip
|
|
Name: pep8
|
|
Function: installed
|
|
Result: True
|
|
Comment: Package was successfully installed
|
|
Changes: pep8==1.4.6: Installed
|
|
|
|
Summary
|
|
------------
|
|
Succeeded: 2
|
|
Failed: 0
|
|
------------
|
|
Total: 2
|
|
|
|
|
|
Since we installed `pip`_ using :mod:`cmd <salt.states.cmd>`, salt has no way
|
|
to know that a system-wide package was installed. On the second execution,
|
|
since the required `pip`_ package was installed, the state executed perfectly.
|
|
|
|
To those thinking, couldn't salt reload modules on every state step since it
|
|
already does for some cases? It could, but it should not since it would
|
|
greatly slow down state execution.
|
|
|
|
So how do we solve this *edge-case*? ``reload_modules``!
|
|
|
|
``reload_modules`` is a boolean option recognized by salt on **all** available
|
|
states which, does exactly what it tells use, forces salt to reload it's
|
|
modules once that specific state finishes. The fixed state file would now be:
|
|
|
|
.. code-block:: yaml
|
|
|
|
python-pip:
|
|
cmd:
|
|
- run
|
|
- cwd: /
|
|
- name: easy_install --script-dir=/usr/bin -U pip
|
|
- reload_modules: true
|
|
|
|
pep8:
|
|
pip.installed
|
|
requires:
|
|
- cmd: python-pip
|
|
|
|
|
|
Let's run it, once:
|
|
|
|
.. code-block:: bash
|
|
|
|
salt-call state.sls pep8
|
|
|
|
And it's output now is:
|
|
|
|
.. code-block:: text
|
|
|
|
----------
|
|
State: - pip
|
|
Name: pep8
|
|
Function: installed
|
|
Result: True
|
|
Comment: Package was successfully installed
|
|
Changes: pep8==1.4.6: Installed
|
|
|
|
Summary
|
|
------------
|
|
Succeeded: 2
|
|
Failed: 0
|
|
------------
|
|
Total: 2
|
|
|
|
|
|
.. _`pip`: http://pypi.python.org/pypi/pip
|
|
.. _`pep8`: https://pypi.python.org/pypi/pep8
|
|
.. _`setuptools`: https://pypi.python.org/pypi/setuptools
|