In NCR Edinburgh, we are focused in infrastructure automation. We are using Chef and Vagrant to automate our infrastructure, but we are always interested in the development of other automation technologies.
Chef is only one part of a whole stack of technologies that is used to enhance the automation and the reproducibility of virtual environments. Other important technologies are:
Vagrant allows us to combine the configuration management systems with the virtualization technologies. It is:
Saltstack is the response of the python community in the automatic provisioning and configuration management needs of modern information technology. Salt is:
In NCR Edinburgh we are using Chef, so it makes sense to do a 1-1 comparison or the best possible approximation between the two techologies features and components so:
Please keep in mind that this is an approximation. The components are not 100% equivalent. The above mapping means that you can more or less achieve a similar outcome by using the different components in this way.
A minimal Vagrant file that can be used to create a centos6 virtual machine and provisionit with Saltstack is the follwing:
box_type = "chef/centos-6.6"
Vagrant.configure("2") do |config|
config.vm.box = "#{box_type}"
config.vm.provider "virtualbox" do |v|
v.memory = 2048
v.cpus = 1
end
# For masterless, mount your salt file root
config.vm.synced_folder "salt/roots/", "/srv/salt/"
## Use all the defaults:
config.vm.provision :salt do |salt|
salt.minion_config = "salt/minion"
salt.run_highstate = true
end
end
As we can see the only thing that changes between Chef and Salt runs is really the provisioner. Vagrant supports both technologies and many more ( e.g puppet, powershell, bash etc). There is no reason, other than good design best practices, that prevents us from mixing different provisioners inside the same Vagrantfile.
This Vagrantfile, will visit the defined directory, find the minion configuration file, read it and since we set the highstate flag to true, execute it. It will converge the system to the state defined in the minion configuration.
Salt same as Chef, supports various execution modes. It can be used either in a master/minion configuration (a server/client architecture) or as in masterless mode, which is equivalent to chef-solo execution mode. Comparatively setting up a salt master and registering minions is a lot simpler than setting up a Chef server with its chef nodes. Saltstack server can distribute configuration files to its minions using gitfs as the distribution mechanism. This file distribution mechanism is not supported when salt is running in masterless mode.
Masterless mode is relatively simpler. Salt reads a number of configuration files already found on the system, compiles a state list, compares the system against the desired states and converges all the diverging resources to it.
is defined by a:
base:
'*':
- common-tools
- httpd.apache
- dovecot.dovecot
- bind.bind
- db.mysql
- db.postgres
- supervisord.supervisord
This sls file, will go ahead and – install a number of common tools in the new vm, – install apache as a webserver, – dovecot as an imap server, – bind as a dns server, – mysql and postgres databases systems, and – supervisord as a service management system.
This is an automation of a pretty common technology stack used in traditional server setup.
Sls files need to conform to a number of rules:
In this example the pkg mysql and mysql-server are the identifiers (block ids) and pkg and service are the salt modules.
mysql:
pkg:
- installed
mysql-server:
pkg:
- installed
service:
- name: mysqld
- running
Even though in masterless mode we do not have a master to access and retrieve files from, we can still access files in the local filesystem. This is important for automation purposes because, even in an isolated run we can still update a repo of configuration files using an external command over e.g ssh and propagate configuration changes over a number of masterless minions.
supervisor:
cmd.run:
- cwd: /
- user: root
- name: pip install supervisor
- env:
LC_ALL: C.UTF-8
supervisor-init-file:
file.managed:
- name: /etc/init.d/supervisor
- source: salt://supervisord/supervisor
- user: root
- group: root
- mode: 755
As we mentioned earlier, salt uses Jinja for its configuration. In this example we can see a list of different postgres package versions available in the different distrubutions supported by this specific salt configuration.
{% set pg_version = salt['grains.filter_by']({
'CentOs' : { 'id': '8.4' },
'RedHat' : { 'id': '9.1' },
'Arch' : { 'id': '9.1' },
'Debian' : { 'id': '9.3' },
}, merge=salt['grains.filter_by']({
'14.04' : { 'id': '9.3' },
'14.10' : { 'id': '9.4' },
}, grain='lsb_distrib_release', merge=salt['grains.filter_by']({
'jessie' : { 'id': '9.4' },
'wheezy' : { 'id': '9.1' },
}, grain='lsb_distrib_codename', merge=salt['pillar.get']('postgres:lookup')))) %}
Nick Apostolakis
Tags: infrastructure
June 8th 2015