🏗️ Terraform Infrastructure as Code
Learn how to manage cloud infrastructure using Terraform, the industry-leading IaC tool.
What is Terraform?
Terraform is an open-source infrastructure as code tool that lets you define and provision infrastructure using a declarative configuration language (HCL).
Installation
# macOS
brew install terraform
# Ubuntu/Debian
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform
# Verify installation
terraform versionBasic Workflow
# Initialize working directory
terraform init
# Preview changes
terraform plan
# Apply changes
terraform apply
# Destroy resources
terraform destroyAWS EC2 Example
Create a simple EC2 instance:
# main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.aws_region
}
# Variables
variable "aws_region" {
description = "AWS region"
default = "ap-southeast-1"
}
variable "instance_type" {
description = "EC2 instance type"
default = "t3.micro"
}
# Data source for latest Ubuntu AMI
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"] # Canonical
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
}
}
# EC2 Instance
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = var.instance_type
tags = {
Name = "WebServer"
Environment = "Development"
ManagedBy = "Terraform"
}
}
# Output
output "instance_public_ip" {
description = "Public IP of the EC2 instance"
value = aws_instance.web.public_ip
}VPC with Subnets
# vpc.tf
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "main-vpc"
}
}
resource "aws_subnet" "public" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)
availability_zone = data.aws_availability_zones.available.names[count.index]
map_public_ip_on_launch = true
tags = {
Name = "public-subnet-${count.index + 1}"
Type = "Public"
}
}
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = {
Name = "main-igw"
}
}
data "aws_availability_zones" "available" {
state = "available"
}State Management
Remote Backend (S3)
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "ap-southeast-1"
encrypt = true
dynamodb_table = "terraform-locks"
}
}Essential Commands
| Command | Description |
|---|---|
terraform init | Initialize directory |
terraform plan | Preview changes |
terraform apply | Apply changes |
terraform destroy | Destroy resources |
terraform fmt | Format code |
terraform validate | Validate config |
terraform output | Show outputs |
terraform state list | List state resources |
Best Practices
- Use modules to organize and reuse code
- Store state remotely with locking
- Use variables for flexibility
- Tag all resources for cost tracking
- Use workspaces for environments
- Implement CI/CD for IaC
⚠️ Warning: Never commit
.tfstatefiles or.tfvarswith secrets to version control!
Related: AWS CloudFormation