Day-9-terraform
Automating AWS Infrastructure with Terraform: A Comprehensive Guide
TLDR: This blog post provides a detailed walkthrough of using Terraform to automate the creation of AWS infrastructure, including VPCs, subnets, EC2 instances, and load balancers. It emphasizes the importance of understanding AWS concepts and Terraform syntax, and offers practical tips for beginners.
In this blog post, we will explore how to use Terraform to automate the creation of infrastructure on AWS. This guide is based on Day 24 of the AWS DevOps Zero to Hero series, where we dive into a real-time Terraform project. If you have previously created infrastructure using the AWS console or CloudFormation templates, transitioning to Terraform will be straightforward, especially if you have a solid understanding of AWS fundamentals.
create IAM user , generate Access and Secrete keys → [this user should have all req access to resource] |
right side top last option → Name (drop)→ security credential |
Access key → create access key → |
use case : CLI → confirmation : checked → next → tag : TerrraformProject → create access key |
install cli → to connect with terraform |
aws —version |
aws configure |
AWS Access key Id : copy and paste from above |
AWS Secrete Access Key : copy and paste from above |
default region name |
default output format |
create folder and open it on vscode |
cd projects |
mkdir TerraformAC |
cd TerraformAC |
code . |
// providers.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "5.11.0"
}
}
}
provider "aws" {
# Configuration options
region = "us-east-1"
}
// -> terraform init
// main.tf
// 1 vpc
resource "aws_vpc" "myvpc" {
cidr_block = var.cidr // 10.0.0.0/16 -> 65,536 IP addresses -> (2^(32-16) = 65,536).
}
// 2 subnet -> vpc
resource "aws_subnet" "sub1" {
vpc_id = aws_vpc.myvpc.id // attach to above vpc
cidr_block = "10.0.0.0/24" // 256 IP addresses -> (2^(32-24) = 256).
availability_zone = "us-east-1a"
map_public_ip_on_launch = true // enable public ip
}
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
}
// 1 gateway -> vpc
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.myvpc.id
}
// 1 route table -> vpc , 2 route table association -> sub1 & sub2
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
}
// 1 security group -> vpc
resource "aws_security_group" "webSg" {
name = "web"
vpc_id = aws_vpc.myvpc.id
// inbound rules
ingress {
description = "HTTP from VPC"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "SSH"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
// outbound rules
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "Web-sg"
}
}
// 1 s3 bucket
resource "aws_s3_bucket" "example" {
bucket = "abhisheksterraform2023project"
}
// 2 instance -> sub1 & sub2
resource "aws_instance" "webserver1" {
ami = "ami-0261755bbcb8c4a84"
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")) // run the all script inside userdata.sh file
}
resource "aws_instance" "webserver2" {
ami = "ami-0261755bbcb8c4a84"
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")) // run the all script inside userdata1.sh file
}
// create 1 lb -> security_group,both subnet , 1 lb_target_group -> vpc , 2 lb_target_group_attachment , 1 lb_listener
// user req -> route 53 -> alb -> lb_listener -> target_group -> instance
resource "aws_lb" "myalb" {
name = "myalb"
internal = false // public
load_balancer_type = "application" // l7
security_groups = [aws_security_group.webSg.id]
subnets = [aws_subnet.sub1.id, aws_subnet.sub2.id]
tags = {
Name = "web"
}
}
resource "aws_lb_target_group" "tg" {
name = "myTG"
port = 80
protocol = "HTTP"
vpc_id = aws_vpc.myvpc.id
health_check {
path = "/" // home route -> traffic is transtered to healthy instance from 2
port = "traffic-port"
}
}
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"
}
}
output "loadbalancerdns" {
value = aws_lb.myalb.dns_name // give output to the terminal
}
terraform init |
terraform verify |
terraform plan |
terraform apply / terraform apply -auto-approve (to skip ‘yes‘ ) |
terraform fmt |
terraform show |
What is Terraform?
Terraform is an Infrastructure as Code (IaC) tool that allows you to define and provision data center infrastructure using a declarative configuration language. It enables you to manage your infrastructure through code, making it easier to automate and replicate environments.
Getting Started with Terraform
Before we begin, ensure you have the following prerequisites:
An AWS account
Terraform installed on your machine
Setting Up AWS Credentials
To use Terraform with AWS, you need to configure your AWS credentials. This involves creating an IAM user with the necessary permissions and generating access keys. Here’s how:
Log in to your AWS Management Console.
Navigate to the IAM service and create a new user with programmatic access.
Attach the necessary policies (e.g., AdministratorAccess) to the user.
Generate access keys and store them securely.
Once you have your access keys, configure them in your terminal using the AWS CLI:
aws configure
Initializing Terraform
Create a new directory for your Terraform project and navigate into it. Initialize Terraform by running:
tf init
This command prepares your working directory for other Terraform commands.
Complete Traffic Flow in Terraform Infrastructure
This Terraform configuration sets up a complete AWS infrastructure with VPC, subnets, security groups, EC2 instances, an S3 bucket, and an Application Load Balancer (ALB). Here's the step-by-step flow of how traffic moves through the infrastructure:
1. VPC Setup
A VPC (Virtual Private Cloud) is created with a CIDR block of 10.0.0.0/16.
This allows for 65,536 IP addresses within the VPC.
2. Subnet Configuration
Two public subnets are created inside the VPC:
Subnet 1:
10.0.0.0/24
(us-east-1a)Subnet 2:
10.0.1.0/24
(us-east-1b)
map_public_ip_on_launch = true
ensures instances launched in these subnets get a public IP.
3. Internet Gateway
An Internet Gateway (IGW) is created and attached to the VPC.
This allows internet access for instances in the public subnets.
4. Route Table & Routing
A Route Table (RT) is created and associated with both subnets.
A route is added:
0.0.0.0/0 → IGW
This enables instances to communicate out to the internet.
5. Security Group for Web Servers
A Security Group (SG) named
webSg
is created with:Inbound Rules:
HTTP (80) from Anywhere (
0.0.0.0/0
)SSH (22) from Anywhere (
0.0.0.0/0
)
Outbound Rules:
- Allow all outbound traffic (
0.0.0.0/0
).
- Allow all outbound traffic (
6. S3 Bucket
A simple S3 Bucket (
abhisheksterraform2023project
) is created.It can be used for storing logs, assets, or backups.
7. Web Servers (EC2 Instances)
Two EC2 instances (
t2.micro
) are created:Instance 1 in
subnet-1
Instance 2 in
subnet-2
User Data Scripts (
userdata.sh
anduserdata1.sh
) are used to configure the servers automatically.Security group
webSg
is attached to allow HTTP and SSH traffic.
8. Application Load Balancer (ALB)
A Public ALB (Application Load Balancer) is created with:
Security Group:
webSg
Attached to both subnets (
subnet-1
andsubnet-2
).Load Balancer Type:
Application
(Layer 7 - HTTP/HTTPS).
9. Target Group & Attachments
A Target Group (
tg
) is created for the ALB to distribute traffic.Health Checks are configured:
Path:
/
Only healthy instances receive traffic.
Two instances are attached to the target group.
10. ALB Listener
A listener on port 80 is created.
Requests hitting the ALB are forwarded to the target group (
tg
).
11. Traffic Flow Summary
User Request: A user accesses the website using
http://<LoadBalancerDNS>
.Route 53 (Optional): If a domain is configured, Route 53 routes the request to the ALB.
ALB: The ALB forwards the request to the target group.
Target Group: Based on health checks, the request is sent to either:
EC2 Instance 1 (Subnet 1)
EC2 Instance 2 (Subnet 2)
Web Server: The instance processes the request and responds with the required data (e.g., webpage, API response).
Response to User: The ALB forwards the instance's response to the user.
12. Output: Load Balancer DNS
The ALB DNS Name is output to the terminal:
output "loadbalancerdns" { value = aws_lb.myalb.dns_name }
Users can access the application using this DNS.
Complete Architecture
User Request → Route 53 (Optional) → Application Load Balancer (ALB)
→ Listener (80) → Target Group → Healthy EC2 Instance
→ Web Server Processes Request → Response Sent Back to User
This setup ensures high availability, scalability, and secure access to the application. 🚀
Conclusion
In this blog post, we covered how to use Terraform to automate the creation of AWS infrastructure, including VPCs, subnets, EC2 instances, and load balancers. Understanding the underlying AWS concepts is crucial for effectively using Terraform. With practice, you will find that Terraform simplifies the management of your infrastructure, making it easier to deploy and maintain applications in the cloud.
Don't forget to experiment with the code and try creating your own configurations. Happy coding!