Deploying a backend and frontend application on AWS using Terraform involves several steps, each integral to creating a robust and scalable environment. This guide will walk you through setting up your infrastructure on AWS with Terraform, focusing on creating resources and using modules for a clear, maintainable approach.
Prerequisites
- AWS Account: Ensure you have an AWS account with the necessary permissions.
- Terraform installed on your local machine
- AWS CLI installed: Install AWS CLI and configure it with your AWS credentials.
Initialize your Terraform Project
Create a new directory for your Terraform project and initialize it:
mkdir my-terraform-project
cd my-terraform-project
terraform init
Define AWS Provider
Create a file provider.tf
and define the AWS provider:
provider "aws" {
region = "us-east-1"
}
Set Up the VPC
Define a Virtual Private Cloud (VPC) in vpc.tf
:
resource "aws_vpc" "my_vpc" {
cidr_block = "10.0.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "my_vpc"
}
}
Create Subnets
Create your subnets.tf
file and create the public and private subnets inside it.
resource "aws_subnet" "public_subnet" {
vpc_id = aws_vpc.my_vpc.id
cidr_block = "10.0.1.0/24"
map_public_ip_on_launch = true
availability_zone = "us-east-1a"
tags = {
Name = "public_subnet"
}
}
resource "aws_subnet" "private_subnet" {
vpc_id = aws_vpc.my_vpc.id
cidr_block = "10.0.2.0/24"
availability_zone = "us-east-1b"
tags = {
Name = "private_subnet"
}
}
Create an Internet Gateway and Route Tables
Define an internet Gateway in igw.tf
:
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.my_vpc.id
tags = {
Name = "my_igw"
}
}
resource "aws_route_table" "public_route_table" {
vpc_id = aws_vpc.my_vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
tags = {
Name = "public_route_table"
}
}
Associate the route table with the public subnet in route_table.tf
:
resource "aws_route_table_association" "public" {
subnet_id = aws_subnet.public_subnet.id
route_table_id = aws_route_table.public_route_table.id
}
Configure Security Groups
Create a new file called security_groups.tf
to define your security groups:
resource "aws_security_group" "allow_web" {
name = "allow_web"
description = "Allow Web inbound traffic"
vpc_id = aws_vpc.my_vpc.id
ingress {
from_port = 80
to_port = 80
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"]
}
}
Deploy EC2 Instances
Create EC2 instances for your frontend and backend in ec2_instance.tf
:
resource "aws_instance" "frontend_instance" {
ami = "ami-123456"
instance_type = "t2.micro"
subnet_id = aws_subnet.public_subnet.id
security_groups = [aws_security_group.allow_web.id]
tags = {
Name = "frontend_instance"
}
}
resource "aws_instance" "backend_instance" {
ami = "ami-123456"
instance_type = "t2.micro"
subnet_id = aws_subnet.private_subnet.id
tags = {
Name = "backend_instance"
}
}
Apply the Configuration
Before you apply your configuration, you can compare the current state of your infrastructure with the desired state defined in your configuration files using terraform plan
This ensures that resources are created, updated, or deleted in the correct sequence.
Run the following command to apply your Terraform configuration:
terraform apply
Implementing Terraform Module
The Terraform module is a great practice for creating reusable, maintainable, and organized infrastructure code. We can modify the Terraform code above to include modules for our backend and frontend applications on AWS.
Define the Module Structure
Firstly we will structure our Terraform configuration to use modules. Here’s a basic directory structure:
my-terraform-project/
│
├── main.tf
├── variables.tf
├── outputs.tf
│
├── modules/
├── vpc/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
│
├── security/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
│
└── ec2/
├── main.tf
├── variables.tf
└── outputs.tf
Define Modules
In your modules/vpc/main.tf
define your VPC module configuration.
resource "aws_vpc" "my_vpc" {
cidr_block = var.cidr_block
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "my_vpc"
}
}
Define your Security Module (modules/security/main.tf)
resource "aws_security_group" "allow_web" {
name = "allow_web"
description = "Allow Web inbound traffic"
vpc_id = var.vpc_id
ingress {
from_port = 80
to_port = 80
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"]
}
}
Define your EC2 Module (modules/ec2/main.tf)
resource "aws_instance" "app_instance" {
ami = var.ami_id
instance_type = var.instance_type
subnet_id = var.subnet_id
security_groups = [var.security_group_id]
tags = {
Name = var.instance_name
}
}
Define the main configuration using Modules (`main.tf`)
module "vpc" {
source = "./modules/vpc"
cidr_block = "10.0.0.0/16"
}
module "security" {
source = "./modules/security"
vpc_id = module.vpc.my_vpc.id
}
module "frontend_instance" {
source = "./modules/ec2"
ami_id = "ami-123456"
instance_type = "t2.micro"
subnet_id = module.vpc.public_subnet.id
security_group_id = module.security.allow_web.id
instance_name = "frontend_instance"
}
module "backend_instance" {
source = "./modules/ec2"
ami_id = "ami-123456"
instance_type = "t2.micro"
subnet_id = module.vpc.private_subnet.id
security_group_id = module.security.allow_web.id
instance_name = "backend_instance"
}
Define Variables and Outputs
In each module, you need to define variables.tf
and outputs.tf
to manage inputs and outputs. This ensures that each module can be used flexibly in different environments.
Apply the Configuration
Run the commands to initialize Terraform and apply the configuration:
terraform init
terraform apply
Conclusion
Using modules in Terraform allows you to combine different parts of your AWS infrastructure, such as VPC, security settings, and EC2 instances, into reusable components. This approach enhances your organization, scalability, and maintainability of your Terraform code, particularly for complex deployments like a full-stack application.
Comments