Installation and Configuration of Salt with Docker in GNS3

Disclaimer: – I am not an expert in Saltstack. I have been spending some good time to understand and unwrap bits of it primarily focused on Network Automation use-cases. This note was written by me (Gaurav Agrawal) in my personal capacity. The opinions expressed in this article are solely my own and do not reflect the view of my employer or my preference towards any of the OEMs.

This blog would demonstrate our first step to start Network Automation using salt. At the end of this section – one would be familiar on “how to start a basic salt environment”.

Below topics will be discussed in this section.

  1. Crafting “Salt-Master” & “Salt-Minion” docker container.
  2. GNS3 topology preparation
  3. Master Configuration
  4. Minion Configuration
  5. Proxy configuration
  6. Verification

Crafting Docker image for Salt-master and Salt-minion

I am sure – you must be thinking why do I need to build a docker container? – Well, we will demonstrate this lab in GNS3 & by default required containers are not available on GNS3 website marketplace. Hence, we need to create one to fulfill following objective i.e. “Faster, Scalable, efficient”

  1. Changes made within an “Ubuntu Hosts” are not persistent if GNS3 application is reloaded. Hence, every time we must install “salt-master” and “salt-minion” and other respective dependencies. Therefore, it would be a good idea to create an image which will have all its dependencies installed as soon as we create a container.
  2. Traditional methodology is not scalable i.e. imagine a situation if we got a requirement to import 3,5,10…so on containers in one project. Adding the same dependency at each container would be an inefficient use of resources and time-consuming process.

Hence, we decided to build a docker container for “Salt-Master” and “Salt-Minion”.

The only prerequisite for this is to have GNS3 VM installed & running in our local machine. Post-installation it would look like this.

  1. Click on “OK” and select “shell” using UP/DOWN arrow key. This will bring to “GNS3 VM” shell.
  2. Enter “pwd” to determine the present working directory
  3. Enter “sudo su –“ to login as “root” user.
  4. Navigate to the above working directory – In our case i.e. /home/gns3
  5. Ensure that you have internet access to GNS3 VM. Try “ping google.com”. If not, please check VM network adapter settings and add the appropriate “NAT” adapter to the VM.
  6. Create a Dockerfile: Master_Dockerfile with “nano Master_Dockerfile” command. Add below commands –
FROM ubuntu:18.04
RUN apt-get update && apt-get install -y nmap
RUN apt-get update && apt-get install net-tools
RUN apt-get update && apt-get install nano
RUN apt-get install yum -y
RUN apt-get install wget
RUN apt-get update && apt-get install iputils-ping -y
RUN DEBIAN_FRONTEND=noninteractive apt install -y tzdata
ENV TZ=Europe/Minsk
ENV ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apt-get install salt-master -y
RUN apt-get install salt-api -y
RUN apt-get update
RUN apt-get install systemd -y
RUN apt-get install less
RUN apt-get install git -y
RUN apt-get install python3-pip -y
RUN apt-get install python-pip -y
RUN apt-get update
RUN pip install napalm
RUN pip install --upgrade pip

7. save and exit.
8. Next step is to build this Docker container from the respective Docker file. Please execute below command

Docker build -f Master_Dockerfile -t mrcissp-master .

9. Similarly, Create a Dockerfile: Minion_Dockerfile with “nano Minion_Dockerfile” command and add below commands –

FROM ubuntu:18.04
RUN apt-get update && apt-get install -y nmap
RUN apt-get update && apt-get install net-tools
RUN apt-get update && apt-get install nano
RUN apt-get install yum -y
RUN apt-get install wget
RUN apt-get update && apt-get install iputils-ping -y
RUN DEBIAN_FRONTEND=noninteractive apt install -y tzdata
ENV TZ=Europe/Minsk
ENV ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apt-get install salt-minion -y
RUN apt-get install salt-api -y
RUN apt-get update
RUN apt-get install systemd -y
RUN apt-get install less
RUN apt-get install git -y
RUN apt-get install python3-pip -y
RUN apt-get install python-pip -y
RUN apt-get update
RUN pip install napalm
RUN pip install --upgrade pip

10. Kindly save and exit.
11. Again build a Docker container with the respective Docker file. Refer below command

Docker build -f Minion_Dockerfile -t mrcissp-minion .

Importing these custom build containers to GNS3

Follow below steps to import these containers to GNS3 applications.

  1. Navigate to Edit -> Preference -> Docker -> Docker Container -> New

2. Click on “Next”

3. Select the appropriate build i.e. “mrcissp-master:latest” for Master & “mrcissp-minion:latest” for Minion from the drop down menu.

4. Click on Next.
5. Repeat this for the Minion Build. This is how the application window looks like

6. Click on “Apply”

Creating First GNS3 topology

To start our first project with Salt :- below GNS3 topology have been considered for demonstration.

Note: By default the changes made to the docker container files will not be persistent to GNS3 if it reloads. Hence, to maintain persistency below configuration change would be require in our Hosts i.e. “mrcissp-master-1” and “mrcissp-minion-1“.  

  1. Right click on mrcissp-master-1/mrcissp-minion-1, select “configure
  2. From the available tab select “Advanced” and add the below mentioned directory.
/etc
/home
/var

3. Click on Apply

R1 Configuration

!
service password-encryption
!
hostname R1
!
ip domain name mrcissplab.com
ip name-server 8.8.8.8
!
username mrcissp privilege 15 password 7 0525100625454F29485744
!
interface Loopback0
 ip address 192.168.200.1 255.255.255.0
!
interface GigabitEthernet0/0
 ip address 192.168.100.1 255.255.255.0
!
interface GigabitEthernet0/1
 ip address dhcp
!
interface GigabitEthernet0/2
 ip address 192.168.240.1 255.255.255.0
!
router ospf 1
 network 192.168.100.0 0.0.0.255 area 0
 network 192.168.200.0 0.0.0.255 area 0
 network 192.168.240.0 0.0.0.255 area 0
!
ip ssh version 2
!
line vty 0 4
 login local
 transport input ssh
!

Switch Configuration

hostname Switch
!
username mrcissp privilege 15 password 0 mrcissp@123
!
ip domain-name mrcissplab.com
ip name-server 8.8.8.8
!
interface GigabitEthernet0/1
 switchport trunk allowed vlan 241
 switchport trunk encapsulation dot1q
 switchport mode trunk
 no cdp enable
!
interface GigabitEthernet0/0
 no switchport
 ip address 192.168.240.2 255.255.255.0
 negotiation auto
!
Vlan 241
Name MGMT_WLC
!
interface Vlan241
 ip address 192.168.241.1 255.255.255.0
!
router ospf 1
 network 192.168.240.0 0.0.0.255 area 0
 network 192.168.241.0 0.0.0.255 area 0
!
ip route 0.0.0.0 0.0.0.0 192.168.240.1
ip ssh version 2
!
line vty 0 4
 login local
 transport input ssh
!

Salt Master Configuration

The Salt system is amazingly simple and easy to configure, the two components of the Salt system each have a respective configuration file. The salt-master is configured via the master configuration file i.e. /etc/salt/master
Identify the Salt-Master IP address.  i.e. 192.168.100.2

root@mrcissp-master-1:/# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.100.2  netmask 255.255.255.0  broadcast 0.0.0.0
        inet6 fe80::44d:85ff:fe50:8fa3  prefixlen 64  scopeid 0x20<link>
        ether 06:4d:85:50:8f:a3  txqueuelen 1000  (Ethernet)
        RX packets 46  bytes 7327 (7.3 KB)
        RX errors 0  dropped 1  overruns 0  frame 0
        TX packets 12  bytes 936 (936.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Execute “nano /etc/salt/master” & add the IP address to which salt-master will be listening to.

# How often, in seconds, to send keepalives after the first one. Default -1 to
# use OS defaults, typically 75 seconds on Linux, see
# /proc/sys/net/ipv4/tcp_keepalive_intvl.
#tcp_keepalive_intvl: -1

interface: 192.168.100.2

Start salt-master using command “salt-master -d” – where “-d” denotes to run this command in background on “shell terminal”. Also, execute “salt-key” command to verify if Master can hear any minion. Since, we don’t have any minion running as of now. Hence, we don’t see any minion key coming to this Master for authentication.

root@mrcissp-master-1:/# salt-master -d
root@mrcissp-master-1:/# salt-key
Accepted Keys:
Denied Keys:
Unaccepted Keys:
Rejected Keys:

Note: To see details of Public and Private key on Master. Please use “salt-key -F” command.

root@mrcissp-master-1:/# salt-key -F
Local Keys:
master.pem:  1d:a2:06:00:47:c3:e8:93:dc:97:53:a8:07:bb:0d:c2:41:0b:d8:7d:70:ce:9f:32:62:9b:98:11:30:2e:23:cb
master.pub:  88:13:60:51:ef:ee:7a:58:1a:2c:63:a0:08:f4:06:82:9f:df:81:2e:75:7b:fb:96:43:be:6d:bf:bb:e9:6b:07

Salt Minion Configuration

The salt-minion is configured via the minion configuration file i.e. /etc/salt/minion.

Execute “nano /etc/salt/minion” & add the IP address of salt-master used by this Minion

######    Miscellaneous  settings     ######
############################################
# Default match type for filtering events tags: startswith, endswith, find, regex, fnmatch
#event_match_type: startswith
master: 192.168.100.2

Start salt-minion using command “salt-minion -d” – where “-d” denotes to run this command in background on “shell terminal”.

root@mrcissp-minion-1:/# salt-minion -d
/usr/local/lib/python2.7/dist-packages/salt/scripts.py:198: DeprecationWarning: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date.  Salt will drop support for Python 2.7 in the Sodium release or later.
root@mrcissp-minion-1:/#

Execute “salt-key” command to verify if Master can hear any minion now. As we can see – Minion with minion ID “mrcissp-minion-1” is seen at master but it’s keys are not accepted by Master.

root@mrcissp-master-1:/# salt-key
Accepted Keys:
Denied Keys:
Unaccepted Keys:
mrcissp-minion-1
Rejected Keys:
root@mrcissp-master-1:/#

To accept key from respective minion – execute “salt-key -A “minion_id”. We can observe that – authentication key for mrcissp-minion-1 has been accepted.

root@mrcissp-master-1:/# salt-key -A mrcissp-minion-1
The following keys are going to be accepted:
Unaccepted Keys:
mrcissp-minion-1
Proceed? [n/Y] Y
Key for minion mrcissp-minion-1 accepted.
root@mrcissp-master-1:/#

Verify the connectivity b/w Master & Minion

Next step is to verify the connectivity between Master & Minion. To do this, use below command

root@mrcissp-master-1:/# salt '*' test.ping
mrcissp-minion-1:
    True
root@mrcissp-master-1:/#

True: means – Master can communicate with minion
False: means – Master cannot communicate with minion.

Refer to my next blog to understand important nomenclature used in Salt.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.