Friday, April 20, 2018

Using Salt with Network Devices - Part 1

Salt is an orchestration system developed by a company called SaltStack ( The Salt software is for complex systems management at scale. Salt is based on Python Salt comes in two flavors:
1) Salt Open Project
2) Salt Enterprise

Salt is easy enough to get running in minutes, scalable enough to manage tens of thousands of servers, and fast enough to communicate with them in seconds. Similarly, Salt can be used to manage network devices effectively. Salt has remote execution capabilities which allows us to run commands on various machines in parallel with flexible targeting system. In this post we will touch base on the basics of Salt and its installation.

Working Model:
Salt follows a client server model:
1) Master – is the server
2) Minion – is the client

It is possible to have multiple minions to connect to a single master. The communication between master and minion is secured and they use dynamically generated keys before anything else. The entire operational model is built on a dynamic communication bus which is ZeroMQ. Sometimes it is also refereed as pub-sub model. The salt system follows a very strict directory structure. By default the files are expected to be in "/etc/salt" folder and "/srv" folder. However, default directory structure can be changed. We will see the use of these folders in subsequent posts.

Other that these there are a few more components like:
1) Grains – the static information about the minion like OS name, Memory, Model No etc
2) Execution Modules – Ad hoc commands which can be executed from master to one or more target minions like ‘disk usage’, ‘ping’ etc
3) Pillar – stores data related to Minion like host information, IP address, user-credentials etc
There are a few more components which we will talk about in the future posts. Since network devices have propriety operating systems, hence it is not possible to make them minions. To resolve this issue, there is a concept of proxy-minion.

In this case the master will talk to the network devices via minions. 

Now lets do the installation of both master and minion. For simplicity we will use one master and one minion. The same minion will be used later on as proxy-minion. Before beginning the installation, it is assumed that the user is familiar with Linux (Ubuntu / Centos etc.) and few other things like git and python-pip. We will be using Ubuntu 16.04 (xenial) for this installation. For other linux platforms, the installation will be very similar. Even though not mandatory, but it’s always better to have the master and minion to be synced to the same ntp server.
Here is the master

root@master01:~# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.3 LTS
Release: 16.04
Codename: xenial
root@master01:~# ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================    .POOL.          16 p    -   64    0    0.000    0.000   0.000
*   .GPS.            1 u  891 1024  377  305.662   -0.067   5.264

And here is the minion
root@minion01:~# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.3 LTS
Release: 16.04
Codename: xenial
root@minion01:~# ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================    .POOL.          16 p    -   64    0    0.000    0.000   0.000
*   .GPS.            1 u   56   64   37  301.813   -0.886   1.007

Even though salt has its own repo on the github but we will use a forked version of the repo. The forked version is based on Nitrogen release of salt and it is available at here ( This repo is managed by Juniper.
The installation of salt on both master and minion is identical. Hence for simplicity I am only showing it on master.
root@master01:~# pip install git+

Collecting git+
  Cloning to /tmp/pip-BOGbIe-build
Collecting Jinja2 (from salt===2017.7.0-693-ga5f96e6)
  Downloading (126kB)
    100% |████████████████████████████████| 133kB 390kB/s
Collecting msgpack-python>0.3 (from salt===2017.7.0-693-ga5f96e6)
  Downloading (138kB)
    100% |████████████████████████████████| 143kB 423kB/s
Collecting PyYAML (from salt===2017.7.0-693-ga5f96e6)
  Downloading (253kB)
    100% |████████████████████████████████| 256kB 399kB/s
Collecting MarkupSafe (from salt===2017.7.0-693-ga5f96e6)
Collecting requests>=1.0.0 (from salt===2017.7.0-693-ga5f96e6)
  Downloading (88kB)
    100% |████████████████████████████████| 92kB 34kB/s
Collecting tornado==4.5.3 (from salt===2017.7.0-693-ga5f96e6)
  Downloading (484kB)
    100% |████████████████████████████████| 491kB 307kB/s
Collecting futures>=2.0 (from salt===2017.7.0-693-ga5f96e6)
Collecting pycrypto>=2.6.1 (from salt===2017.7.0-693-ga5f96e6)
  Downloading (446kB)
    100% |████████████████████████████████| 450kB 366kB/s
Collecting pyzmq>=2.2.0 (from salt===2017.7.0-693-ga5f96e6)
  Downloading (3.0MB)
    100% |████████████████████████████████| 3.0MB 149kB/s
Collecting certifi>=2017.4.17 (from requests>=1.0.0->salt===2017.7.0-693-ga5f96e6)
  Downloading (150kB)
    100% |████████████████████████████████| 153kB 423kB/s
Collecting chardet<3 .1.0="">=3.0.2 (from requests>=1.0.0->salt===2017.7.0-693-ga5f96e6)
  Downloading (133kB)
    100% |████████████████████████████████| 143kB 442kB/s
Collecting idna<2 .7="">=2.5 (from requests>=1.0.0->salt===2017.7.0-693-ga5f96e6)
  Downloading (56kB)
    100% |████████████████████████████████| 61kB 626kB/s
Collecting urllib3<1 .23="">=1.21.1 (from requests>=1.0.0->salt===2017.7.0-693-ga5f96e6)
  Downloading (132kB)
    100% |████████████████████████████████| 133kB 411kB/s
Collecting singledispatch (from tornado==4.5.3->salt===2017.7.0-693-ga5f96e6)
Collecting backports_abc>=0.4 (from tornado==4.5.3->salt===2017.7.0-693-ga5f96e6)
Collecting six (from singledispatch->tornado==4.5.3->salt===2017.7.0-693-ga5f96e6)
Building wheels for collected packages: msgpack-python, PyYAML, MarkupSafe, tornado, pycrypto
  Running bdist_wheel for msgpack-python ... done
  Stored in directory: /root/.cache/pip/wheels/d5/de/86/7fa56fda12511be47ea0808f3502bc879df4e63ab168ec0406
  Running bdist_wheel for PyYAML ... done
  Stored in directory: /root/.cache/pip/wheels/03/05/65/bdc14f2c6e09e82ae3e0f13d021e1b6b2481437ea2f207df3f
  Running bdist_wheel for MarkupSafe ... done
  Stored in directory: /root/.cache/pip/wheels/33/56/20/ebe49a5c612fffe1c5a632146b16596f9e64676768661e4e46
  Running bdist_wheel for tornado ... done
  Stored in directory: /root/.cache/pip/wheels/72/bf/f4/b68fa69596986881b397b18ff2b9af5f8181233aadcc9f76fd
  Running bdist_wheel for pycrypto ... done
  Stored in directory: /root/.cache/pip/wheels/27/02/5e/77a69d0c16bb63c6ed32f5386f33a2809c94bd5414a2f6c196
Successfully built msgpack-python PyYAML MarkupSafe tornado pycrypto
Installing collected packages: MarkupSafe, Jinja2, msgpack-python, PyYAML, certifi, chardet, idna, urllib3, requests, six, singledispatch, backports-abc, tornado, futures, pycrypto, pyzmq, salt
  Running install for salt ... done
Successfully installed Jinja2-2.10 MarkupSafe-1.0 PyYAML-3.12 backports-abc-0.5 certifi-2018.4.16 chardet-3.0.4 futures-3.2.0 idna-2.6 msgpack-python-0.5.6 pycrypto-2.6.1 pyzmq-17.0.0 requests-2.18.4 salt-2017.7.0-693-ga5f96e6 singledispatch- six-1.11.0 tornado-4.5.3 urllib3-1.22

We can check the Salt Version on both master and minion.
root@master01:~# salt --version
salt 2017.7.0-693-ga5f96e6 (Nitrogen)

root@minion01:~# salt --version
salt 2017.7.0-693-ga5f96e6 (Nitrogen)

For any questions please comment below.
****End of Part 1**** Part-2 available here

People who read this post also read :

No comments: