What is Infrastructure as Code?
Infrastructure as Code (IaC) lets you manage your cloud resources with configuration files instead of clicking around a web console. It is repeatable, versionable, and less error prone. Terraform by HashiCorp is one of the most popular IaC tools because it is cloud agnostic and uses a declarative language called HCL (HashiCorp Configuration Language).
Installing Terraform
Terraform is a single binary. Download the appropriate package for your OS from the official site, unzip it, and ensure the terraform binary is in your PATH. Verify with:
terraform version
Your First Terraform Configuration
Create a directory for your project and a file named main.tf. Here is a minimal example that provisions an AWS EC2 instance:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
tags = {
Name = "ExampleInstance"
}
}
This configuration tells Terraform to use the AWS provider, set the region, and create an EC2 instance with a specific AMI and instance type.
Core Terraform Workflow
Terraform follows a simple three step workflow:
- Init - Initialize the working directory and download the required providers.
terraform init
- Plan - Preview the changes Terraform will make without actually applying them.
terraform plan
- Apply - Execute the changes to create or update resources.
terraform apply
After running apply, Terraform will prompt you to confirm. Type yes to proceed. When you are done, you can destroy the resources with:
terraform destroy
State Management
Terraform keeps track of the resources it manages in a state file (by default terraform.tfstate). This file is crucial; never edit it manually. For team use, store state remotely (e.g., in an S3 bucket with DynamoDB locking) to avoid conflicts.
Variables and Outputs
Hardcoding values is bad practice. Use variables to make your configuration reusable:
variable "instance_name" {
description = "Name tag for the instance"
type = string
default = "MyInstance"
}
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
tags = {
Name = var.instance_name
}
}
And outputs to display useful information:
output "instance_ip" {
value = aws_instance.example.public_ip
}
Pass variable values via a terraform.tfvars file or the -var flag.
Modules for Reusability
Modules are self contained packages of Terraform configurations. You can call a module from a registry or your own local directory. For example, to use the VPC module from the Terraform Registry:
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
name = "my-vpc"
cidr = "10.0.0.0/16"
azs = ["us-east-1a", "us-east-1b"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24"]
enable_nat_gateway = true
tags = {
Terraform = "true"
Environment = "dev"
}
}
Best Practices
- Use version control for your Terraform files.
- Format your code with
terraform fmt. - Validate configurations with
terraform validate. - Keep secrets out of code; use environment variables or a secrets manager.
- Use remote state with locking for team collaboration.
Conclusion
Terraform gives you a powerful, declarative way to manage infrastructure across multiple cloud providers. Start small, learn the workflow, and gradually adopt modules and remote state. The time you invest in IaC pays off in consistency, auditability, and speed.
Top comments (0)