Comparing CloudFormation, Terraform and Ansible - Simple example
Whenever someone asks me what tools do you use to provision your infrastructure within AWS - the answer is it can be done with a variety of tools - but people usually use one of the following three
The next question that comes up of course - is which one is easier/better to use? The answer of course (as always..) is - “It Depends”. There are really good reasons to use each and everyone of the tools. This could be ease of use, support, extensibility, flexibility, community support (or lack thereof).
I have worked with all three tools, and each of them have their ups and their downs. There are periods that I prefer Ansible, other days that Terraform and sometimes CloudFormation is the only way to get things done.
I wanted to compare all three in a set of scenarios - from the really simple to moderate - to complicated. Firstly - to see how this can be accomplished in each of the tools,evaluating complexity, time to completion and anything else that came up along the way.
Let’s start by diving straight into the first example.
I want to create a VPC. A plain simple VPC, nothing else. No Network, no NAT gateways, routes, subnets, as simple as can be. Essentially this is a simple AWS API call which would be:
aws ec2 create-vpc --cidr-block 192.168.90.0/24
(The code for all of these scenarios is located here - https://github.com/maishsk/automation-standoff/tree/master/simple)
First lets have a look at CloudFormation
Description:
This template deploys a VPC.
Parameters:
EnvironmentName:
Description: An environment name that will be prefixed to resource names
Type: String
Default: "testvpc"
VpcCIDR:
Description: Please enter the IP range (CIDR notation) for this VPC
Type: String
Default: 192.168.90.0/24
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VpcCIDR
EnableDnsSupport: true
Tags:
- Key: Name
Value: "testvpc"
Outputs:
VPC:
Description: A reference to the created VPC
Value: !Ref VPC
Looks pretty simple. I used the native resources in CloudFormation, and set defaults for the name and the CIDR block.
Lets look at Ansible. There is a built-in module for this ec2_vpc_net.
- name: VPC creation playbook
hosts: localhost
connection: local
gather_facts: no
vars_files:
- vars/vpc_vars.yml
tasks:
- name: Create a VPC
ec2_vpc_net:
region: "{{ region }}"
name: "{{ project_name }}"
cidr_block: "{{ cidr_block }}"
state: present
register: vpc
The only difference here is that the variables are split into a separate file (as per Ansible best practices
Last but not least - Terraform.
resource "aws_vpc" "testvpc" {
cidr_block = "${var.vpc_cidr}"
enable_dns_hostnames = true
tags {
Name = "${var.project_name}"
}
}
Here the provider is split out into a separate file and the variables into another file (Terraform best practices)
First Score - # lines of Code (Including all nested files)
Ansible - 19
CloudFormation - 28
Terraform - 29
Second Score - Easy of deployment / teardown.
I will not give a numerical score here - just to mention a basic difference between the three options.
Each of the tools use a simple command line syntax to deploy
-
CloudFormation
aws cloudformation create-stack --stack-name testvpc --template-body [file://vpc_cloudformation_template.yml](file://vpc_cloudformation_template.yml)
-
Ansible
ansible-playbook create-vpc.yml
-
Terraform
terraform apply -auto-approve
The teardown is a bit different
-
CloudFormation stores the information as a stack - and all you need to do to remove the stack and all of its resources is to run a simple command of:
aws cloudformation delete-stack --stack-name <STACKNAME>
-
Ansible - you will need to create an additional playbook for tearing down the environment - it does not store the state locally. This is a drawback
ansible-playbook remove-vpc.yml
-
Terraform - stores the state of the deployment - so a simple run will destroy all the resources
terraform destroy -auto-approve
The last one I wanted to address was the time it took to deploy/tear down the resources for each tool - and I think that the differences here are quite interesting.
I ran a for.. loop through 3 iterations to bring up the VPC and tear it down and timed the duration for each run.
You can find the full output of the runs below:
Results
CloudFormation
create: 31.987s destroy: 31.879s
Ansible
create: 8.144s destroy: 2.554s
Terraform
create: 17.452s destroy: 12.652s
So to summarize - it seems that Ansible is the fastest one of them all - there are a number of reasons why this is the case (and I will go into more detail into this in a future post)
This is by no means a recommendation to use one tool or the other - or to say that one tool is better than the other - just a simple side by si*de comparison between the three options that I have used in the past.
Next blog post will go into a slightly more complicated scenario.
Thoughts and comments are always welcome, please feel free to leave them below.