vRA SaltStack Config – Pillars

Salt Pillars are key elements to have parametric Salt State files allowing them to be more flexible and reusable. Here is an introduction to Salt Pillar

Salt Pillars are key elements to have parametric Salt State files allowing them to be more flexible and reusable. Pillars are data structures defined on the Salt Master and distributed to minions. They allow confidential, targeted data to be securely sent only to the relevant Minions. Pillar data structure can be used for:

  • Minion configuration: Minion modules such as the execution modules, states, and returners can often be configured via data stored in Pillars.
  • Variables: variables which need to be assigned to specific Minions or groups of Minions can be defined in Pillars and then accessed inside sls formulas and template files.
  • Arbitrary data: Pillars can contain any basic data structure in dictionary format, so a key/value store can be defined making it easy to iterate over a group of values in sls formulas.

Salt Pillar Top File

Salt Pillars use a Top file to match Salt Pillar data to Salt Minions. See my post about Top File if you need a refresher about Top files. This Top file is very much like the Top file that is used to match Salt State files to Salt Minions. Like Top File, Salt Pillar is best learned by example, here is an very simple example.

Pillar Top File named top.sls (the name has to be exactly this):

    - defaults

Pillar data file defaults.sls in the same directory of the Top file. In the example below we have two key/value pairs:

shell: bash
editor: vim

Pillar data refresh (the action to provide Pillar data to targeted Minions):

salt '*' saltutil.refresh_pillar

When Salt Pillar data is refreshed, each Salt Minion is matched against the targets listed in the top.sls file. When a Salt Minion matches a target, it receives all of the Salt Pillar SLS files defined in the list underneath that target.

In order to sees Minion’s Pillar use the following command:

salt '*' pillar.items

Salt Pillar in Salt States

We can reference Pillar data in Salt States by means of templating, here is a State File that leverages key/values defined in the defaults.sls Pillar data file introduced before:

    - name: {{ pillar['editor'] }}

Actually Pillar data files are three-like data structures, so we can have a bit more complex data structures. Let’s assume to modify our defaults.sls file as follows:

  shell: bash
  editor: vim
  http: 8080

As a consequence our State file should change as follow in order to recognize that now they key editor is nested under system.

    - name: {{ pillar['system']['editor'] }}

Get Started with Pillar

There are few things we need to know and configure on the Salt Master before we can start playing with Pillar.

We need to start setting up Pillar making sure the directory /srv/pillar exists on you Salt Master:

mkdir /srv/pillar

The Pillar location can be configured using the pillar_roots option in the Master configuration file. It must not be in a subdirectory of the state tree or file_roots. If the pillar is under file_roots, any pillar targeting can be bypassed by minions. Here after there is the piece of configuration I have in my Master configuration file. Please, note that you can manage multiple environments, external Pillars (e.g. source your Pillars file from a git repository) and other nice things, but this goes beyond the scope of this post.

    - /srv/pillar

Do not forget to restart you Salt Master service in order to make sure the new configuration is taken into account by the Master:

systemctl restart salt-master

Store your top.sls file and any Pillar SLS file referenced in the Top file in the /srv/pillar directory. Now you can use the saltutil.refresh_pillar and the pillar.items as introduced above to assign and check Pillar data against Minions.

Lab Time!

In my lab I have some Minions, but for this activity I will restrict the scope to 3 minions having the string secops in their Minion IDs.

In the /srv/pillar directory I have the following files:

Top file, as usual named top.sls:

    - match: grain
    - centosdefaults
    - match: grain
    - ubuntudefaults
    - match: grain
    - windowsdefaults

Pillar SLS for CentOS Minions named centosdefaults.sls:

path: /opt/iberia_lab
user: root
group: root
mode: 755

Pillar SLS for Ubuntu Minions named ubuntudefaults.sls:

path: /opt/iberia_lab
user: seiberia
group: seiberia
mode: 755

Pillar SLS for Windows Minions named windowsdefaults.sls:

path: C:\iberia_lab
user: Administrator
group: na
mode: na

Here is how my /srv/pillar directory looks like:

Now I can refresh Pillar:

I can check Pillar data assignment to Minions:

Now that I have Pillars data available in my Minions I can make good use of them. For this purpose I have a simple State file:

# This State file ensure all systems have default directory according to company policy

# Ensure default directory is there
create standard_directory:
   - name: {{ pillar['path'] }}
   - user: {{ pillar['user'] }}
   - group: {{ pillar['group'] }}
   - mode: {{ pillar['mode'] }}

Apply the State file and see it using different values available in different Minions:

With this post I am just scratching the surface of a powerful yet simple mechanism such as Pillar, however even with this basic notions you can start doing real life stuff and automate (A LOT!) in your environment.