Basic Configuring basic remote execution with a client-server architecture

First up is a bit of an explanation about what Salt is, and why it’s so awesome. Salt was originally designed for high-speed communication (aka remote execution) with large numbers of systems. It then took the next logical step and became a configuration management utility founded on the same principle of fast communication.

So at it’s core Salt is a remote execution engine, that establishes a high-speed, secure and bi-directional communication grid for groups of systems. Then on top of that, Salt provides an extremely fast, flexible and easy-to-use configuration management system.

What I love most about Salt is how easy it is to use as a configuration management tool. The configuration files are written in yaml format and Salt provides many options for templating with jinja (amongst other engines). It’s relatively simple to look at your files and know exactly what’s going on.

We’re not going to cover the configuration management portion today, we’re going to focus solely on the remote execution process.

Remote execution requires a master and client (or minions as they are referred to in Salt) relationship.

Set up the salt-master

Firstly you will need to install salt. You can install via pip with pip install salt, via rpm with yum install salt-master (you will need the EPEL), or via a bootstrap script on GitHub (example one liner: curl -L https://bootstrap.saltstack.com | sudo sh).

Once you’ve installed Salt, you will need to start the service with service salt-master start and enable it at boot with chkconfig salt-master on.

For a CentOS 6 box setting up the salt-master with rpms looks like:

rpm -Uvh http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
yum install salt-master -y
chkconfig salt-master on

This assumes that you’re not using iptables, but if you are:

\-A INPUT -m state --state new -m tcp -p tcp --dport 4505 -j ACCEPT
\-A INPUT -m state --state new -m tcp -p tcp --dport 4506 -j ACCEPT

Set up the salt-minion

Firstly a bit of prep work is needed so that your minion can find a salt-master. By default the salt-minion looks for ‘salt’ on the network.

You can customize the minion’s configuration file manually or you can set the minion’s hostfile to point at the salt-master. Generally I like to set the hostfile and have the minion bootstrap everything (including the minion configuration). For example:

echo ‘192.168.250.100 salt’ » /etc/hosts

Next you will need to install salt. You can install via pip with pip install salt, via rpm with yum install salt-minion (you will need the EPEL), or via a bootstrap script on GitHub (example one liner: curl -L https://bootstrap.saltstack.com | sudo sh).

Once you’ve installed Salt, you will need to start the service with service salt-minion start and enable it at boot with chkconfig salt-minion on.

Back on the salt-master, run salt-key -A -y to accept all connected minion keys. Alternatively, if your environment makes sense to do so, set a cronjob to accept keys:

crontab -l | fgrep -i -v 'salt-key -A -y' | echo '\* \* \* \* \* salt-key -A -y' | crontab -

Running remote commands via the salt-master

The basic syntax for running a command from the salt-master is:

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

To target a system you can specify it via the minion id like:

\# All Minions
salt '\*' <function> \[arguments\]

# Minions that start with "dev"
salt 'dev\*' <function> \[arguments\]

# Minions with ".db." in the id
salt '\*.db.\*' <function> \[arguments\]

You can also target minions based on system information (embedded into what salt calls grains) like:

\# Target boxes running Fedora
salt -G 'os:Fedora' <function> \[arguments\]

# Target boxes running a custom role
salt -G 'role:web' <function> \[arguments\]

You can use salt '*' grains.items to identify available grains to match against.

You can combine types of queries like this:

\# Match on OS and minionid
salt -C 'G@os:CentOS and web\* or dev\*' <function> \[arguments\]

Once you can target systems you need to know how to actually run commands. There are lots of available commands or functions that we can run out of the box (you can also expand on this). You can get a list using the salt '*' sys.doc command.

The most common useful commands that I frequently use are:

  • test.ping - tests whether or not the minion(s) is available.
  • cmd.run - run arbitrary commands.
  • state.sls - apply a configuration state.
  • state.highstate - apply all applicable states.

Some working examples (just targeting all minions):

\# Test whether minions exists.
salt '\*' test.ping

# Run an arbitrary command.
salt '\*' cmd.run 'yum update -y; service httpd restart;'

Avoid commands like this unless you want to ruin everything:

salt '\*' cmd.run 'rm -rf /;'

Example environment with Vagrant

You can see an example environment using SaltStack and Vagrant on my GitHub account here.