How to use Terraform to provision two EC2 instances and a load balancer on AWS

I am a Salafiyyah who has a passion for creative and technological innovations. Currently, I am focused on DevOps and project management. With my skills and experience, I am committed to delivering quality results in every project that I work on.
Introduction
In this tutorial, we will create an AWS Load Balancer with Terraform, and distribute the server display as 50-50 on the load balancer. We will provision two EC2 instances - one with NGINX and another with Apache web servers - and attach them to the Load Balancer.

Prerequisites
To follow along with this tutorial, you should have:
An AWS account
The AWS CLI installed on your local machine
Terraform installed on your local machine
Key Terms
Here are some definitions of key terms used in the article for absolute beginners:
AWS: Amazon Web Services, a cloud computing platform that provides a wide range of services for building and deploying applications and services in the cloud.
Load Balancer: A device or service that distributes incoming network traffic across multiple servers to ensure that no single server is overloaded, improving the overall reliability and scalability of a service.
Terraform: An open-source infrastructure as code (IaC) tool that allows developers to define and manage infrastructure in a declarative manner, using a high-level configuration language called HashiCorp Configuration Language (HCL).
EC2: Elastic Compute Cloud, a web service that provides resizable compute capacity in the cloud, designed to make web-scale cloud computing easier for developers.
NGINX: A popular open-source web server and reverse proxy server that is widely used for serving high-traffic websites and applications.
Apache: A popular open-source web server software that is widely used for serving websites and applications.
Step 1: Create a key pair
Before creating an EC2 instance, we need to create a key pair to access it. To create a key pair, follow these steps:
Open the AWS Management Console and navigate to the EC2 service.
Click on the "Key Pairs" link in the left navigation menu.
Click on the "Create Key Pair" button.
Enter a name for the key pair and click "Create."
Save the downloaded key pair file securely as you will need it to SSH into the EC2 instance.
Step 2: Configure the AWS CLI
To configure the AWS CLI, follow these steps:
Open a terminal or command prompt on your local machine.
Run the command
aws configure.Enter your AWS access key ID and secret access key.
Enter the region you want to use for this tutorial (e.g., "us-east-1").
Enter the output format you prefer (e.g., "json").
Step 3: Create a new directory and initialize Terraform
Create a new directory and three files inside the directory; main.tf, variable.tf, and terraform.tfvars by running the following commands:
$ mkdir terraform-load-balancer
$ cd terraform-load-balancer
$ touch main.tf
$ touch variable.tf
$ touch terraform.tfvars
In the Terraform configuration, we define variables to make our code more flexible and reusable. Variables can be used to determine values that may change depending on the environment or other factors.
In our project, there are two variables defined: key_name and region. These variables can be set to different values depending on the environment you are working in.
You can set the value of variables in several ways, including through environment variables, command line arguments, or a tfvars file. A tfvars file is a file that contains variable values, and it has a .tfvars or .tfvars.json extension.
For example, if you have a variables.tf file that defines a variable my_variable, you can set its value in a terraform.tfvars file which we will see example below.
Step 4: Create a Terraform configuration file
Next, we will create a Terraform configuration file to provision an EC2 instance with a web server and an ALB. Open the file main.tf and paste the following code into it:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~>4.0"
}
}
backend "s3" {
key = "aws/terraform1/terraform.tfstate"
region = "us-east-1"
}
}
provider "aws" {
profile = "default"
region = "us-east-1"
}
# Provision the ec2 instance for NGINX
resource "aws_instance" "nginx-server" {
ami = "ami-0aa2b7722dc1b5612"
instance_type = "t2.micro"
key_name = var.key_name
vpc_security_group_ids = [aws_security_group.general-sg.id]
user_data = <<-EOF
#!/bin/bash
sudo apt-get update
sudo apt-get install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx
EOF
tags = {
"Name" = "nginx-server"
}
}
# Provision the ec2 instance for APACHE
resource "aws_instance" "apache-server" {
ami = "ami-0aa2b7722dc1b5612"
instance_type = "t2.micro"
key_name = var.key_name
vpc_security_group_ids = [aws_security_group.general-sg.id]
user_data = <<-EOF
#!/bin/bash
sudo apt-get update
sudo apt-get install apache2 -y
sudo systemctl start apache2
sudo systemctl enable apache2
EOF
tags = {
"Name" = "apache-server"
}
}
# Provision a load balancer
resource "aws_lb" "terraform-one" {
name = "terraform-one-lb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.general-sg.id]
subnets = ["subnet-031b178c271230523", "subnet-0477dfc2s6480ae573", "subnet-0d02saie187990de6"]
}
# Provision a target group
resource "aws_lb_target_group" "terraform-one" {
name = "terraform-one-tg"
port = 80
protocol = "HTTP"
target_type = "instance"
vpc_id = "vpc-0840aafd81290290s"
health_check {
path = "/"
}
}
# Provision a listener
resource "aws_lb_listener" "terraform-one" {
load_balancer_arn = aws_lb.terraform-one.arn
port = 80
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.terraform-one.arn
}
}
# Provision the target group attachments
resource "aws_lb_target_group_attachment" "nginx-server" {
target_group_arn = aws_lb_target_group.terraform-one.arn
target_id = aws_instance.nginx-server.id
port = 80
}
resource "aws_lb_target_group_attachment" "apache-server" {
target_group_arn = aws_lb_target_group.terraform-one.arn
target_id = aws_instance.apache-server.id
port = 80
}
# Provision the security group
resource "aws_security_group" "general-sg" {
egress = [{
cidr_blocks = ["0.0.0.0/0"]
description = ""
from_port = 0
ipv6_cidr_blocks = []
prefix_list_ids = []
protocol = "-1"
security_groups = []
self = false
to_port = 0
}]
ingress = [{
cidr_blocks = ["0.0.0.0/0"]
description = "allow ssh"
from_port = 22
ipv6_cidr_blocks = []
prefix_list_ids = []
protocol = "tcp"
security_groups = []
self = false
to_port = 22
},
{
cidr_blocks = ["0.0.0.0/0"]
description = "allow http"
from_port = 80
ipv6_cidr_blocks = []
prefix_list_ids = []
protocol = "tcp"
security_groups = []
self = false
to_port = 80
}]
}
Next, paste the following code in the variable.tf file:
variable "region" {
description = "terraform one region"
type = string
}
variable "key_name" {
description = "key name"
type = string
}
Next, paste the following code in the terraform.tfvars file:
region = "us-east-1"
key_name = "ec2-server"
Note: Replace the values of region, ami, instance_type, key_name, subnets, security_groups, and vpc_id with your own values.
Now, let's move on to the explanations of the code:
Firstly, we start with the terraform block, where we specify the provider and backend configurations. The required_providers block specifies the provider and version we are using, in this case, we are using the AWS provider from HashiCorp with version ~>4.0. The backend block specifies that we are using an S3 bucket as our backend to store the state file of our Terraform infrastructure. We specify the key, and region where we want to store the state file.
Next, we have the provider block that specifies the AWS credentials and region we want to use. In this case, we are using the default profile and us-east-1 region.
Then, we have two aws_instance resources, nginx-server and apache-server, that provision two EC2 instances. Both instances have the same ami and instance_type, and are associated with the key_pair and aws_security_group resources we created earlier and will define later respectively. The user_data block is used to specify the commands that will be run when the instance starts. In this case, we are installing and starting different web servers on each instance - NGINX on the NGINX server and Apache on the Apache server.
After that, we have an aws_lb resource that provisions an Application Load Balancer. We specify the name, internal, load_balancer_type, security_groups, and subnets for the load balancer.
Then, we define an aws_lb_target_group resource that specifies the target group to which the instances will be attached. We set the name, port, protocol, target_type, vpc_id, and health_check path for the target group.
Next, we define an aws_lb_listener resource that specifies the listener that the load balancer will use. We set the load_balancer_arn, port, and protocol, and define a default action to forward traffic to the target group we defined earlier.
After that, we define two aws_lb_target_group_attachment resources to attach the instances to the target group. We specify the target_group_arn, target_id, and port for each attachment.
Finally, we define an aws_security_group resource that specifies the ingress and egress rules for the security group associated with the instances. In this case, we allow inbound traffic on port 22 for SSH and port 80 for HTTP, and allow outbound traffic to any destination.
Overall, this Terraform configuration provisions two EC2 instances running different web servers and an Application Load Balancer that distributes traffic between the instances. and up next is how to successfully deploy and destroy the infrastructure respectively.
Initializing the Terraform Backend
Before we can use Terraform to manage our infrastructure, we need to initialize the backend. This is done with the terraform init command. The backend is where Terraform stores its state file, which tracks the resources it has created. In our case, we are using an S3 bucket as our backend.
To initialize the backend, navigate to the directory containing your Terraform files and run the following command:
$ terraform init -backend-config="bucket=<your-bucket-name>"
This command initializes the backend and sets the bucket name for the state file. You will need to replace <your-bucket-name> with the name of the S3 bucket you created.
Creating an Execution Plan
Once we have initialized the backend, we can use the terraform plan command to create an execution plan. This plan shows us what Terraform will do when we apply our changes.
To create an execution plan, run the following command:
$ terraform plan --var-file=terraform.tfvars
This command tells Terraform to use the variables defined in the terraform.tfvars file. This file should contain the values for all of the variables we defined earlier.
The terraform plan command will analyze our Terraform code and create a plan of what resources will be created or modified. It will also show us any errors or warnings in our code.
Applying Changes
After we have reviewed the execution plan and made any necessary changes, we can apply our changes with the terraform apply command. This command will create or modify the resources specified in our Terraform code.
To apply our changes, run the following command:
$ terraform apply -var-file=terraform.tfvars
This command tells Terraform to use the variables defined in the terraform.tfvars file. It will prompt us to confirm that we want to apply the changes before proceeding. which we can also escape with the -auto-approve flag.
Destroying Resources
If we want to delete the resources we created with Terraform, we can use the terraform destroy command. This command will remove all of the resources specified in our Terraform code.
To destroy our resources, run the following command:
$ terraform destroy -var-file=terraform.tfvars
This command tells Terraform to use the variables defined in the terraform.tfvars file. It will also prompt us to confirm that we want to destroy the resources before proceeding.
Conclusion
In conclusion, Terraform provides a simple, declarative approach to infrastructure management, allowing you to automate the provisioning, configuration, and deployment of resources across multiple cloud providers. In this tutorial, we have seen how to use Terraform to create an AWS Load Balancer and distribute the server display as 50-50 on the load balancer, provision two EC2 instances with different web servers, and attach them to the Load Balancer. We have covered the basics of Terraform, including how to create and use variable and tfvars files, how to initialize a Terraform project, how to create a plan and apply it, and how to destroy resources when they are no longer needed. With this knowledge, you can now start building more complex infrastructure as code using Terraform.
Thank you for your patience to learn and implement. Kindly leave your opinion below. you can appreciate our effort, by sharing with friends and social networks. See you in the next one.


