Enable javascript in your browser for better experience. Need to know to enable it? Go here.
Blogs Banner

Infrastructure as Code: A Reason to Smile

So you receive this unpleasant notification that a server is unreachable. You follow your usual quick fix routines (for example: flip through the logs to see what has happened), only to find out that the server has actually crashed. You freeze! Immediately, you get flashbacks of the hustle that you had to go through while trying to configure that server. You try to recall every component you had installed on the dead machine, plus their versions. It strikes you that you cannot even recall the order in which everything was installed, along with the nitty gritty. You request the ground to open up and swallow you, but unfortunately (or in fact fortunately), it cannot hear you.

Every developer or support person dreads a moment like this when they have to reconfigure the servers, because of the different aspects involved in the seemingly tedious process. But it doesn't always have be to like this.

There's one part of you that says, “I have a solution for that” (to be read with the same enthusiasm used for “I have an app for that!”). And maybe you do have documentation that outlines every step to reconfigure everything. But consider the time you need to invest in order to accomplish your tasks manually.

The systems admin in you is probably saying, “Come on, I have been automating processes like that for ages using my scripts. I could simply do that!”. Well, as presidential campaigns would tell you - "Yes, you can!". But hold on, there is a better way to do it.

Infrastructure as code, or programmable infrastructure, means writing code (which can be done using a high level language or any descriptive language) to manage configurations and automate provisioning of infrastructure in addition to deployments. This is not simply writing scripts, but involves using tested and proven software development practices that are already being used in application development. For example: version control, testing, small deployments, use of design patterns etc. In short, this means you write code to provision and manage your server, in addition to automating processes.

Infrastracture as Code by Kief Morris

It differs from infrastructure automation, which just involves replicating steps multiple times and reproducing them on several servers.

With this, the knowledge of server provisioning, configuration management and deployment is no longer only with the systems admins. Even developers can easily engage in the activities, because they can easily write infrastructure code in the languages that they are familiar with. In addition to this, the learning curve for most descriptive languages used by tools like ansible is not very steep. This makes devops even simpler for a developer.

A vast number of tools like vagrant, ansible, puppet, docker makes the whole process even easier. This is even made better by the fact that server hosting sites like aws are providing RESTful apis that can be leveraged.

Most tools are even idempotent, which ensures that you can run the same configuration multiple times while achieving the same result. For example, consider the following ansible play:

---
- hosts: server
  sudo: yes
  sudo_user: root

  tasks:

  - name: install mysql-server
    apt: name=mysql-server state=present update_cache=yes

  - name: install ansible dependencies
    apt: name=python-mysqldb state=present

  - name: Ensure mysql is running 
    service: name=mysql state=started

  - name: Create user with the password and all previleges
    mysql_user: login_user=root login_password="" name={{ mysql_user }} password={{ mysql_password }} priv=*.*:ALL host=% state=present

  - name: Delete test database
    mysql_db: name=test state=absent

  - name: Create ansible_example database
    mysql_db: name=ansible_example state=present

  - name: Copy mysql back up dump to the remote_user
    copy: src=dump.sql.bz2 dest=/tmp

  - name: Restore the dump into ansible_example database
    mysql_db: name=ansible_example state=import target=/tmp/dump.sql.bz2

It installs mysql-server on the remote machine (server), ensures that mysql is running, creates a user with the password, deletes the test database, creates the ansible_example database, copies a sql dump on to the machine, and restores it into ansible_example database.

All these actions are carried out automatically when the playbook is run. And irrespective of the number number of times it is run, if the task required has already been executed on the machine, the task will not be run again. In other words, it just ensures the machine is in the required state.

Also worth noting is - you can run it from your machine (or any other that has ansible installed) and it is applied to all the machines as specified in your inventory file.

Virtualisation tools like virtualbox and vagrant or docker are really helpful during development as well.

Virtualbox allows you to run several multiple machines with different operating systems on your own computer.

Vagrant wraps around any virtualization tool, to help you quickly spin up the boxes. It bases on already built images (or call them boxes). So you just add it, specify it in your vagrant file, spin up the box and you are good to go. It also allows you to specify the provisioning method or tool to use (e.g chef or ansible) and the script to use. Then it can automatically carry out the provisioning for you.

Docker leverages chroot and linux containers (lxc) to allow you to spin up (and provision if you want) multiple lightweight containers on your machine. This can even be helpful if you are developing for a micro-service architecture.

With the help of these tools and more, development and testing becomes simpler, as one can easily spin up a server and fully configure it even on their development box for use while developing. This eliminates breaking of the common server that is usually shared during development. The QAs can also do the same thing. For example: easily spin up another for his staging environment.

Despite all the different machines involved, there is a sense of confidence that all of them have the same configurations, thus avoiding issues like snowflake servers.

The ability to use version control on your infrastructure code implies that you can easily track all the changes in your infrastructure environment. Therefore, you have an easier option of rolling back configuration changes to a previous  working configuration in case of a problem.

The other sweeter part is that your configurations have the possibility to run on almost anything, from local machine to local physical servers, cloud and virtualisation tools.

On the other hand, there are a few glitches:

1. Having to plan much before the configuration - such as choosing the right tools

2. Bad configurations could get duplicated on all the servers

3. Configuration drift, in which the server configurations are modified on the machines (for example, through hot-fixes without modifying the original templates), makes configurations on the server and in the template to differ. This is      especially true if strict discipline is not followed.

Despite these few mishaps, infrastructure as code will surely bring a smile on your face once you try it out.

This piece has been updated from the original version, which was published on October 27, 2014.

Disclaimer: The statements and opinions expressed in this article are those of the author(s) and do not necessarily reflect the positions of Thoughtworks.

Keep up to date with our latest insights