Task 3: Launching AWS VPC, Public and Private Subnets using Terraform
Task Description:-
1) Write an Infrastructure as code using Terraform, which automatically creates a VPC.
2) In that VPC we have to create 2 subnets:
a) public subnet [ Accessible for Public World! ]
b) private subnet [ Restricted for Public World! ]
3) Create a public facing internet gateway for connecting our VPC/Network to the internet world and attach this gateway to our VPC.
4) Create a routing table for the Internet gateway so that the instance can connect to the outside world, update and associate it with the public subnet.
5) Launch an ec2 instance that has WordPress setup already having the security group allowing port 80 so that our client can connect to our WordPress site.
6) Launch an ec2 instance that has MYSQL set up already with the security group allowing port 3306 in a private subnet so that our WordPress VM can connect with the same.
Note: WordPress instance is a part of public subnet so that our client can connect our site and MYSQL instance is a part of private subnet so that the outside world can't connect to it.
Terraform Code :-
1. Provider -
Firstly, we will provide the Provider to the Terraform which is AWS along with region and profile.
provider "aws"{
region = "ap-south-1"
profile = "tanmay2"
}
2. VPC -
We created a VPC that has a certain range of IP addresses which is also known as CIDR. This will be provided to the subnets.
Here, we are providing the IP address range or CIDR = 192.168.0.0/16
resource "aws_vpc" "myvpc" {
cidr_block = "192.168.0.0/16"
instance_tenancy = "default"
enable_dns_hostnames = true
}
3. Public Subnet -
This Subnet is connected to the internet. This Subnet is launched in the availability zone ap-south-1a to launch the WordPress. Also, enable the auto public IP assign so that client can access the site.
resource "aws_subnet" "subnet1" {
vpc_id = aws_vpc.myvpc.id
cidr_block = "192.168.0.0/24"
availability_zone = "ap-south-1a"
map_public_ip_on_launch = true
tags = {
Name = "subnet_public"
}
}
4. Private Subnet -
This Subnet is not connected to the internet so that the MYSQL in it is secure and cannot be accessed by the outside. It is in the availability zone ap-south-1b region.
resource "aws_subnet" "subnet2" {
vpc_id = aws_vpc.myvpc.id
cidr_block = "192.168.1.0/24"
availability_zone = "ap-south-1b"
tags = {
Name = "subnet_private"
}
}
5. Internet Gateway -
Next, we created an internet gateway so that our public subnet can connect to the outside world and clients can access the WordPress site.
resource "aws_internet_gateway" "gw" {
vpc_id = aws_vpc.myvpc.id
tags = {
Name = "IGw"
}
}
6. Route Tables -
Created a route table. A route table contains a set of rules, called routes, that are used to determine where network traffic from your subnet or gateway is directed. Also, we have to associate the route table to our public subnet so that it can know where is the internet gateway to connect to the outside world.
resource "aws_route_table" "route" {
vpc_id = aws_vpc.myvpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.gw.id
}
tags = {
Name = "route"
}
}
resource "aws_route_table_association" "asso" {
subnet_id = aws_subnet.subnet1.id
route_table_id = aws_route_table.route.id
}
7. MySQL AMI using snapshot -
First, we launched an instance manually using Amazon Linux AMI, then installed docker and httpd, then pulled MySQL image from docker. Run following commands sequentially :
#sudo su - root
#yum install docker
#systemctl start docker
#systemctl enable docker
#yum install httpd
Recommended by LinkedIn
#systemctl start httpd
#systemctl enable httpd
#yum install mysql
#docker pull mysql:5.7
Then we created a snapshot using this instance and then our own AMI using this snapshot.
8. MySQL Instance -
We launched an instance in the private subnet using our own AMI. We will launch a docker container for MySQL inside this instance.
The security group for MySQL instance - two inbound rules, one for port 3306 as MySQL runs on this port and another port 8080 as we will use this port to expose our MySQL docker container.
resource "aws_instance" "mysql" {
ami = "ami-0f443923b22ba17c3"
instance_type = "t2.micro"
availability_zone = "ap-south-1b"
subnet_id = aws_subnet.subnet2.id
key_name = "mykey"
vpc_security_group_ids = [ aws_security_group.sg1.id ]
user_data = <<-EOF
#!/bin/bash
sudo docker run -dit -e MYSQL_ROOT_PASSWORD=***** -e MYSQL_DATABASE=data -e MYSQL_USER=tanmay -e MYSQL_PASSWORD=***** -p 8080:3306 --name dbos mysql:5.7
EOF
tags = {
Name = "mysql1"
}
}
Security Group for MySQL instance:
resource "aws_security_group" "sg1" {
name = "sg1"
description = "Allow tcp inbound traffic"
vpc_id = aws_vpc.myvpc.id
ingress {
description = "TLS from VPC"
from_port = 3306
to_port = 3306
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "TLS from VPC"
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"]
}
tags = {
Name = "mysqlhttp"
}
}
9. WordPress Instance -
We launched another instance in the public subnet for WordPress. But again for this, we have first created a security group that allows port 80 since WordPress runs on port 80. Then we launch the EC2 instance using my AMI inside which we launch docker container for the WordPress.
resource "aws_instance" "wordpress"{
ami = "ami-0f443923b22ba17c3"
instance_type = "t2.micro"
availability_zone = "ap-south-1a"
associate_public_ip_address = "true"
subnet_id = aws_subnet.subnet1.id
key_name = "mykey"
vpc_security_group_ids = [ aws_security_group.wp1.id ]
connection {
type = "ssh"
user = "ec2-user"
private_key = file("C:/Users/dell/Downloads/mykey.pem")
host = aws_instance.wordpress.public_ip
}
provisioner "remote-exec" {
inline = [
"sudo yum install docker -y",
"sudo service docker start",
"sudo docker pull wordpress:5.1.1-php7.3-apache",
"sudo docker run -dit -e WORDPRESS_DB_HOST=${aws_instance.mysql.private_ip}:8080 -e WORDPRESS_DB_USER=tanmay -e WORDPRESS_DB_PASSWORD=***** -e WORDPRESS_DB_NAME=data -p 8000:80 --name mywp wordpress:5.1.1-php7.3-apache"
]
}
tags = {
Name = "wordpress1"
}
}
Security Group for WordPress instance:
resource "aws_security_group" "wp1" {
name = "wp1"
description = "Allow tcp inbound traffic"
vpc_id = aws_vpc.myvpc.id
ingress {
description = "TLS from VPC"
from_port = 8000
to_port = 8000
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "TLS from VPC"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "TLS from VPC"
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 = "wphttp"
}
}
Now we will run our terraform code, run the following commands in the windows command prompt.
1. terraform init (it will download necessary plugins from the internet)
2. terraform validate (it will check the syntax and keyword error in our code)
3. terraform apply -auto-approve (it will run our terraform code without asking permission "yes")
OUTPUT :
So now we can access WordPress using the public IP of the WordPress instance, which stores all its data in MySQL which is running in the private subnet so that our data is secure.
1.Select the desired language and click on continue.
2. Fill in the details, set username and password, and install WordPress.
3. Login to WordPress.
We are in.
Thank You !!!