This is an assignment h1 - Palvelinten hallinta ICT4TN022-5 in Haaga-Helia University of Applied Sciences

SaltStack Platform, or Salt, is open-source configuration management software, which provides infrastructure management as a code. Salt provides fast and flexible management via its “Salt states”.

For the examples below I’m using Lenovo Z710 which is running OpenSUSE Tumbleweed for my local minion and my master computer is VPS provided by DigitalOcean running Ubuntu 16.04.

Salt Installation

On my local computer, and my minion computer, I’m using OpenSUSE Tumbleweed which uses zypper as its package manager. To install salt-minion, run:

(minion)$ sudo zypper ref

(minion)$ sudo zypper in salt-minion

On my server, and my master computer, I’m running Ubuntu 16.04. To install salt-master, run:

(master)$ sudo apt-get update

(master)$ sudo apt-get install salt-master

Since my master computer is online I need to make a hole in my firewall to make it possible to connect to it. Salt uses ports 4505/TCP and 4506/TCP for its connections. To make a hole for Salt, run:

(master)$ sudo ufw allow 4505/tcp

(master)$ sudo ufw allow 4506/tcp

Before you start using Salt you need to make a master-minion pair between your computers. On your minion computer you need to insert your master computer’s ip-address to your minion’s Salt configurations:

(minion)$ sudo emacs /etc/salt/minion

Add following to the end of the file:

master: master's ip-address

You can print your ip-address with hostname -I.

After these configurations you need to restart your Salt on your minion and master computer:

On minion:

(minion)$ sudo systemctl restart salt-minion.service

Update 04.04.2018: Removed unnecessary command

Before you can start running commands remotely on your master you need to accept the minion computer as a pair. To do this, run following on your master computer:

(master)$ sudo salt-key
Accepted Keys:
Denied Keys:
Unaccepted Keys:
tumble
Rejected Keys:

Here you can see that my local computer, tumble, is listed at Unaccepted Keys. To accept your minion computer’s key, run:

(master)$ sudo salt-key -A 
The following keys are going to be accepted:
Unaccepted Keys:
tumble
Proceed? [n/Y]

Then just pressing Return you’ll accept the key.

Now you can test if your Salt is working correctly by running command on your master:

(master)$ sudo salt '*' cmd.run 'ls /'
tumble:
    bin
    boot
    dev
    etc
    home
    lib
    lib64
    mnt
    opt
    proc
    root
    run
    sbin
    selinux
    srv
    sys
    tmp
    usr
    var

And seems that Salt is working as intended.

Salt States

Next I tested some example Salt states. I made a state that installs few mandatory packages for my personal workflow. Also following steps are done at root shell on my master computer, which is indicated by #.

First I’ll create folder for my Salt states:

(master)# mkdir -p /srv/salt

Then I’ll create state that installs following packages for me:

(master)# emacs /srv/salt/workstation.sls
install_workstation:
  pkg.installed:
    - pkgs:
      - emacs
      - openssh
      - git
      - rsync

To apply this state, run:

(master)# salt '*' state.apply workstation
tumble:
----------
          ID: install_workstation
    Function: pkg.installed
      Result: True
     Comment: All specified packages are already installed
     Started: 19:15:27.361419
    Duration: 17690.959 ms
     Changes:   

Summary for tumble
------------
Succeeded: 1
Failed:    0
------------
Total states run:     1

And it succeeded!

Since I already had those packages installed, I’ll try to install something that is not present in my minion computer, but which I user regularly.

(master)# emacs /srv/salt/workstation.sls
install_workstation:
  pkg.installed:
    - pkgs:
      - emacs
      - openssh
      - git
      - rsync
      - neomutt

tumble:
----------
          ID: install_workstation
    Function: pkg.installed
      Result: True
     Comment: The following packages were installed/updated: neomutt
              The following packages were already installed: emacs, openssh, git, rsync
     Started: 20:04:37.729331
    Duration: 32547.175 ms
     Changes:   
              ----------
              gpg-pubkey:
                  ----------
                  new:
                      3dbdc284-53674dd4
                  old:
                      1abd1afb-54176598,307e3d54-4be01a65,3dbdc284-53674dd4
              kernel-default:
                  ----------
                  new:
                      4.15.13-1.6
                  old:
                      4.15.10-1.5,4.15.13-1.6
              kernel-default-devel:
                  ----------
                  new:
                      4.15.13-1.6
                  old:
                      4.15.10-1.5,4.15.13-1.6
              kernel-devel:
                  ----------
                  new:
                      4.15.13-1.6
                  old:
                      4.15.10-1.5,4.15.13-1.6
              kernel-source:
                  ----------
                  new:
                      4.15.13-1.6
                  old:
                      4.15.10-1.5,4.15.13-1.6
              kernel-syms:
                  ----------
                  new:
                      4.15.13-1.6
                  old:
                      4.15.10-1.5,4.15.13-1.6
              libgmime-3_0-0:
                  ----------
                  new:
                      3.2.0-2.1
                  old:
              libkyotocabinet16:
                  ----------
                  new:
                      1.2.76-14.1
                  old:
              liblmdb-0_9_17:
                  ----------
                  new:
                      0.9.17-3.2
                  old:
              libnotmuch5:
                  ----------
                  new:
                      0.26-1.1
                  old:
              libxapian30:
                  ----------
                  new:
                      1.4.5-1.1
                  old:
              neomutt:
                  ----------
                  new:
                      20180323-1.1
                  old:
              neomutt-doc:
                  ----------
                  new:
                      20180323-1.1
                  old:
              neomutt-lang:
                  ----------
                  new:
                      20180323-1.1
                  old:
              perl-Expect:
                  ----------
                  new:
                      1.35-1.2
                  old:

Summary for tumble
------------
Succeeded: 1 (changed=1)
Failed:    0
------------
Total states run:     1

And it successfully installed neomutt to my minion.

Salt Grains

You can easily fetch system information from your minion with grains.

To fetch all information, run:

(master)# salt '*' grains.items |less

This then opens a long list of different system information in less view.

For security reasons I won’t post these information here.

Salt in Real-Life

Last I’ll test Salt in “real-life”. So I use it in something useful that might be needed in the real world.

In this example I’ll install Go programming language environment to my minion computer and I’ll do the necessary configurations from my master.

First I’ll make a state for this:

(master)# emacs /srv/salt/go.sls
go:
  pkg.installed: []

setup_env:
  cmd.run:
    - runas: topi
    - name: 'source /etc/profile.d/go.sh'
    - require:
      - pkg: go
	  
gotour:
  cmd.run:
    - runas: topi
    - name: 'go get golang.org/x/tour/gotour'
    - require:
      - pkg: go

I then apply this state to all my minions:

(master)# salt '*' state.apply go
tumble:
----------
          ID: go
    Function: pkg.installed
      Result: True
     Comment: The following packages were installed/updated: go
     Started: 21:47:18.508231
    Duration: 61382.782 ms
     Changes:   
              ----------
              go:
                  ----------
                  new:
                      1.9.4-2.1
                  old:
              go-race:
                  ----------
                  new:
                      1.9.4-2.1
                  old:
              go1.9:
                  ----------
                  new:
                      1.9.4-3.1
                  old:
              go1.9-doc:
                  ----------
                  new:
                      1.9.4-3.1
                  old:
              go1.9-race:
                  ----------
                  new:
                      1.9.4-3.1
                  old:
              gpg-pubkey:
                  ----------
                  new:
                      3dbdc284-53674dd4
                  old:
                      1abd1afb-54176598,307e3d54-4be01a65,3dbdc284-53674dd4
              kernel-default:
                  ----------
                  new:
                      4.15.13-1.6
                  old:
                      4.15.10-1.5,4.15.13-1.6
              kernel-default-devel:
                  ----------
                  new:
                      4.15.13-1.6
                  old:
                      4.15.10-1.5,4.15.13-1.6
              kernel-devel:
                  ----------
                  new:
                      4.15.13-1.6
                  old:
                      4.15.10-1.5,4.15.13-1.6
              kernel-source:
                  ----------
                  new:
                      4.15.13-1.6
                  old:
                      4.15.10-1.5,4.15.13-1.6
              kernel-syms:
                  ----------
                  new:
                      4.15.13-1.6
                  old:
                      4.15.10-1.5,4.15.13-1.6
----------
          ID: setup_env
    Function: cmd.run
        Name: source /etc/profile.d/go.sh
      Result: True
     Comment: Command "source /etc/profile.d/go.sh" run
     Started: 21:48:19.895745
    Duration: 120.925 ms
     Changes:   
              ----------
              pid:
                  22551
              retcode:
                  0
              stderr:
              stdout:
----------
          ID: gotour
    Function: cmd.run
        Name: go get golang.org/x/tour/gotour
      Result: True
     Comment: Command "go get golang.org/x/tour/gotour" run
     Started: 21:56:12.672896
    Duration: 19342.375 ms
     Changes:   
              ----------
              pid:
                  23772
              retcode:
                  0
              stderr:
              stdout:

Summary for tumble
------------
Succeeded: 3 (changed=3)
Failed:    0
------------
Total states run:     3

Here the setup_env state is not working as intended, since it doesn’t source the designated file. During installation Go, source /etc/profile.d/go.sh is required for setting the Go environment variable during your current session. You can get the right variables if you log out and log back in.

I’ll try to figure it out why this doesn’t source the file correctly. To set the correct variables, during your current session, run:

(minion)$ source /etc/profile.d/go.sh

Then you can check your environment variables by:

(minion)$ env | grep GO
GOPATH=/home/topi/go:/usr/share/go/1.9/contrib
GOROOT=/usr/lib64/go/1.9
GOOS=linux
GOARCH=amd64

Go also uses one designated directory for all your projects, usually ~/go. Installation doesn’t make this directory automatically, but if you have your environment variable set correctly you can download any package via go get and it creates this directory.

State gotour runs go get golang.org/x/tour/gotour, which then creates this directory.

We can check that if it worked as intended:

(minion)$ ls -l go/
total 0
drwxr-xr-x 2 topi users 20 Apr  2 21:56 bin
drwxr-xr-x 3 topi users 25 Apr  2 21:56 pkg
drwxr-xr-x 3 topi users 24 Apr  2 21:56 src

We can then test if the Go language works:

(minion)$ cd ~/go/bin/
(minion)$ ./gotour

Note that you can run Go programs just by typing, e.g., gotour if you have set your ~/go/bin to you PATH variable. Which is something that I could add to this state eventually.

It opened a Tour of Go to my web browser. So Go is working as intended.

Resources

Update 04.04.2018: Added resources