Table of contents
1.
Introduction
2.
Pillars
2.1.
Declaring Master Pillar
2.2.
Dynamic Pillar Environments
2.3.
Namespace Flattening in Pillar
2.4.
Dictionary Merging in Pillar
2.5.
In-Memory Pillar Data
2.6.
How to handle Pillar Environment?
2.7.
Viewing Pillar Data
2.8.
Setting Pillar data using CLI
3.
Frequently Asked Questions
3.1.
What is Salt?
3.2.
What are Pillars in salt?
3.3.
What is a Grain in Salt?
3.4.
What is the Event System in Salt?
3.5.
What is an Event bus in salt?
4.
Conclusions
Last Updated: Mar 27, 2024
Medium

Overview of Pillar in Salt

Author Rajat Agrawal
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

Salt is a configuration management and distributed remote execution system. It was created with the goal to improve, simplify, and further customize the best remote execution solutions. It can maintain the remote nodes in defined states and query and execute commands on various nodes.

saltstack

In this blog, we will discuss and learn the concept of Pillars in salt.

Pillars

Pillars are salt interfaces designed to provide global values to salt minions. The pillar’s data is managed in the same way as it is managed in the Salt state tree. Pillar is helpful for storing sensitive data to a particular minion.

Let’s see how to declare the master pillar in salt.

Declaring Master Pillar

The salt master has a pillar_roots file that matches the file_roots file saved in the file server. The pillar_roots option, like file_roots, maps environments to folders. Then, using matches in a top file that is organized similarly to the state top file, the pillar data is mapped to minions. The pillars can use the same matcher types as top files.

In the below example, we can see that the pillar_roots file is configured the same way as file_roots.

pillar_roots:
  base:
    - /srv/pillar


Let’s see the structure of the top file

/srv/pillar/top.sls

base:
  '*':
    - packages


In the above top file, we can see that it is declared that in the base environment, the glob matching all minions will have access to the pillar data located in the packages pillar. 

We can ignore errors related to missing pillar files with the help of the ignore_missing keyword. The example using the ignore_missing keyword is given below:

base:
  '*':
    - servers
    - systems
    - ignore_missing: True


Let’s see what is there in the packages pillar. 

/srv/pillar/packages.sls

{% if grains['os'] == 'Debian' %}
apache: apache2
git: git-core
{% elif grains['os'] == 'RedHat' %}
apache: httpd
git: git
{% endif %}


In the above pillar, the pillar sets two key-value pairs. If the minion is running Debian, then the apache key is set to apache2, and the git key is set to git-core. Otherwise, if the minion is running RedHat, then the  apache key is set to httpd, and the git key is set to git

Let's see how to create a dynamic pillar environment.

Dynamic Pillar Environments

 To use dynamic git branch based environments for pillar files, make sure that the environment __env__ is specified in pillar_roots. Let’s see an example. 

pillar_roots:
  __env__:
    - /srv/pillar

ext_pillar:
  - git:
    - __env__ https://example.com/git-pillar.git


Let’s see how to do namespace flattening in Pillar.

Namespace Flattening in Pillar

During the namespace flattening, all the .sls files are merged into a single dictionary of key-value pairs. There could be an error if the same key is defined in multiple .sls files. 

Let’s take a look at the example below.

In top.sls

base:
  '*':
    - packages
    - services


The packages.sls contains the key-value pairs bind: bind9. 

And the services.sls contains the key-value pairs bind: named

In the above example, the request for the bind pillar key will return named only. The bind9 value will be lost because of services.sls pillar was evaluated later. 

To solve the above problem, its recommended to structure the pillar files with more hierarchy. For example, the packages.sls file can also be configured like this:-

packages:
  bind: bind9


Let’s see how to do dictionary merging in the pillar.

Dictionary Merging in Pillar

The dictionary merging is required when the same pillar key is used in multiple .sls files, and the keys in all the files refer to nested dictionaries. In this case, the content from these dictionaries is merged recursively.

Let's take an example where the top.sls file will remain the same, and other SLS files are modified:-

packages.sls

bind:
  package-name: bind9
  version: 9.9.5


services.sls:

bind:
  port: 53
  listen-on: any


The dictionary for the above example will look like this:

$ salt-call pillar.get bind
local:
    ----------
    listen-on:
        any
    package-name:
        bind9
    port:
        53
    version:
        9.9.5


Let’s learn about In-memory pillar data.

In-Memory Pillar Data

It is very computationally expensive to compile all the pillar data. To avoid this problem, the salt minions maintain a copy of pillar data in memory and send a copy of the pillar data each time pillar data is requested. 

The functions such as pillar.itempillar.get, and pillar.raw returns the in-memory pillar data. 

If you are writing your custom execution modules, then the in-memory pillar data is available as the __pillar__ dunder dictionary. 

You can refresh the in-memory pillar data using the following command:-

salt '*' saltutil.refresh_pillar


Let’s see how to handle the pillar environment.

How to handle Pillar Environment?

If there are multiple pillar environment that is running simultaneously. By default, all the pillar data from all the environments are merged together, and the pillar dictionary will contain the keys from all the configured environments. 

The pillarenv minion config option is used to force minions to take configuration from a single environment. This can be helpful for running states with different pillar data, whether for testing or quality assurance purposes or to test changes to the pillar data before releasing them online. 

For example, in the minion config file, the pillarenv is set to base.  

Note: In running states, the pillarenv CLI argument can be used to override the minion's pillarenv config value.

To run a pillar in the testing phase, run the following command.

salt '*' state.apply mystates pillarenv=testing


To run a pillar in dev mode, run the following command.

salt '*' state.apply mystates saltenv=dev


or

salt '*' state.apply mystates saltenv=dev pillarenv=dev


To run a pillar in QA mode, run the following command.

salt '*' state.apply mystates saltenv=dev pillarenv=qa


Let’s learn how to view pillar data.

Viewing Pillar Data

We can use the pillar execution module in order to view pillar data. The pillar execution module has several functions, each having its own significance.

The execution functions are:-

  • pillar.item: Its function is to fetch the value of one or more keys from the in-memory pillar data.
     
  • pillar.items: Its function is to compile a fresh pillar dictionary and return it when required.
     
  • pillar.raw: Its function is quite similar to pillar.items, it also returns the entire pillar dictionary but from the in-memory pillar data, not from compiled fresh pillar dictionary.
     
  • pillar.get: Its function is to return the demanded data.
     

Let’s see how to set pillar data using the command line.

Setting Pillar data using CLI

The below example clearly describes how to set pillar data using CLI.

salt '*' state.apply pillar='{"coding": "ninjas"}'


This will add a pillar key of coding with its value set to ninjas.

Note: Avoid sending any sensitive data using CLI.

Frequently Asked Questions

What is Salt?

Salt is a configuration management and distributed remote execution system. It was created with the goal to improve, simplify, and further customize the best remote execution solutions. 

What are Pillars in salt?

Pillars are salt interfaces designed to provide global values to salt minions.  Pillar is helpful for storing sensitive data to a particular minion.

What is a Grain in Salt?

Grain is a salt interface that derives information about the underlying system. Grains are collected for the IP address, domain name, OS, kernel, OS type, and various other system properties.

What is the Event System in Salt?

The salt event system is used to fire off events like the Start event, Key event, Job event, etc., using third-party apps or with the help of an external process.

What is an Event bus in salt?

The event bus is used for both network transport and inter-process communication in salt. It consists of two components, the event socket and the event library.

Conclusions

In this article, we have extensively discussed the concept of Pillars in salt. I hope you enjoyed this blog on the Overview of Pillar in Salt. 

If you want to learn more, check out our articles on Salt Event SystemOverview of Grains in SaltAbout Salt RunnersTarget Minions in SaltAbout Salt Engine, and Pillar Walkthrough

Also, check out these exciting courses from coding ninjas to expand your knowledge, Coding CourseCode StudioInterview ExperienceGuided PathInterview ProblemsTest SeriesLibrary, and Resources

Happy Coding!

Live masterclass