In recent months, we have engaged in an initiative to automate application deployments and IT infrastructure. As our server-side application stack has evolved, it has become more critical than ever that we employ reliable, replicable methods of software installation and configuration. This is especially true for the management of various deployment environments (development, testing, production, etc.) and for projects that require horizontal scaling.
Additionally, we need to easily run local development environments that replicate the target deployment environment. The sticky issue is that most of our local development occurs on MacBooks (OS X), while server-side deployments target Ubuntu Linux. Thus, we were looking for an IT automation solution that could be easily leveraged to create local virtual machines that were replicas of our deployment environments.
Research and prototyping led us to Ansible and Vagrant. Ansible bills itself as a “radically simple IT automation engine that automates cloud provisioning, configuration management, application deployment, intra-service orchestration.” Using simply defined YAML files that contain IT instructions and SSH sessions, Ansible (running on a “management node”) automates software installation, configuration, and data transfers on remote servers (target nodes) that become deployment environments.
Using an Ansible management node to provision a fleet of servers (target nodes).
The solution outlined in the diagram above had a few shortcomings. First, the Ansible management node tends to need a little bit of provisioning and configuration itself. We could set that up as a remote server to avoid the need to alter our local OS, but that is a bit less convenient and presents a few issues (e.g., the management node often requires personal credentials for Github or AWS and I don’t want to store mine on a remote server). Second, the solution in the diagram doesn’t address the requirement for local deployments. This is where Vagrant comes into the picture.
Vagrant describes itself as a way to provide “easy to configure, reproducible, and portable work environments”, which are basically small VirtualBox-managed virtual machines. One nice aspect of Vagrant is that the VM configuration is easily shared via a single Vagrantfile that defines and installs an OS, port forwarding, and provisioning scripts. This allows developers to “share” a Vagrant VM by Git repository. In addition, Vagrant’s provisioning mechanism supports Ansible, so we can use our Anisble skills to provision the Vagrant VM as an Ansible management node. Using the Vagrant VM as the Ansible management node allows us to 1) avoid many local OS configuration steps (that may differ across OS’s) and 2) provides an easy way for multiple developers to share the Ansible Mangement Node.
Using a Vagrant virtual machine as an Ansible management node.
Vagrant solves the local deployment requirement as well because the Vagrant VM can serve dual purposes of acting as the management node AND the target node. With this configuration, your local Vagrant VM uses Ansible to provision ITSELF, thus giving you a local development environment that is identical to your deployment environment.
Using a Vagrant virtual machine as an Ansible management node that provisions itself and acts as a local development environment.
We’ve been using this solution for the last few months. We first used on a project with a distributed team as a way of developing server-side code on our local MacBooks, and we were able to replicate everything on the server onto our local machines. Now we’re using it on a number of projects such as our Grand Challenge grant, OMK Server, and others. We’re finding value in our ability to collaborate and streamline processes.