Terraform Provising Ec2

ยท

4 min read

Terraform Provising Ec2

Setting Up an AWS Infrastructure with Terraform

Welcome to this guide where we will walk you through setting up your own AWS infrastructure using Terraform. Whether you're new to cloud provisioning or looking to refine your skills, this tutorial will help you get started. Let's dive in!

Project Introduction

In this project, we will create an AWS Virtual Private Cloud (VPC) along with several other essential resources using Terraform. We'll set up a VPC, subnet, route table, internet gateway, and security group, launch an EC2 instance within the newly created infrastructure and run the nginx container inside the EC2 instance.

What We Are Doing

We will use Terraform to automate the creation of the following resources:

  1. VPC (Virtual Private Cloud): We'll establish a dedicated network environment within AWS for our resources.

  2. Subnet: We'll create a subnet within the VPC to host our resources.

  3. Route Table: We'll set up a routing table to manage the routing of network traffic.

  4. Internet Gateway: We'll create an internet gateway to allow our resources to communicate with the internet.

  5. Security Group: We'll configure a security group to control inbound and outbound traffic to our resources.

  6. EC2 Instance: We'll launch an EC2 instance within the subnet, allowing us to deploy our application.

  7. Running nginx container: After doing all these things we are going to run the nginx container inside our instance.

Resources Created

  • AWS VPC named ${var.env_prefix}-vac

  • Subnet named ${var.env_prefix}-subnet-1

  • Route Table named ${var.env_prefix}-rtb

  • Internet Gateway named ${var.env_prefix}-igw

  • Security Group named ${var.env_prefix}-SG

  • EC2 Key Pair named project-key

  • EC2 Instance named ${var.env_prefix}-server

Terraform Configuration (YAML)

provider "aws" {
  region = "us-east-1"
}
variable "vpc_cidr_block" {}
variable "subnet_cidr_block" {}
variable "avalibilty_zone" {}
variable "env_prefix" {}
variable "my_ip" {}
variable "instance_type"{}
variable "public_key_location"{}
variable "private_key_location"{}

resource "aws_vpc" "my_vpc" {
    cidr_block = var.vpc_cidr_block
    tags = {
      Name: "${var.env_prefix}-vpc"
    }

}
resource "aws_subnet" "my_subnet" {
    vpc_id = aws_vpc.my_vpc.id
    cidr_block = var.subnet_cidr_block
    availability_zone = var.avalibilty_zone
    tags = {
        Name: "${var.env_prefix}-subnet-1"
    }

}
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: "${var.env_prefix}-rtb"
    }
 }

# Instead of creating new route table you can use the default one
# You can configure in the same way as mentioned below
/*
 resource "aws_default_route_table" "main-rtb"{
    default_route_table_id = aws_vpc.my_vpc.default_route_table_id

    route {
        cidr_block = "0.0.0.0/0"
        gateway_id = aws_internet_gateway.my_igw.id
    }
        tags = {
        Name: "${var.env_prefix}-main-rtb"
    }
}

*/

 resource "aws_internet_gateway" "my_igw" {
    vpc_id = aws_vpc.my_vpc.id

    tags = {
        Name: "${var.env_prefix}-igw"
    }

 }

 resource "aws_route_table_association" "my_rta" {
   subnet_id = aws_subnet.my_subnet.id
   route_table_id = aws_route_table.my_route_table.id

 }

 resource "aws_security_group" "my-sg" { # if you want to use default security group then instead of "aws_security_group" use "aws_default_security_group" 
                                         # Remove the name of security group cause it is already assigned as default and reamining configuration is samename = "my-security-group"
     vpc_id = aws_vpc.my_vpc.id

    ingress{
        from_port = 22
        to_port = 22
        protocol = "tcp"
        cidr_blocks = [var.my_ip]
    }
    ingress{
        from_port = 8080
        to_port = 8080
        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"]
        prefix_list_ids = []
    }
    tags = {
      Name: "${var.env_prefix}-SG"
    }
 }
 resource "aws_key_pair" "ssh-key" {
   key_name = "project-key"
   public_key = file(var.public_key_location)
 }

 resource "aws_instance" "myapp-server" {
   ami = "ami-053b0d53c279acc90"
   instance_type = var.instance_type
   subnet_id=aws_subnet.my_subnet.id
   vpc_security_group_ids = [aws_security_group.my-sg.id]
   availability_zone = var.avalibilty_zone
   associate_public_ip_address = true

   key_name = aws_key_pair.ssh-key.key_name

   connection {
    type = "ssh"
    host = self.public_ip
    user = "ubuntu"
    private_key  = file(var.private_key_location)
   }

   provisioner "file" {
    source ="entry-script.sh"
    destination = "/home/ubuntu/entry-script-on-ec2.sh"
  }

   provisioner "remote-exec"{
       inline = [ 
      "chmod +x /home/ubuntu/entry-script-on-ec2.sh", 
      "sh /home/ubuntu/entry-script-on-ec2.sh",           
    ]
   }
   provisioner "local-exec" {
    command = "echo ${self.public_ip} > output.text"

   }

   tags = {
    Name = "${var.env_prefix}-server"
   }
}
output "aws_public_ip" {
  value = aws_instance.myapp-server.public_ip
}

Explaining the Code

The provided Terraform code accomplishes the following:

  1. VPC and Subnet Creation: We define a VPC and a subnet within that VPC. The subnet is associated with an availability zone.

  2. Route Table and Internet Gateway: We create a route table and associate it with the VPC. This table includes a default route pointing to the internet gateway.

  3. Security Group: We configure a security group allowing SSH access from your IP and opening port 8080 to the world. Outbound traffic is unrestricted.

  4. EC2 Key Pair: We generate an EC2 key pair for secure SSH access.

  5. EC2 Instance: We launch an EC2 instance within the subnet and associate the security group and key pair. We also copy an entry script to the instance and execute it remotely.

Understanding the Entry-Point Script

The entry-point. sh script provided performs the following actions:

#!/bin/bash
sudo apt-get update 
sudo apt install docker.io -y
sudo systemctl start docker
sudo usermod -aG docker ubuntu 
sudo docker pull nginx:latest
sudo docker run -d -p 8080:8080 nginx:latest
  • Updates package information and installs Docker.

  • Starts the Docker service and adds the Ubuntu user to the docker group.

  • Pulls the latest Nginx image and runs a container on port 8080.

Conclusion

Congratulations! You've successfully set up an AWS infrastructure using Terraform. By automating the provisioning of resources, you've saved time and ensured consistency.

ย