It’s a long time ago that system administrators used to manually configure the infrastructure (hardware and software) on which applications are hosted. With the adoptation of DevOps culture and emergence of public cloud infrastructure creation and provisioning seems to be shifting left in devops cycle. One of the critical components of this trend is called “Infrastructure as Code (IaC),” In this blog, written for DevOps engineers and architects, I will share my experience with Infrastructure as Code and talk about some market leaders in this domain.
Infrastructure as Code (IaC)
Wikipedia defines IaC as follows: “Infrastructure as code is the process of managing and provisioning computer data centers through machine-readable definition files, rather than physical hardware configuration or interactive configuration tools”
In simpler terms: Infrastructure as code (IaC) refers to managing IT infrastructure using configuration files. These configuration files are version controlled, consistent and can be used by different automation tools for mutable infrastructure setup.
War of IaC’s
Searching Infrastructure as Code on internet will show plethora of options like Chef, Puppet, Ansible, Terraform, CloudFormation etc. What’s not easy to find is which tool you should use and fits your purpose. Therefor, I will compare two of the most used IaC’s: Terraform and Ansible, and try to break down who is winning this war of cloud IaC supremacy.
State management is one of the main differences between both the tools and hence we should talk about this upfront. Ansible is a stateless IaC configuration tool. The configuration files do not represent the state of system and any change in the configuration does not care about current state of system. It offers some explicit modules like set_facts to read the actual system but there is no implicit support for this.
On the other hand, terraform is built on top of a state persistency system. Each time configuration of the system changes, a state file is written with the new state of system and each time a change is executed that is first compared with previous state and only differential of the new and old state is incorporated into the system.
Mutable Vs Immutable Infrastructure
Ansible typically defaults to a mutable infrastructure pattern, that means if you ask ansible to deploy new software it will run an update on your existing servers and changes will happen in-place. That means in a period of time, there is a possibility of different minor software version differences between the servers. This phenomenon is known as configuration drift.
In case of terraform, default is immutable infrastructure pattern in which each update forces new infrastructure creation and uses golden images as source of truth.
Mutable infrastructures have, of course, a faster execution time but lower reliability. It also has higher configuration issues over a long period of time if it’s not maintained properly by a system administrator.
Procedural vs Declarative
Ansible is a procedural style of provisioning which expect step by step configuration to reach a desired end state. In contrast terraform uses declarative approach in which terraform decide the steps to reach user provided end state. For example, below is code snippet of creating 5 EC2 instances by Ansible and Terraform
Both seems similar and equally effective on the surface of it. But difference became quite apparent when we want to modify the behavior. Suppose due to increase in load we want to scale instances to ten instances. If you update above code and make count ten in both the snippets and rerun the script Ansible will create 10 more servers and in total there will be fifteen servers whereas Terraform just create 5 more servers and maintain proper end state.
Of course, this is very simplified example and Ansible has capability of calculating number of instances already running based on tags and facts and only create additional instances like Terraform but that logic needs to be programmed and not in-built in the language itself like terraform has. Also, the reusability of procedural code is very limited as system administrator has to know upfront the state of system in comparison to actual resources.
Ansible in a nutshell can be compared to an interpreted language which cannot judge errors till it hit that particular line/command. So, feedback of error in large playbooks is pretty poor. Ansible lint can help in eliminating the syntax errors but configuration issues can only be identified at the runtime.
In contrast, Terraform can be compared to a compilation language and it sort of dry run the full configuration during terraform plan and provide error feedbacks before actually applying the configuration.
Ansible provides error handling and rollback features via error block handlers which are basically programmable blocks/procedures which can do actions if a task fails.
Basic Ansible error rollback blocks
Unfortunately, there is no rollback mechanism for Terraform and it relies on version Control systems to restore back to previous state by running the old working configuration.
Configuration management, i.e., installing and managing software packages on a server in a cloud agnostic manner, is where Ansible shines brighter than its competitors. It provides inbuilt package managers to work at OS level to remove dependency of cloud provider and makes tedious task of configuring even a bare metal server simple and easily manageable.
Terraform is not a configuration manager tool and it depends on scripts and procedures supported by a particular cloud/VM/OS to install software’s on the servers. For example, for provisioning software on AWS EC2 we have to provide userdata script in bash/shell.
With emergence of technologies like docker container and packer golden images this is becoming less and less relevant but for now it is a win for ansible.
Ansible uses YAML with Jinja2 scripting to write IaC configurations whereas Terraform uses HCL (Hashicorp Configuration Language) which resembles JSON and completely JSON compatible.
Ansible uses concept like vars and roles for modularization whereas terraform works on concept of modules and submodules.
Also, both tools are open source and extendable. Python modules can be written for extending Ansible whereas Terraform uses up and coming Golang at its base. We can say that Ansible has a little edge in that respect as we will deal with some known and well used programming language but terraform also does not seems like an alien language and HCL is said to be closer to humans than machines.
Both Ansible and Terraform are open source projects with huge community contributors and support. They have an extensive list of plugin and modules and supports almost all cloud and non-cloud infrastructure platforms.
Being an early entrant in market of IaC’s Ansible holds a good lead in this regard, but if we see recent trends Terraform is growing at a pretty fast pace than Ansible. In fact, at the time of writing Terraform has more external integration/provider than Ansible which will expand its utility in coming years.
Also, in terms of documentation, Terraform seems to be more organized, elaborated and easy to search than Ansible, but of course that depends on individual perspective and preferences.
As stated before, both are very good Infrastructure as Code tools, having their own strengths and weaknesses. So which one should you choose?
In terms of cloud infrastructure provisioning Terraform has a solid edge over Ansible due to its statefulness and error feedback mechanism.
Whereas Ansible shines in software provisioning over bare metal servers and cloud virtual machines.
A hybrid IaC configuration involving both Ansible and Terraform also works great if maintained properly. It will combine infrastructure provisioning power of Terraform with configuration management excellence of Ansible and provide a cutting edge IaC platform.
After using both technologies for over a year now in combination, I am more inclined towards Terraform first approach. If it is possible, do it in terraform. Ansible is still relevant as powerful configuration manager where non-containerized and on-premise solutions are present but with increase in microservice and serverless adoptation I think its Terraform’s time to really shine and overtake its competition.