Back to DevOps

Infrastructure as Code (Terraform)

Master Terraform and Infrastructure as Code. Learn to provision and manage cloud infrastructure through code.

Video Tutorial

Introduction to Infrastructure as Code

Infrastructure as Code (IaC) is the practice of managing and provisioning infrastructure through code instead of manual processes. Terraform is an open-source IaC tool that lets you define both cloud and on-prem resources in human-readable configuration files.

Examples:

# Benefits of IaC
- Version Control
- Automation
- Consistency
- Reusability
- Documentation

Key advantages of using Infrastructure as Code

Terraform Basics

Terraform uses HashiCorp Configuration Language (HCL) to describe infrastructure. The basic workflow is: Write → Plan → Apply.

Examples:

# Install Terraform (Linux)
wget https://releases.hashicorp.com/terraform/1.6.0/terraform_1.6.0_linux_amd64.zip
unzip terraform_1.6.0_linux_amd64.zip
sudo mv terraform /usr/local/bin/
terraform version

Install Terraform on your system

terraform init      # Initialize working directory
terraform plan      # Preview changes
terraform apply     # Apply changes
terraform destroy   # Destroy infrastructure

Essential Terraform commands

Terraform Configuration Files

Terraform configurations are written in .tf files. The main configuration file typically includes providers, resources, and variables.

Examples:

# main.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  
  tags = {
    Name = "WebServer"
  }
}

Basic Terraform configuration for AWS EC2 instance

Variables and Outputs

Variables make your Terraform configurations flexible and reusable. Outputs display information after applying changes.

Examples:

# variables.tf
variable "instance_type" {
  description = "EC2 instance type"
  type        = string
  default     = "t2.micro"
}

variable "region" {
  description = "AWS region"
  type        = string
  default     = "us-east-1"
}

Define input variables

# outputs.tf
output "instance_id" {
  description = "ID of the EC2 instance"
  value       = aws_instance.web.id
}

output "instance_public_ip" {
  description = "Public IP of instance"
  value       = aws_instance.web.public_ip
}

Define outputs to display after apply

# terraform.tfvars
instance_type = "t2.small"
region        = "us-west-2"

Set variable values in tfvars file

State Management

Terraform state tracks your infrastructure. It's crucial for Terraform to know what resources it manages.

Examples:

terraform state list           # List resources in state
terraform state show aws_instance.web  # Show resource details
terraform state pull           # Download remote state
terraform state rm aws_instance.web    # Remove resource from state

Manage Terraform state

# backend.tf - Remote state in S3
terraform {
  backend "s3" {
    bucket = "my-terraform-state"
    key    = "prod/terraform.tfstate"
    region = "us-east-1"
  }
}

Configure remote state storage in AWS S3

Modules

Modules are containers for multiple resources that are used together. They help organize and reuse code.

Examples:

# modules/vpc/main.tf
resource "aws_vpc" "main" {
  cidr_block = var.vpc_cidr
  
  tags = {
    Name = var.vpc_name
  }
}

resource "aws_subnet" "public" {
  vpc_id     = aws_vpc.main.id
  cidr_block = var.public_subnet_cidr
  
  tags = {
    Name = "${var.vpc_name}-public"
  }
}

Create a reusable VPC module

# main.tf - Using the module
module "vpc" {
  source = "./modules/vpc"
  
  vpc_name           = "production"
  vpc_cidr           = "10.0.0.0/16"
  public_subnet_cidr = "10.0.1.0/24"
}

Use the VPC module in your configuration

Data Sources

Data sources allow Terraform to fetch information from existing infrastructure or external sources.

Examples:

# Fetch latest Amazon Linux AMI
data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]
  
  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-*-x86_64-gp2"]
  }
}

resource "aws_instance" "web" {
  ami           = data.aws_ami.amazon_linux.id
  instance_type = "t2.micro"
}

Use data source to get latest AMI dynamically

Best Practices

Follow these best practices to write maintainable and secure Terraform code.

Examples:

# Use version constraints
terraform {
  required_version = ">= 1.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

Pin Terraform and provider versions

# Use workspaces for environments
terraform workspace new dev
terraform workspace new staging
terraform workspace new prod
terraform workspace select dev

Manage multiple environments with workspaces

# Format and validate
terraform fmt       # Format code
terraform validate  # Validate configuration
terraform plan      # Always plan before apply

Essential commands for code quality

Quick Reference

Core Commands

  • terraform init - Initialize
  • terraform plan - Preview
  • terraform apply - Deploy
  • terraform destroy - Remove

Best Practices

  • ✓ Use remote state
  • ✓ Version your code
  • ✓ Use modules
  • ✓ Always run plan first