Image for post
Image for post

Vagrant Provisioning with SaltStack

Provisioning Virtual System using Masterless Salt Stack

This tutorial covers provisioning systems with a Vagrant provisioner for Salt Stack. This will demonstrate how to create a local development environment for crafting your own Salt Stack solutions.

About Salt Stack

Salt Stack is a distributed remote execution platform with change configuration (desired state). Salt Stack scripts are called states and can be grouped into a component structure called a formula. A formula can contain several states, local variables, files, and templates. In addition to states and formulas, Salt Stack uses pillars to store variables and arbitrary data and secrets.

Activities within the Salt Stack system are coordinated with Salt Master server(s) and a message queuing control bus, with minions installed onto the clients.

This organizational structure allows for not only high performance scenarios, but for managing cloud based infrastructure as well as services that exist as clusters, like Elastic Search, Apache Kafka, Apache Spark, Apache Storm, or Kubernetes.

Prerequisites

Image for post
Image for post
Prerequisites

This tutorial requires these components:

I have published some previous guides on installing Vagrant and Virtualbox on macOS, Windows, and Linux operating systems.

Using Chocolatey to install the requirements:

Using Homebrew to install the requirements:

Using native package manager Dandified YUM, or in short DNF, to install requirements:

Part I: Salt Formula with Intelligent Defaults

We’ll start this tutorial with a Salt Stack Formula called hello_web that will install an Apache web server and copy over HTML content on Ubuntu system.

Vagrant will call Salt Stack to run this formula using masterless mode.

We need to lay down some roots…

Using Bash shell, we can create our overall staging area and structure for this tutorial.

The resulting structure will look like this, with our formula under the salt directory.

Update the Vagrantfile to have this content, using the Ubuntu box from the Bento project:

We can see provisioner doesn’t do much of anything, except use the default behavior, which are looking for the top.sls in /srv/salt and /srv/pillar. These are mounted from out local roots directory.

In the top file, we can organize and group several systems, and then specify what to do on them, such as formulas to run. For our one machine scenario, we’re going to run the formula hello_web on all systems.

Update the state/top.sls to mach the following:

Similar to the top salt state, we want to configure variables and data for our systems, which is all systems again, all systems being our one guest Ubuntu system.

Update the pillar/top.sls to match the following:

Now we can dive into developing our formula. First let’s create intelligent default variables that make sense for an Ubuntu system.

In the hello_web formula, update the defaults.yaml with the following:

Now we can create a map that glues in all of our variables that we would like to use for this formula. The map is essentially a Jinja template.

In this map, we want to we will import our defaults, optionally specify our own local variables, and then merge in variables from pillar.

In the hello_web formula, update the map.jinja with the following:

Update: I added or defaults.get('hello_web') for the off chance you add an empty hash of hello_web to roots/pillar/hello_web.sls. This would cause Salt Stack to ERROR because is cannot merge None with default hash.

The main course has arrived with our Salt State file. In the hello_web formula, update init.sls with the following:

This needs some explanation…

The first thing here to to make a bold declaration!!!

Er, um, rather, I mean an identity declaration that I like to use to group all of the states together under hello_web, but serves a functional purpose to declare a high state component within Salt Stack.

Under this identity declaration, each of the following members will have will be a state module (pkg, service, file) followed by a corresponding state function (installed, running, managed). Under these state module and state function keys, we supply a list of parameters that will be passed to the function, such as a name parameter that makes sense to the state, like a package name, a service name, and a file name.

Salt States can use Jinja, reference variables, whether they are local default variables of the formula, or variables set in a pillar.

Now let’s bring up our virtual guest, provision the system, and then use lovable curl command on the host:

This should result in the following:

Part II: Salt Formula and a New Pillar

Let’s shift gears and use the delicious Linux flavor of CentOS from the Bento folks.

As the default variables in the hello_web formula will not work well for with CentOS, we’ll need to specify different variables using pillar. The hello_world formula will scoop these pillar variables up and use them instead of the default variables.

Update the Vagrantfile with the following:

We can add new pillar values with the salt provisioner by calling the pillar method and passing in a single ruby hash. Vagrant converts this ruby hash to a Python dict format and passes it on the command line to salt-call state.highstate in our case. For more information, see Vagrant docs on Pillar Data.

Side note: For the those uninitiated to Ruby, when passing anonymous hashes, you can remove the outer curly braces {}, and when using a parameter list, you can omit the outer parenthesis (). Thus:

First destroy our existing virtual guest running the previous distro and bring this new one up with CentOS, and then test again with curl:

This will give us the following:

Final Thoughts

Well, not stating the obvious, but this with Vagrant you can achieve a new pillar of success or high state of achievement by sprinkling a little salt across your systems.

You can quickly develop, test, and learn Salt Stack environment in a controlled and repeatable way across a variety of distributions. I hope this tutorial has helped begin that journey.

Written by

Linux NinjaPants Automation Engineering Mutant — exploring DevOps, Kubernetes, CNI, IAC

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store