Introduction
Infrastructure as Code (IaC) has transformed how we manage cloud infrastructure. Instead of manually clicking through console interfaces, you define your infrastructure in code, version it, review it, and deploy it automatically.
This guide covers the major IaC tools and best practices for managing production infrastructure.
What is Infrastructure as Code?
IaC Principles
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ INFRASTRUCTURE AS CODE PRINCIPLES โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Core Principles: โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ Define infrastructure in code โ โ
โ โ โ Version control (Git) for all configurations โ โ
โ โ โ Automated testing and validation โ โ
โ โ โ Peer review before changes โ โ
โ โ โ Automated deployment pipelines โ โ
โ โ โ Idempotent (same result every time) โ โ
โ โ โ Document everything (code is documentation) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Benefits: โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ Consistency across environments โ โ
โ โ โ Version history and rollback โ โ
โ โ โ Faster provisioning โ โ
โ โ โ Reduced human errors โ โ
โ โ โ Self-documenting infrastructure โ โ
โ โ โ Enables GitOps workflows โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
IaC Tool Categories
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ IAC TOOL CATEGORIES โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ IMPERATIVE Tools โ โ
โ โ Execute commands in sequence โ โ
โ โ โข AWS CLI โ โ
โ โ โข Azure CLI โ โ
โ โ โข gcloud CLI โ โ
โ โ โข Pulumi (programmatic) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ DECLARATIVE Tools โ โ
โ โ Define desired state, tool figures out how โ โ
โ โ โข Terraform (HCL) โ โ
โ โ โข CloudFormation (JSON/YAML) โ โ
โ โ โข Kubernetes (YAML) โ โ
โ โ โข Pulumi (declarative mode) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ CONFIGURATION Management โ โ
โ โ Configure running systems โ โ
โ โ โข Ansible โ โ
โ โ โข Chef โ โ
โ โ โข Puppet โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Terraform Deep Dive
Basic Terraform Workflow
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ TERRAFORM WORKFLOW โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โ
โ โ Write โโโโโบโ Plan โโโโโบโ Apply โ โ
โ โ (.tf) โ โ (preview) โ โ (deploy) โ โ
โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โ
โ โ โ โ โ
โ โ โ โ โ
โ โผ โผ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ .tfstate file โ โ
โ โ โข Tracks created resources โ โ
โ โ โข Located locally or in remote backend โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Commands: โ
โ โข terraform init - Initialize working directory โ
โ โข terraform validate - Validate syntax โ
โ โข terraform plan - Preview changes โ
โ โข terraform apply - Apply changes โ
โ โข terraform destroy - Tear down resources โ
โ โข terraform state - Manage state โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Terraform Configuration
# main.tf - Basic Terraform configuration
# Configure the AWS provider
provider "aws" {
region = "us-west-2"
# Use multiple profiles for different environments
alias = "main"
default_tags {
tags = {
Environment = "production"
ManagedBy = "Terraform"
}
}
}
# Terraform settings
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
# Remote state storage (recommended)
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "us-west-2"
encrypt = true
dynamodb_table = "terraform-locks"
}
}
# Variables
variable "environment" {
description = "Environment name"
type = string
default = "production"
}
variable "instance_type" {
description = "EC2 instance type"
type = string
default = "t3.micro"
}
variable "vpc_cidr" {
description = "CIDR block for VPC"
type = string
default = "10.0.0.0/16"
}
# Create a VPC
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "${var.environment}-vpc"
}
}
# Create subnets
resource "aws_subnet" "public" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index)
availability_zone = ["us-west-2a", "us-west-2b"][count.index]
tags = {
Name = "${var.environment}-public-subnet-${count.index + 1}"
}
}
# Internet Gateway
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = {
Name = "${var.environment}-igw"
}
}
# Security Group
resource "aws_security_group" "web" {
name = "${var.environment}-web-sg"
description = "Security group for web servers"
vpc_id = aws_vpc.main.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "${var.environment}-web-sg"
}
}
# EC2 Instance
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0" # Amazon Linux 2
instance_type = var.instance_type
subnet_id = aws_subnet.public[0].id
vpc_security_group_ids = [aws_security_group.web.id]
tags = {
Name = "${var.environment}-web-server"
}
}
# Outputs
output "vpc_id" {
description = "ID of the VPC"
value = aws_vpc.main.id
}
output "public_ip" {
description = "Public IP of the web server"
value = aws_instance.web.public_ip
}
Terraform Modules
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ TERRAFORM MODULES โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Module Structure: โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ my-module/ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ main.tf (module logic) โ โ โ
โ โ โ resource "aws_instance" "this" { ... } โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ variables.tf (inputs) โ โ โ
โ โ โ variable "instance_type" { ... } โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ outputs.tf (outputs) โ โ โ
โ โ โ output "instance_id" { ... } โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Using a Module: โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ module "web_server" { โ โ
โ โ source = "./modules/ec2" โ โ
โ โ โ โ
โ โ instance_type = "t3.micro" โ โ
โ โ ami = "ami-xxx" โ โ
โ โ environment = "production" โ โ
โ โ } โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# modules/vpc/main.tf
variable "vpc_cidr" {
description = "CIDR block for VPC"
type = string
}
variable "environment" {
description = "Environment name"
type = string
}
variable "availability_zones" {
description = "List of availability zones"
type = list(string)
default = ["us-west-2a", "us-west-2b"]
}
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "${var.environment}-vpc"
}
}
resource "aws_subnet" "public" {
count = length(var.availability_zones)
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index)
availability_zone = var.availability_zones[count.index]
tags = {
Name = "${var.environment}-public-${count.index + 1}"
}
}
output "vpc_id" {
value = aws_vpc.main.id
}
output "subnet_ids" {
value = aws_subnet.public[*].id
}
---
# main.tf - Using the module
module "vpc" {
source = "./modules/vpc"
vpc_cidr = "10.0.0.0/16"
environment = "production"
availability_zones = ["us-west-2a", "us-west-2b"]
}
AWS CloudFormation
CloudFormation Template
# cloudformation-template.yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: "VPC with public and private subnets"
Parameters:
EnvironmentName:
Type: String
Default: production
Description: Environment name
VPCCidr:
Type: String
Default: 10.0.0.0/16
Description: CIDR block for VPC
Resources:
# VPC
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VPCCidr
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-vpc
# Internet Gateway
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-igw
InternetGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
# Public Subnet
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: !Select [0, !CidrSplit [!Ref VPCCidr, 8]]
AvailabilityZone: !Select [0, !GetAZs '']
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-public-1
# Private Subnet
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: !Select [1, !CidrSplit [!Ref VPCCidr, 8]]
AvailabilityZone: !Select [0, !GetAZs '']
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-private-1
# Route Table
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-public-rt
PublicRoute:
Type: AWS::EC2::Route
DependsOn: InternetGatewayAttachment
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
SubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1
RouteTableId: !Ref PublicRouteTable
Outputs:
VPCId:
Description: ID of the VPC
Value: !Ref VPC
Export:
Name: !Sub ${AWS::StackName}-VPCID
PublicSubnet1Id:
Description: ID of the public subnet
Value: !Ref PublicSubnet1
Export:
Name: !Sub ${AWS::StackName}-PublicSubnet1
Pulumi
Pulumi Program
// Pulumi - TypeScript program
import * as aws from "@pulumi/aws";
import * as pulumi from "@pulumi/pulumi";
// Get config
const config = new pulumi.Config();
const environment = config.require("environment");
const instanceType = config.get("instanceType") || "t3.micro";
// Create a VPC
const vpc = new aws.ec2.Vpc(`${environment}-vpc`, {
cidrBlock: "10.0.0.0/16",
enableDnsHostnames: true,
enableDnsSupport: true,
tags: {
Name: `${environment}-vpc`,
Environment: environment,
},
});
// Create subnets
const publicSubnet = new aws.ec2.Subnet(`${environment}-public-subnet`, {
vpcId: vpc.id,
cidrBlock: "10.0.1.0/24",
availabilityZone: "us-west-2a",
mapPublicIpOnLaunch: true,
tags: {
Name: `${environment}-public-subnet`,
Environment: environment,
},
});
const privateSubnet = new aws.ec2.Subnet(`${environment}-private-subnet`, {
vpcId: vpc.id,
cidrBlock: "10.0.2.0/24",
availabilityZone: "us-west-2a",
tags: {
Name: `${environment}-private-subnet`,
Environment: environment,
},
});
// Create security group
const webSg = new aws.ec2.SecurityGroup(`${environment}-web-sg`, {
description: "Security group for web servers",
vpcId: vpc.id,
ingress: [
{
protocol: "tcp",
fromPort: 80,
toPort: 80,
cidrBlocks: ["0.0.0.0/0"],
},
{
protocol: "tcp",
fromPort: 443,
toPort: 443,
cidrBlocks: ["0.0.0.0/0"],
},
],
egress: [
{
protocol: "-1",
fromPort: 0,
toPort: 0,
cidrBlocks: ["0.0.0.0/0"],
},
],
tags: {
Name: `${environment}-web-sg`,
Environment: environment,
},
});
// Create EC2 instance
const webServer = new aws.ec2.Instance(`${environment}-web`, {
ami: "ami-0c55b159cbfafe1f0",
instanceType: instanceType,
subnetId: publicSubnet.id,
vpcSecurityGroupIds: [webSg.id],
tags: {
Name: `${environment}-web-server`,
Environment: environment,
},
});
// Export outputs
export const vpcId = vpc.id;
export const publicIp = webServer.publicIp;
export const instanceId = webServer.id;
State Management
Remote State
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ TERRAFORM STATE MANAGEMENT โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Local State (Not Recommended for Teams): โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ terraform.tfstate stored locally โ โ
โ โ โข Doesn't work with team โ โ
โ โ โข No locking - concurrent changes cause conflicts โ โ
โ โ โข Lost if workstation fails โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Remote State (Recommended): โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Backend Types: โ โ
โ โ โข S3 + DynamoDB (AWS) - Most common โ โ
โ โ โข Azure Blob Storage โ โ
โ โ โข Google Cloud Storage โ โ
โ โ โข Terraform Cloud/Enterprise โ โ
โ โ โข Consul โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Key Benefits: โ
โ โ Shared among team members โ
โ โ State locking - prevents conflicts โ
โ โ Encryption at rest and in transit โ
โ โ Audit trail โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
State Locking
# S3 Backend with DynamoDB locking
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "us-west-2"
encrypt = true
dynamodb_table = "terraform-locks" # Required for locking
}
}
# Create DynamoDB table for locking
resource "aws_dynamodb_table" "terraform_locks" {
name = "terraform-locks"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
CI/CD for IaC
GitHub Actions for Terraform
# .github/workflows/terraform.yml
name: Terraform
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
TF_VERSION: "1.5.0"
AWS_REGION: "us-west-2"
jobs:
terraform:
name: Terraform
runs-on: ubuntu-latest
environment: production
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: ${{ env.TF_VERSION }}
cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }}
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Terraform Init
run: terraform init
working-directory: ./terraform
- name: Terraform Validate
run: terraform validate
working-directory: ./terraform
- name: Terraform Plan
if: github.event_name == 'pull_request'
run: terraform plan -no-color
working-directory: ./terraform
continue-on-error: true
- name: Terraform Apply
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
run: terraform apply -auto-approve
working-directory: ./terraform
Best Practices
IaC Security Best Practices
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ IAC SECURITY BEST PRACTICES โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Secret Management โ โ
โ โ โข NEVER commit secrets in code โ โ
โ โ โข Use secret management services โ โ
โ โ โข AWS: Secrets Manager, Parameter Store โ โ
โ โ โข Azure: Key Vault โ โ
โ โ โข GCP: Secret Manager โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Access Control โ โ
โ โ โข Use IAM roles, not access keys โ โ
โ โ โข Principle of least privilege โ โ
โ โ โข Enable MFA for console access โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ State Security โ โ
โ โ โข Use remote state with encryption โ โ
โ โ โข Enable state versioning โ โ
โ โ โข Restrict access to state files โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Code Review โ โ
โ โ โข Require PRs for all changes โ โ
โ โ โข Peer review infrastructure changes โ โ
โ โ โข Run plan before apply โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Testing โ โ
โ โ โข Validate syntax before apply โ โ
โ โ โข Use policy as code (OPA, Sentinel) โ โ
โ โ โข Test in non-production first โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Tool Comparison
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ IAC TOOL COMPARISON โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโโโฌโโโโโโโโโโโโฌโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Feature โ Terraform โCloudFormationโ Pulumi โ โ
โ โโโโโโโโโโโโโผโโโโโโโโโโโโผโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโค โ
โ โ Language โ HCL โ YAML/JSON โ TS/Py/Go/C# โ โ
โ โโโโโโโโโโโโโผโโโโโโโโโโโโผโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโค โ
โ โ Provider โ Multi-cloudโ AWS only โ Multi-cloud โ โ
โ โโโโโโโโโโโโโผโโโโโโโโโโโโผโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโค โ
โ โ State โ File/Remotโ JSON โ File/Remote โ โ
โ โโโโโโโโโโโโโผโโโโโโโโโโโโผโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโค โ
โ โ Learning โ Medium โ Low โ Low (use lang) โ โ
โ โโโโโโโโโโโโโผโโโโโโโโโโโโผโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโค โ
โ โ Community โ Large โ AWS-focused โ Growing โ โ
โ โโโโโโโโโโโโโผโโโโโโโโโโโโผโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโค โ
โ โ Testing โ Good โ Limited โ Excellent โ โ
โ โโโโโโโโโโโโโดโโโโโโโโโโโโดโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ When to use what: โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Terraform: Multi-cloud, large community, mature โ โ
โ โ CloudFormation: AWS-only, deep AWS integration โ โ
โ โ Pulumi: Teams familiar with programming languages โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Conclusion
Infrastructure as Code is essential for modern cloud deployment. Key takeaways:
- Start with Terraform - Most widely adopted, large community
- Use remote state - S3 for AWS, with DynamoDB locking
- Modularize - Create reusable modules for common patterns
- Automate - CI/CD pipelines for all infrastructure changes
- Secure - Never commit secrets, use IAM roles, peer review
IaC transforms infrastructure management from manual, error-prone processes to automated, version-controlled, and repeatable workflows.
Comments