Getting Started with Saltstack – Part 2

In the first part of this tutorial we set up Salt on a simple setup and played around with some basic commands from command line. In this part of tutorial we will go ahead and write a complete module for installing and configure a web server. This will also introduce us to some of Salt’s terminology and working in detail. By end of this tutorial we will have installed apache2 displaying a custom page with info specific to that node. We will also setup apache such that it restarts by itself if it goes down at all. From salt’s perspective we will write a short formula, utilise values from Pillar and Grain and use beacon to watch service and send a event which will be caught by reactor to restart the service. But don’t get scared – we have a working setup and you can always play around.  Do check out the project from link so that you can follow along.
Before we build out the code for formula (Which is equivalent to playbook in Ansible, Cookbook in Chef or Module in Puppet) – let’s understand how salt finds out what it needs to execute.
salt_structure
The only difference in diagram and our case is: to enable any changes we make locally to be visible in Salt vagrant machine immediately – I have added /vagrant/salt/srv/salt and /vagrant/salt/srv/pillar  directories to the roots. Since /vagrant is the directory from host – any changes we make in editor will be made directly to Vagrant machine. Going forward we will refer as salt_root & pillar_root to refer to formula & pillar base directories respectively.
In salt_root create a directory named apache and inside it init.sls looks like:
The above is super simple! There are two blocks – one is installing apache and other is making sure it is running. Let’s look at first block: “install-apache” is just a title and can be anything but has to be unique in a formula. Second line calls a module named “pkg” and expects the state to be “installed”.  The name attribute provided to state tells what needs to be installed. There are lot more attributes that we can pass to installed state and lot more states available in pkg module as documented here. As a Salt engineer you will need to refer to documentation quite often to write appropriate states. Now add in salt_root directory a file top.sls with following contents.
 We are telling salt to include apache formula for all nodes which have a grain roles with value as apache in base environment. Similarly you could have MySQL installed only on certain roles/sites etc. For things which need to be installed on all nodes, we could use ‘*’ to target all nodes. But for above top.sls file to work – we will have to add role apache to our nodes where we want apache installed. We can go and edit /etc/salt/grains on all nodes and restart minions or we could again use command line to achieve the same. Let’s use command line:
 Let’s look at how that reflects in grains file:
Now if we restart our minions and run highstate – it will execute all modules which match criteria on given nodes:
Let’s get ip_addrs of our nodes and then test in browser by hitting at port 80 to check if apache was indeed installed. You should see default apache info page.
Alright but default apache is no good for us, neither it is any fun. Let’s go ahead and customize it for our top secret company we are going to launch some day. Let’s add following block to $salt_root/apache/init.sls:
What’s going on here? So we are managing a file through Salt – this file is the one which Apache was displaying earlier – but now we are modifying it to show content we intend to show. For that we using a file in files directory as source and using templating engine called Jinja. Now let’s look at content of the template (Most of HTML part truncated – check complete file in source code):
All we are doing is embedding some dynamic content in between some static content. We got the machine ID by querying grain and got the greeting message from Pillar. There is a lot more you can do with Jinja and Salt and you should check out documentation here. Finally for this to work, we will have to add following in $pillar_root/apache.sls:
And following in $pillar_root/top.sls file:
And now it’s time to see some fun. Let’s first refresh Pillar cache so that latest file changed we made are picked up and then run highstate to deliver the file to target server:
 Now if you hit browser at port 80 on the machine on which highstate ran successfully – you should see a webpage with our custom page. Now let’s go to our last part – using beacon and reactor to restart apache if it goes down, here is overall scheme of things:
BeaconReactor
First thing is to configure beacon to watch apache2 service. We will configure this through pillar (And there are other ways like configuring in minion config file), add a file $pillar_root/beacon.sls with code:
And add entry of beacon in $pillar_root/top.sls (Like we did in case of apache). Before we go to reactor – let’s check if beacon is behaving the way it should. Refresh the pillar on all minions and then in one prompt open salt master & minion in other. On salt master we will fire a command to watch event queue and then stop apache. Ideally this should be seen as an event in salt master terminal:
This confirms that beacon is reporting the change in state of apache service. Now let’s configure a event watcher, this file will reside in /etc/salt/master.d and you will need to uncomment a setting ‘default_include’ in master config, I have done this in code attached if you want to check out.
And the file apache_down.sls will look like:
In above snippet – we are digging in data of event and checking if running state is false – and if that is the case then issue command only on that minion to restart apache. The ‘tgt’ attribute is the one which says target only minion from which this event was received. Having built this – it’s time to see it in action. Restart the salt master – so that reactor config is picked up. In one terminal open salt master and start looking at event queue and in another go ahead and stop apache2 service.
You will notice that in addition to earlier event from beacon, you will see reactor reacting to event – and it is event from master to minion signified by  ‘salt/job/20160428071412092896/ret’ and once apache comes up – beacon again reporting the event but now “running” is true.
Just to recap: We wrote a first formula which managed Apache with our custom homepage during which we touched upon jinja, grains & pillars. We then built a mini demo of how beacon and reactor works together. If you have any questions or bugs to report feel free to comment/raise issue on Github.
Vishal Biyani

Author Vishal Biyani

More posts by Vishal Biyani

Leave a Reply