Introduction

As described by their website; Salt is "Event-driven automation for a software-defined world". You gotta love marketing :) Salt is a large project with many features including; configuration management, an event based reactor, cloud management and network automation.

Salt can do ALOT but it does have a relatively steep learning curve. In saying that, Salt does have extensive documentation, although in my experience you have to know how to use Salt a little bit before the documentation starts to make sense.

This post aims to help get you started on your Salt journey and hopefully once you are done you will continue down the Salt mine, it's pretty fun down here !

Architecture

Salt has many components, these are the main ones:

  • Salt Master - Controls minions
  • Salt Minion - Executes code from the master via an agent
  • Salt Proxy Monion - Executes code on hosts that cannot install an agent
  • Message Bus - Messages between Salt master and minions are sent along the message bus
salt-architecture

Lab Environment

In this post I will configure a Centos host as a Salt master and a Cumulus host as a Salt minion.

lab-topology

For reference the code version used in this lab are as follows:

  • Centos - 7 minimal
  • Cumulus - 3.4.3
  • Salt - 17.7.2

Note: I have built this lab with Vagrant boxes so the Firewall and SELinux are already disabled in the Centos image.

Installation

The process of installing Salt and its dependencies differs from system to system, for the most accurate information refer to the specific instructions per platform .

Centos 7


sudo yum install https://repo.saltstack.com/yum/redhat/salt-repo-latest-2.el7.noarch.rpm
              

Update the YUM cache.


sudo yum clean expire-cache
              

Install the Salt master and minion.


sudo yum install -y salt-master salt-minion
              

Note: The salt-minion daemon is also installed on the Salt Master so that we can manage it via salt.

Cumulus

The Cumulus linux 3.X train is based on the Debian Jessie release, therefore the bellow instructions are based on Debian Jessie.

Use vi or nano to add the required repositories to the end of the /etc/apt/sources.list file.


# /etc/apt/sources.list
deb http://ftp.us.debian.org/debian/ jessie main contrib non-free
deb http://repo.saltstack.com/apt/debian/8/amd64/latest jessie main
              

Install the GPG key.


wget https://repo.saltstack.com/apt/debian/8/amd64/latest/SALTSTACK-GPG-KEY.pub
sudo apt-key add SALTSTACK-GPG-KEY.pub
              

Update the APT cache.


sudo apt-get update
              

Install the Salt minion.


sudo apt-get install -y salt-minion
              

Configuration

Salt daemon configuration files use a YAML syntax. If you are not familiar with YAML there is a good overview here

Master

Update the configuration files on the Centos host which is the Salt Master. The /etc/salt/master file specifies the configuration for the salt-master daemon.

Tell the Salt master where the files related to state are located by setting the file_roots parameter in the /etc/salt/master config file.


file_roots:
  base:
    - /srv/salt/
    - /srv/salt/states
    - /srv/salt/templates
    - /srv/salt/files
          

Pillar data is static variables that relate to a minions and are defined by the Salt administrator. Tell the Salt master where pillar data is located by setting the pillar_roots parameter in the /etc/salt/master config file.


pillar_roots:
  base:
    - /srv/salt/pillar
          

Create the directories that where just defined above in the /etc/salt/master config file.


sudo mkdir -p /srv/salt/{states,templates,files,pillar}
          

The /etc/salt/minion file specifies the configuration for the salt-minion daemon.

Set the master configuration parameter in the /etc/salt/minion file.


master: 192.168.121.201
          

Set the id configuration parameter in the /etc/salt/minion file.


id: 192.168.121.201
          

Restart both the salt-master and salt-minion daemons.


sudo systemctl restart salt-master
sudo systemctl restart salt-minion
          

Enable both the salt-master and salt-minion daemons to start on boot.


sudo systemctl enable salt-master
sudo systemctl enable salt-minion
          

Use systemctl status command to confirm both services are running and enabled.


systemctl status salt-master
systemctl status salt-minion
          

Note: Since I am not running DNS in this lab I am using IP addresses, if DNS is active in the environment you can use host names in lieu of IP addresses.

Minion

The Cumulus host only needs to have its /etc/salt/minion file updated.

Set the master configuration parameter in the /etc/salt/minion file.


master: 192.168.121.201
          

Set the id configuration parameter in the /etc/salt/minion file.


id: 192.168.121.202
          

Restart the salt-minion daemon.


sudo systemctl restart salt-minion
          

Enable the salt-minion daemon to start on boot.


sudo systemctl enable salt-minion
          

Confirm the salt-minion service is running and enabled with the systemctl status command.


systemctl status salt-minion
          

Salt Key

Salt uses public key encryption to authenticate hosts. Before a minion can join the message bus its key must be accepted by the Salt Master.

Use the salt-key -L command to view the status of all the minion keys.


sudo salt-key -L

# output
Accepted Keys:
Denied Keys:
Unaccepted Keys:
192.168.121.201
192.168.121.202
Rejected Keys:
          

As you can see there are two unaccepted keys, these belong to both our Centos and Cumulus hosts.

Use the salt-key -A command to accept all the minion keys.


sudo salt-key -A --yes

# output
The following keys are going to be accepted:
Unaccepted Keys:
192.168.121.201
192.168.121.202
Key for minion 192.168.121.201 accepted.
Key for minion 192.168.121.202 accepted.
          

Test Connectivity

Use the salt '*' test.ping command to confirm the Salt master can connect to all the Salt minions. If the master can connect to the minions a True status will be returned.


sudo salt '*' test.ping

# output
192.168.121.202:
    True
192.168.121.201:
    True
          

Salt Command

Performing actions against minions with Salt from the CLI is done with the salt command. The salt command has the following structure.

salt [options] '<target>' <function> [arguments]

  • options - Examples are version and timeout values.
  • target - Used to select minions to execute functions against. '*' targets all minions.
  • function - Action to execute on the minion. EG: pkg.installed is used to install packages.
  • arguments - Some functions also take arguments. EG: pkg.installed vim

Note: Both the option and arguments parameters are optional.

Grains

Grain data is collected from the minions by salt automatically and can be used to target hosts and also as variables in device configuration templates.

Use the grains.items function to see all the grains that have been collected from a device.


sudo salt '192.168.121.202' grains.items

# output
192.168.121.202:
    ----------
    SSDs:
    biosreleasedate:
        04/01/2014
    biosversion:
        Ubuntu-1.8.2-1ubuntu1
.
. <snip>
.
          

Use the grains.item <grain-name> function to see a specific grain


sudo salt '192.168.121.202' grains.item os_family

# output
192.168.121.202:
    ----------
    os_family:
        Cumulus
          

Pillar

Pillar data is static variables that relate to minions and is defined by the Salt administrator. The location of the pillar data is defined in the /etc/salt/master config file under the pillar_roots section.

Lets configure some pillar data that defines the minions data centre location to apply to minion configuration. Create two files: master.sls and minion.sls under the /srv/salt/pillar/ directory.


# /srv/salt/pillar/master.sls
data_centre: syd
          

# /srv/salt/pillar/minion.sls
data_centre: nyc
          

Note: By default .sls files are a combination of YAML and Jinja2 data. This means they use the YAML syntax but it's also possible to use Jinja2 template structures to build out dynamic parts of the config file. I will not cover that as part of this blog but its something to be aware of.

The last piece of the pillar puzzle is to configure a top.sls file that ties the pillar data to the minion. Create a file called top.sls under the /srv/salt/pillar/ directory.


# /srv/salt/pillar/top.sls
base: # environment
  '192.168.121.201': # target
    - master # master.sls without the .sls extension
  '192.168.121.202':
    - minion
          

Use the pillar.items function to see the pillar data avaiable to a minion.


sudo salt '*' pillar.items

# output
192.168.121.202:
    ----------
    data_center:
        nyc
192.168.121.201:
    ----------
    data_center:
        syd
          

Note: If no data was returned the pillar data may need to be refreshed. This can be done using the saltutil.refresh_pillar function.


sudo salt '*' saltutil.refresh_pillar

# output
192.168.121.202:
    True
192.168.121.201:
    True
          

States

Salt states define the configuration to apply to a minion. Lets create a motd state that configures the message of the day banner using variables from both the pillar and grain data.

The location of the state data is defined in the /etc/salt/master config file under the file_roots section.

Create a file called motd.sls under the /srv/salt/states/ directory.


# /srv/salt/states/motd.sls
/etc/motd:
  file.managed:
    - source: salt://templates/motd.j2
    - template: jinja
    - user: root
    - group: root
    - mode: 0644
          

Next we need to create a configuration template that will be applied to the minions. The location of configuration templates is defined in the /etc/salt/master config file under the file_roots section.

Salt uses Jinja2 as its default templating engine but it does support many others. Create a file called motd.j2 under the /srv/salt/templates/ directory.


# /srv/salt/templates/motd.j2
############### Salt Managed ###############
hostname: {{ grains['fqdn'] }}
os: {{ grains['os'] }}
os_family: {{ grains['os_family'] }}
{%- if pillar['data_center'] is defined %}
data center: {{ pillar['data_center'] }}
{%- endif %}
############# End Salt Managed #############
          

Grain and pillar data is available as a dictionary so it can be accessed from within Jinja2 templates using the standard dictionary access methods.

Finally, create a top.sls file under the /srv/salt/states/ directory that defines the states to be applied to minions.


# /srv/salt/states/top.sls
base: # environment
  '*': # target all mininos
    - motd # motd.sls without the .sls extension
          

Now apply the motd state to the minions with the state.apply command.


sudo salt '*' state.apply

# output
192.168.121.201:
----------
          ID: /etc/motd
    Function: file.managed
      Result: True
     Comment: File /etc/motd updated
     Started: 09:40:09.158947
    Duration: 44.262 ms
     Changes:
              ----------
              diff:
                  ---
                  +++
                  @@ -0,0 +1,6 @@
                  +############### Salt Managed ###############
                  +hostname: master
                  +os: CentOS
                  +os_family: RedHat
                  +data center: syd
                  +############# End Salt Managed #############

Summary for 192.168.121.201
------------
Succeeded: 1 (changed=1)
Failed:    0
------------
Total states run:     1
Total run time:  44.262 ms
.
. <snip>
.
          

As you can see below the /etc/motd was updated on both the master and the minion with the variables from the template replaced with the grain and pillar data.


# [vagrant@master ~]$ cat /etc/motd
############### Salt Managed ###############
hostname: master
os: CentOS
os_family: RedHat
data center: syd
############# End Salt Managed #############
          

# vagrant@minion:~$ cat /etc/motd
############### Salt Managed ###############
hostname: minion
os: Cumulus
os_family: Cumulus
data center: nyc
############# End Salt Managed #############
          

Summary

Salt is a very useful tool not just for configuration management but for automation and orchestration. Salt is FAST, secure and once you get you head around it, a pleasure to work with.

Remember: This is not the end, but merely the beginning!

The "from the start to the beginning" series aims to take you from nothing to getting you up and running. This is not meant to be a comprehensive guide, but should be enough to get you going on the journey.

Links

https://saltstack.com/
https://saltstack.com/salt-open-source/






















Published: 2018-01-14