Help, I've been a-salt-ed!

I love to start posts with a terrible pun. I also love Salt. If you’re not familiar with Salt, it’s a tool for managing servers, similar to the likes of Puppet and Chef. They all claim to be great for taking control of an army of machines, but for my purposes I just wanted to be able to quickly deploy code changes to a single machine. Each obviously has its pros and cons, and you might come to a different conclusion of what’s best for you based on your requirements. Having not installed and used Puppet or Chef, I can’t guarantee the accuracy of what I’ve written about them below, although I have done my best to get accurate information from their documentation.

Puppet

Puppet is written in Ruby, and has the concept of “manifests” which are interpreted and applied on the server. They are written in the Puppet language, and the syntax is similar to Ruby. Manifests can do anything from describing file ownership and permission to creating system users, managing databases and installing packages. One cool feature is that you can have Puppet restart a service if a configuration file changes on the manifest execution.

In its simplest form, manifest files are stored and applied directly to the server on which they’re executed, however Puppet can also be used in master/agent mode. Agents are configured to pull the manifests that apply to them from the master, and will by default check for updates every half hour. On demand updates could be achieved by scripting ssh to log into each managed server and execute the agent, but this seems to be out of scope for Puppet (at least the open source version, maybe Puppet Enterprise can do this).

Puppet has excellent documentation and a great quick getting started tutorial.

Chef

Like Puppet, Chef is written in Ruby. The Chef project has embraced the whole cooking metaphor to describe parts of its system: recipes describe the configuration, multiple recipes will make up a cookbook, which can be stored in a bookshelf; there’s also “knife”, the command line interface to all this. Recipes are written fully in Ruby, so it looks like you would need a good understanding of the language to take full advantage of Chef features.

The Chef tutorial walks through setting up Apache by having Chef read recipes from a Chef server, but Chef can also be run serverless with chef-solo (or just running chef-client with a --local flag in recent versions. When running Chef server, executing knife commands will trigger their effect immediately on the Chef clients, and advantage over Puppet.

Again, like Puppet, Chef has excellent documentation and a quick start tutorial.

Salt

It’s no surprise that I love Python, which may have influenced my decision to use Salt. Salt’s configuration files are called “pillars”, and are written in YAML, so they’re concise and easy to understand. Salt also uses the Jinja templating engine to allow these to be configured on-the-fly with variables. Salt’s main mode of use is with minions and a master, which communicate using ZeroMQ. Minions find the master by resolving the host “salt”, and pushing out changes happen instantly. Apparently, due to the fact Salt uses ZeroMQ and not SSH, it is much faster than Chef, I can’t comment on this however.

Salt also has a masterless mode, which means the minion executes salt-call locally, reading all pillars from the local file system. There’s salt-ssh which lets you do Salt stuff over ssh, however I didn’t have much luck getting this working in my setup; I didn’t persevere too much because I had already created my own SSH solution (below).

Push Button Deployment

I’m working on a new project, and I wanted to get the deployment right from the start. My ultimate goal was to be able to make all config changes in local files, and be able to push a button to get the latest code onto the server. By using SSH and salt together, this turned out to be pretty simple.

#!/bin/bash

scp -r srv-salt/* $1:/srv/salt/
ssh $1 'sudo salt-call --local state.highstate'

I now have salt configs that will create users, set up databases, upload configs for nginx and create Python virtualenvs in a matter of seconds.

The Good Bits

Starting new projects is always a good excuse for me for playing with new technologies. I decided to give Amazon EC2 a try, as I’d never used it before. I set up a free VM and experimented with it getting my required services running on it using salt. Everything was up and running, and a few hours later the server stopped responding for some reason. A reboot fixed it, but I discovered that unless you’re using an Elastic IP, your EC2 instance will get a new public IP address on reboot. This is obviously not ideal, so I decided to set up a paid virtual sever instead (Digital Ocean, if you’re wondering). Thanks to salt, I was back up and running on my new server within 5 minutes (the only manual process being install salt and setting up an admin user). Very cool.

The Not So Good Bits

I don’t yet have code-deployment working as well as I’d like. It is a manual process to clone the git repo to the machine and git pull from the master branch when it’s time to update. I’m sure I could code up a custom salt pillar to make this nicer but at this stage it’s not that hard to do.

Conclusions

Automated deployment is not a new concept, however, I’d never tried it before, always just doing things the manual way. Salt is awesome, and works just how I want it, and from what I’ve researched, Puppet and Chef should work just as well. If you’re not doing it yet, give it a try, it will change your system management life.

Previous entry

Next entry