This blogpost is an introduction to Saltstack, a configuration management system we are using within Enrise.
What is Salt?
No, we’re not talking about the mineral or condiment but about SaltStack.
Saltstack is a Python-based open-source configuration management software and remote execution engine. Plainly put, this platform allows us to define our ‘Infrastructure as Code’.
This configuration specifies what a server should do (e.g: it’s a web server running NGINX with PHP7) and Salt ensures this server is following this configuration. It will install the required packages and configurations and make sure the server remains in this state.
The Salt platform consists of two main components: the master and minions.The minions connect to the master via an encrypted eventbus (either via ZeroMQ or RAET) and use this to communicate internally. The master holds the configurations and provides these to the minions whenever they need it.
Within the Salt platform there are several components:
- States: These tell a minion to do something (e.g. install NGINX). States are – by default – based on Jinja2 templated files
- Pillars: This is the configuration of a server (e.g. which domains a server hosts) represented in YAML.
- Grains: These are minion-specific values that can be used in the states (e.g. OS version)
- Formulas: A group of states revolving around a certain component (e.g. NGINX)
Salt at Enrise
Prior to using Salt we were using Puppet within our environments. While this did get the job done, we weren’t too happy about how it worked and generally the knowledge of its inner workings where not known by everyone. Adding a new component took a lot of work and effort to get right.
We then slowly started migrating towards Salt. New environments were being set up using Salt and eventually all old systems were migrated to the new system.
We’d liked to have a view of what’s happening within Salt. For this we have created a dashboard showing the latest state runs. With this dashboard we have a quick overview of the latest state of a machine and can easily spot if something went awry.
Salt returns its state data to the master which we capture from the eventbus using salt-eventsd which formats the results and stores them in a database. The dashboard reads from this database and generates an overview based on this data.
Apart from that we have also linked this eventsd system to our Zabbix (in Dutch) monitoring system so we can easily see if a state run failed.
In a recent project we worked on a client asked us to set up an extensive TAP (Testing, Acceptance, Production) environment on Amazon AWS. Since this involved a clusterized setup with a lot of different components with similar configurations spread out over 3 environments we decided to set this up using Salt. This allows us to set up identical environments which are easily extendible, but also easily recoverable in case of emergency.
Salt offers two methods of doing this, either by using the modules for services like EC2, RDS or by using the Salt-cloud component. We decided for the former since it gave us greater flexibility and created an aws-formula for this to make it easily manageable via the Pillars.
Apart from the configuration management Salt provides there is also support for Remote Execution. Using this you can run commands on servers or retrieve information.
It can be used to query information (e.g. which version of NGINX is installed) or execute commands (e.g. ping this node).
Within our development process we make extensive use of Vagrant to setup a virtual development environment. Our Vagrant boxes are configured using the Enrise Basebox which essentially is a Vagrantfile and a collection of Salt states, formulae and pillars to deal with the configuration.
Why Salt and not …?
We are strong believers of ‘the right tool for the right job’. In our case this was Salt since it does what we need it to and since it is Python we are able to extend upon it fairly easily.
For some projects we’re also using Ansible in environments where the server-client setup isn’t practical or desirable.