Day-24-Aws

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.

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:

  1. Log in to your AWS Management Console.

  2. Navigate to the IAM service and create a new user with programmatic access.

  3. Attach the necessary policies (e.g., AdministratorAccess) to the user.

  4. 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.

Defining Your Infrastructure

Provider Configuration

The first step in your Terraform configuration is to define the provider. Since we are using AWS, add the following to your main.tf file:

provider "aws" {
  region = "us-east-1"
}

Creating a VPC

Next, we will create a Virtual Private Cloud (VPC). Add the following resource definition:

resource "aws_vpc" "my_vpc" {
  cidr_block = "10.0.0.0/16"
  enable_dns_support = true
  enable_dns_hostnames = true
  tags = {
    Name = "MyVPC"
  }
}

Creating Subnets

We will create two subnets within the VPC:

resource "aws_subnet" "subnet1" {
  vpc_id = aws_vpc.my_vpc.id
  cidr_block = "10.0.1.0/24"
  availability_zone = "us-east-1a"
  map_public_ip_on_launch = true
  tags = {
    Name = "Subnet1"
  }
}

resource "aws_subnet" "subnet2" {
  vpc_id = aws_vpc.my_vpc.id
  cidr_block = "10.0.2.0/24"
  availability_zone = "us-east-1b"
  map_public_ip_on_launch = true
  tags = {
    Name = "Subnet2"
  }
}

Creating an Internet Gateway

To allow internet access to our VPC, we need to create an Internet Gateway:

resource "aws_internet_gateway" "my_igw" {
  vpc_id = aws_vpc.my_vpc.id
  tags = {
    Name = "MyIGW"
  }
}

Creating a Route Table

Next, we will create a route table and associate it with our subnets:

resource "aws_route_table" "my_route_table" {
  vpc_id = aws_vpc.my_vpc.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.my_igw.id
  }
  tags = {
    Name = "MyRouteTable"
  }
}

resource "aws_route_table_association" "subnet1_association" {
  subnet_id      = aws_subnet.subnet1.id
  route_table_id = aws_route_table.my_route_table.id
}

resource "aws_route_table_association" "subnet2_association" {
  subnet_id      = aws_subnet.subnet2.id
  route_table_id = aws_route_table.my_route_table.id
}

Creating Security Groups

Security groups act as virtual firewalls for your instances. Define a security group for your EC2 instances:

resource "aws_security_group" "web_sg" {
  vpc_id = aws_vpc.my_vpc.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"]
  }
  tags = {
    Name = "WebSG"
  }
}

Creating EC2 Instances

Now, we will create two EC2 instances:

resource "aws_instance" "web_server1" {
  ami           = "ami-0c55b159cbfafe1f0"  # Replace with your AMI ID
  instance_type = "t2.micro"
  subnet_id     = aws_subnet.subnet1.id
  security_groups = [aws_security_group.web_sg.name]
  user_data = <<-EOF
              #!/bin/bash
              echo "Welcome to Abhishek's channel" > index.html
              nohup python -m SimpleHTTPServer 80 &
              EOF
}

resource "aws_instance" "web_server2" {
  ami           = "ami-0c55b159cbfafe1f0"  # Replace with your AMI ID
  instance_type = "t2.micro"
  subnet_id     = aws_subnet.subnet2.id
  security_groups = [aws_security_group.web_sg.name]
  user_data = <<-EOF
              #!/bin/bash
              echo "Welcome to Cloud Champ" > index.html
              nohup python -m SimpleHTTPServer 80 &
              EOF
}

Creating a Load Balancer

Finally, we will create an Application Load Balancer to distribute traffic between the two EC2 instances:

resource "aws_lb" "my_lb" {
  name               = "my-load-balancer"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.web_sg.id]
  subnets           = [aws_subnet.subnet1.id, aws_subnet.subnet2.id]
}

resource "aws_lb_target_group" "my_tg" {
  name     = "my-target-group"
  port     = 80
  protocol = "HTTP"
  vpc_id   = aws_vpc.my_vpc.id
}

resource "aws_lb_listener" "front_end" {
  load_balancer_arn = aws_lb.my_lb.arn
  port              = "80"
  protocol          = "HTTP"
  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.my_tg.arn
  }
}

Applying Your Configuration

After defining all the resources, run the following commands to apply your configuration:

tf plan

This command shows you what will be created. If everything looks good, run:

tf apply

This command will create all the resources defined in your configuration.

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!