Introduction
Infrastructure as Code (IaC) tools like Terraform have revolutionized how we manage cloud resources. By writing declarative configurations, you can automate the provisioning of infrastructure and reduce the risk of manual errors. In this tutorial, we will walk you through setting up a simple infrastructure on AWS, including a VPC, subnets, an EC2 instance, and a load balancer, all managed by Terraform.
Prerequisites
Before you begin, ensure you have the following:
- AWS Account: Access to AWS Management Console.
- Terraform Installed: Download and install Terraform from terraform.io.
- IAM User with Proper Permissions: A user with access to create VPC, EC2, S3, and other AWS resources.
- AWS CLI Installed and Configured: Set up using aws configure with your IAM credentials.
Step-1. Initialize Terraform Project
- Create a Working Directory
mkdir terraform-aws-setup
cd terraform-aws-setup - Add Terraform Configuration Files
- Create files:
- Initialize Terraform
terraform init
Step-2. Define AWS VPC and Subnets
The main.tf file includes:
Terraform Code:
resource “aws_vpc” “myvpc” {
cidr_block = var.cidr
}
resource “aws_subnet” “sub1” {
vpc_id = aws_vpc.myvpc.id
cidr_block = “10.0.0.0/24”
availability_zone = “us-east-1a”
map_public_ip_on_launch = true
}
resource “aws_subnet” “sub2” {
vpc_id = aws_vpc.myvpc.id
cidr_block = “10.0.1.0/24”
availability_zone = “us-east-1b”
map_public_ip_on_launch = true
}
Step-3. Set Up Networking
Terraform Code:
source “aws_internet_gateway” “igw” {
vpc_id = aws_vpc.myvpc.id
}
resource “aws_route_table” “RT” {
vpc_id = aws_vpc.myvpc.id
route {
cidr_block = “0.0.0.0/0”
gateway_id = aws_internet_gateway.igw.id
}
}
resource “aws_route_table_association” “rta1” {
subnet_id = aws_subnet.sub1.id
route_table_id = aws_route_table.RT.id
}
resource “aws_route_table_association” “rta2” {
subnet_id = aws_subnet.sub2.id
route_table_id = aws_route_table.RT.id
}
Step-4. Configure Security Groups
Allows access to HTTP (port 80) and SSH (port 22) from anywhere.
Terraform Code:
resource “aws_security_group” “webSg” {
name = “web”
vpc_id = aws_vpc.myvpc.id
ingress {
from_port = 80
to_port = 80
protocol = “tcp”
cidr_blocks = [“0.0.0.0/0”]
}
ingress {
from_port = 22
to_port = 22
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”]
}
}
Step-5. Add EC2 Instances
Creates two instances in separate subnets, each using a key pair for SSH access.
The user_data script sets up Apache with custom HTML content.
Terraform Code:
resource “aws_key_pair” “mykey” {
key_name = “my-terraform-key”
public_key = file(“~/.ssh/id_rsa.pub”)
}
resource “aws_instance” “webserver1” {
ami = “ami-0866a3c8686eaeeba”
instance_type = “t2.micro”
vpc_security_group_ids = [aws_security_group.webSg.id]
subnet_id = aws_subnet.sub1.id
user_data = base64encode(file(“userdata.sh”))
key_name = aws_key_pair.mykey.key_name
}
resource “aws_instance” “webserver2” {
ami = “ami-0866a3c8686eaeeba”
instance_type = “t2.micro”
vpc_security_group_ids = [aws_security_group.webSg.id]
subnet_id = aws_subnet.sub2.id
user_data = base64encode(file(“userdata1.sh”))
key_name = aws_key_pair.mykey.key_name
}
Step-6. Configure Load Balancer
Terraform Code:
resource “aws_lb” “myalb” {
name = “myalb”
internal = false
load_balancer_type = “application”
security_groups = [aws_security_group.webSg.id]
subnets = [aws_subnet.sub1.id, aws_subnet.sub2.id]
}
resource “aws_lb_target_group” “tg” {
name = “myTG”
port = 80
protocol = “HTTP”
vpc_id = aws_vpc.myvpc.id
}
resource “aws_lb_target_group_attachment” “attach1” {
target_group_arn = aws_lb_target_group.tg.arn
target_id = aws_instance.webserver1.id
port = 80
}
resource “aws_lb_target_group_attachment” “attach2” {
target_group_arn = aws_lb_target_group.tg.arn
target_id = aws_instance.webserver2.id
port = 80
}
resource “aws_lb_listener” “listener” {
load_balancer_arn = aws_lb.myalb.arn
port = 80
protocol = “HTTP”
default_action {
target_group_arn = aws_lb_target_group.tg.arn
type = “forward”
}
}
Step-7. Outputs
Retrieve the Load Balancer DNS name for accessing the deployed infrastructure.
Terraform Code:
output “loadbalancerdns” {
value = aws_lb.myalb.dns_name
}
Steps to Deploy
- Initialize Terraform:
terraform init - Validate the Configuration:
terraform validate - Apply the Configuration:
terraform applyConfirm with yes.
- Access the Application:
Clean Up
Destroy the infrastructure to avoid costs:
terraform destroy
Post-Deployment Best Practices
- Security:
- Restrict SSH (port 22) to trusted IPs.
- Enable HTTPS for the Load Balancer.
- Encrypt S3 bucket data and limit public access.
- Monitoring:
- Cost Optimization:
- Reliability:
- User Data:
- Fix default Apache page issue by overwriting /var/www/html/index.html.
- Automate instance patching in userdata.sh.
- Terraform State:
- Documentation:
- Create an architecture diagram and operational runbook.
These steps ensure your infrastructure is secure, cost-efficient, and reliable.
Conclusion
This setup provisions a robust AWS infrastructure using Terraform, including networking, compute instances, and a load balancer. It serves as a foundational template for deploying scalable applications.
Source: hashnode.com