https://github.com/Ngwaabanjong/terraform-projects/tree/main/deploy-vpc-ec2-with-terraform
Introduction to Terraform:
- HashiCorp Terraform is an infrastructure as code tool that lets you define both cloud and on-prem resources in human-readable configuration files.
How Terraform works:
- Terraform’s primary function is to create, modify, and destroy infrastructure resources to match the desired state described in the Terraform configuration.
- Desire state is the code definition.
- Current state is the resource when it’s deployed.
What we will do:
- We will create a basic VPC and its components.
- We will create a security group
- We will create an ec2 instance in the VPC.
Prerequisites:
- Install Terraform – https://www.terraform.io/
- Install AWS CLI – https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html
- Install SDK tool: exp – Visual Studio Code
- Configure IAM access to AWS: $ aws configure
To Configure authentication to your AWS Console, you need to create an IAM user and use it’s credentials on the CLI.
0 – Configure Provider:
- Create a folder for your project & create a file in it called 0-provider.tf
- Terraform provider: Link – https://registry.terraform.io/providers/hashicorp/aws/latest/docs
provider "aws" {
region = "us-east-1"
}
Configure Variables and tags
- There are other ways of passing variables but here we go.
- Create 2 files named variables.tf & terraform.tfvars.
- We will pass the variables in the variables file.
- We will pass the value in the .tfvars file.
- Not to confuse you, we will create just one variable and pass it on the tags, you could create more.
variables.tf
variable "project-name" {
description = "Write the project name as value in the .tfvars file"
}
terraform.tfvars
- This filename shouldn’t be change. It’s unique.
project-name = "my-project-name"
Tag Syntax on resources:
- We will use the project name variable to tag our resources.
tags = {
Name = "${var.project-name}-vpc"
}
1 – Configure VPC:
- (Optional) Select a specific CIDR Range for your infrastructure with the Mask Calculator.
- Subnet Mask Calculator: Link – https://www.site24x7.com/tools/ipv4-subnetcalculator.html
- Every resource has a resource name and a given name.
- Example: the resource name is aws_vpc then I gave MyVpc.
- Create a file in the root folder called 1-vpc.tf
resource "aws_vpc" "MyVpc" {
cidr_block = "10.1.0.0/16"
tags = {
Name = "${var.project-name}-vpc"
}
}
2 – Create Internet Gateway:
- A VPC always needs an internet gateway to access the internet.
- We need to create an IGW and link it to the VPC ID dynamically.
- Syntax: “resource_name.given_name.id” = aws_vpc.MyVpc.id
- Create a file in the root folder and name it 2-internetgw.tf
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.MyVpc.id
tags = {
Name = "${var.project-name}-igw"
}
}
3 – Configure Subnets:
- To create the subnet we need the VPC ID and a CIDR Block.
- We need to link the VPC ID dynamically by following the syntax.
- Syntax: “resource_name.given_name.id” = aws_vpc.MyVpc.id
- Create a file in the root folder and name it 3-subnets.tf
resource "aws_subnet" "public1" {
vpc_id = aws_vpc.MyVpc.id
cidr_block = "10.1.1.0/24"
availability_zone = "us-east-1a"
tags = {
Name = "${var.project-name}-public1"
}
}
resource "aws_subnet" "public2" {
vpc_id = aws_vpc.MyVpc.id
cidr_block = "10.1.2.0/24"
availability_zone = "us-east-1b"
tags = {
Name = "${var.project-name}-public2"
}
}
4 – Create Route Tables:
- Our VPC has an implicit router which must be attached to a subnet.
- We need route tables to control where network traffic is directed.
- Dynamically link the internet gateway ID and VPC ID to the route.
- Create a file in the root folder and name it 4-routetb.tf
resource "aws_route_table" "public_custom_route_table" {
vpc_id = aws_vpc.MyVpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
tags = {
Name = "${var.project-name}-public-rt"
}
}
5 – Configure Route Table Association:
- Create the route table association.
- Dynamically link the Route tb ID & Subnet ID to the association.
- Create a file in the root folder and name it 5-rtassociation.tf
resource "aws_route_table_association" "pub1" {
subnet_id = aws_subnet.public1.id
route_table_id = aws_route_table.public_custom_route_table.id
}
resource "aws_route_table_association" "pub2" {
subnet_id = aws_subnet.public2.id
route_table_id = aws_route_table.public_custom_route_table.id
}
6 – Create a security group for our instance:
- We need a security group to control traffic to our ec2 instance.
- Dynamically link the VPC ID to the security group.
- We will open port 80 for http and 22 for SSH.
- Create a file in the root folder and name it 6-securitygroup.tf
resource "aws_security_group" "MySg" {
name = "my-tf-sg"
description = "Allow HTTP to web server"
vpc_id = aws_vpc.MyVpc.id
ingress {
description = "SSH ingress"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "HTTP 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"]
}
}
7 – Create a .pem Key Pair:
- Login to AWS Console EC2.
- Resource on the left side – Click: Key pair.
- Click: Create Key pair.
- Give name -> select .pem
- Create – it will download on your pc.
8 – Create and EC2 Instance in our VPC:
- We know an EC2 instance is a virtual server in the Cloud.
- We can install our web app by bootstrapping during provisioning.
- We can also install our applications after the instance is created.
- We will link multiple resources to the ec2 for it to reside in our VPC.
- Pick an AMI ID per your template region by login into AWS Console ec2 -> click create instance and copy AMI ID.
- Create a file in the root folder and name it 7-ec2instance.tf
resource "aws_instance" "MyServer" {
ami = "ami-0ff8a91507f77f867"
instance_type = "t2.micro"
key_name = "your pem key name without .pem on it"
monitoring = true
subnet_id = aws_subnet.public2.id
vpc_security_group_ids = [aws_security_group.MySg.id]
associate_public_ip_address = true
//CODE//
# for_each = toset(["node-1", "node-2"])
# tags = {
# Name = "${each.key}-${var.project-name}-ec2"
# }
tags = {
Name = "${var.project-name}-ec2"
}
}
Add multiple instances:
- You may have a request to create multiple instances.
- For each argument is used to add more resources.
- Add the code snippet below to create multiple instances.
- name them differently.
for_each = toset(["node-1", "node-2"])
tags = {
Name = "${each.key}-${var.project-name}-ec2"
}
Terraform CLI Commands:
- terraform init = will initialize the directory by installing independencies.
- terraform validate = will help validate if your code is well written.
- terraform plan = will output the entire plan of the resources that will be created after apply.
- terraform apply = will deploy the resources in your cloud platform.
- terraform destroy = will destroy the whole infrastructure.
$ terraform init
$ terraform validate
$ terraform plan
$ terraform apply
$ terraform destroy