Infrastructure as Code (IaC) allows you to manage and provision infrastructure through machine-readable definition files, rather than physical hardware configuration or interactive configuration tools.
Let’s see this in action. Imagine you need to spin up a simple web server on AWS.
provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0" # This AMI ID is for Amazon Linux 2 in us-east-1
instance_type = "t2.micro"
tags = {
Name = "HelloWorldInstance"
}
}
If you save this as main.tf and run terraform init, then terraform apply, Terraform will create an EC2 instance in your AWS account. It keeps track of the state of your infrastructure in a terraform.tfstate file, allowing it to plan changes and avoid drift.
Ansible is often used for configuration management after infrastructure is provisioned. However, it can also provision resources. Here’s an Ansible playbook to create an EC2 instance (this requires the amazon.aws collection to be installed):
---
- name: Provision EC2 instance
hosts: localhost
connection: local
gather_facts: no
tasks:
- name: Launch EC2 instance
amazon.aws.ec2_instance:
name: "HelloWorldInstanceAnsible"
key_name: "my-ec2-keypair" # Replace with your keypair name
instance_type: "t2.micro"
image_id: "ami-0c55b159cbfafe1f0" # Amazon Linux 2 in us-east-1
region: "us-east-1"
vpc_subnet_id: "subnet-xxxxxxxxxxxxxxxxx" # Replace with your subnet ID
security_group: "sg-xxxxxxxxxxxxxxxxx" # Replace with your security group ID
wait: yes
register: ec2_result
- name: Print instance IP
debug:
msg: "Instance {{ ec2_result.instance_id }} is running with IP {{ ec2_result.public_ip_address }}"
Running ansible-playbook your_playbook.yml would create the instance. Ansible uses an agentless, SSH-based approach for configuration management, but for cloud provisioning, it interacts directly with cloud provider APIs.
This is AWS’s native IaC service. A CloudFormation template defines your AWS resources.
{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"HelloWorldInstance": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId": "ami-0c55b159cbfafe1f0",
"InstanceType": "t2.micro",
"Tags": [
{
"Key": "Name",
"Value": "HelloWorldInstanceCFN"
}
]
}
}
}
}
You’d upload this JSON (or YAML) template to CloudFormation via the AWS console or CLI, and it would create a "stack." CloudFormation manages the lifecycle of these resources as a single unit.
The core problem IaC solves is the manual, error-prone, and time-consuming process of setting up and managing infrastructure. Instead of clicking through a console or running ad-hoc scripts, you declare the desired state of your infrastructure in code. This code can then be version-controlled, tested, and reused, bringing software development best practices to infrastructure management.
Terraform, by HashiCorp, is cloud-agnostic and uses its own declarative language (HCL). It excels at provisioning and managing the lifecycle of infrastructure across multiple cloud providers and services. Its strength lies in its state management, which allows for intelligent diffing and planning of changes.
Ansible, by Red Hat, is primarily a configuration management tool, known for its agentless nature and use of YAML playbooks. While it can provision infrastructure, it’s often used after a server is running to install software, configure services, and manage ongoing changes. Its procedural nature (tasks executed in order) makes it great for defining workflows.
CloudFormation is AWS’s proprietary IaC service. It’s deeply integrated with AWS services, allowing for complex deployments and automated rollbacks. Because it’s AWS-native, it often has the earliest support for new AWS features.
When you define a resource in Terraform, like aws_instance, Terraform doesn’t just tell AWS to create it; it records the specific attributes of that instance (like its ID, IP address, etc.) in its terraform.tfstate file. The next time you run terraform plan or terraform apply, Terraform compares the desired state in your .tf files with the actual state recorded in terraform.tfstate and also queries the cloud provider for the current state. It then calculates the minimum changes needed to make the real infrastructure match your code, which is far more efficient and safer than simply re-applying everything.
The most surprising thing about IaC tools, especially those like Terraform and CloudFormation, is their ability to perform destructive operations safely. When you declare a resource, the IaC tool registers it. If you later remove that resource’s declaration from your code and run terraform destroy or delete the CloudFormation stack, the tool will then explicitly delete the corresponding resource in your cloud environment. This level of controlled destruction is crucial for managing the full lifecycle of infrastructure, from creation to eventual decommissioning.
The next step after mastering IaC is understanding how to manage secrets securely within your infrastructure code.