Creating a Public and Private Subnet in AWS
AWS offer highly secure and available network solutions with consistently high performance and global coverage. Today we will try to setup a public and a private subnet to launch ec2 instances in AWS. We will do this by using Terraform.
Amazon's VPC?
Amazon Virtual Private Cloud (Amazon VPC) enables you to launch AWS resources into a virtual network that you’ve defined. This virtual network closely resembles a traditional network that you’d operate in your own data center, with the benefits of using the scalable infrastructure of AWS.
Internet Gateway?
An internet gateway is a horizontally scaled, redundant, and highly available VPC component that allows communication between your VPC and the internet. An internet gateway serves two purposes: to provide a target in your VPC route tables for internet routable traffic, and to perform network address translation (NAT) for instances that have been assigned public IPv4 addresses.
If a gateway associates with routing table then it is known as gateway routing table.
Routing Tables?
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.
Task at hand!
- create a custom VPC with two subnets
- create one public subnet and one private subnet. Here we will launch wordpress in public subnet and MySql in private to increase security.
- Set up Destination Network Address Translation (DNAT) using an Internet Gateway and attach it to the VPC.
- Set routing tables to determine where network traffic from your subnet or gateway is directed.
- Create a security group and mentioned inbound rules.
- Launch ec2 instances for wordpress and mysql
Firstly Install Terraform . Then make a directory and initialize it with the command:
terraform init
Open your editor and make a new file with a .tf extension and add:
provider "aws" { region = "us-east-1" profile = "default" }
This will initialize your aws region and profile. By setting the profile key to default, terraform will automatically search your credential file in available in the .aws folder. For more information you can visit AWS CLI
To create VPC you have to mention the IP range. First let's initialize the variables.
variable "cidr_vpc" { description = "creating CIDR block for VPC" default = "10.1.0.0/16" }
Create two subnets one public and other private. Also we have to mention the IP address range. Remember we get only 251 addresses because First and Last IP Addresses are Network name and Broadcast IP. The third one is for the Gatewa and remaining two are reserved by AWS for future use. Also mention the AZ.
variable "cidr_sn1" { description = "creating CIDR block for subnet 1" default = "10.1.0.0/24" } variable "cidr_sn2" { description = "creating CIDR block for subnet 2" default = "10.1.1.0/24" } variable "az" { description = "availability zone for subnet" default = "us-east-1" }
Now create a environment variable
variable "env_tag" { description = "Environment Tag" default = "Prod" }
This will help us in tagging. Finally we create our VPC and subnets after initializing the variables.
resource "aws_vpc" "vpc" { cidr_block = "${var.cidr_vpc}" enable_dns_support = true enable_dns_hostnames = true tags ={ Environment = "${var.env_tag}" Name= "Terraform_VPC" } } resource "aws_subnet" "public_subnet" { vpc_id = "${aws_vpc.vpc.id}" cidr_block = "${var.cidr_sn1}" map_public_ip_on_launch = "true" availability_zone = "us-east-1a" tags ={ Environment = "${var.env_tag}" Name= "public_subnet" } } resource "aws_subnet" "private_subnet" { vpc_id = "${aws_vpc.vpc.id}" cidr_block = "${var.cidr_sn2}" map_public_ip_on_launch = "true" availability_zone = "us-east-1a" tags ={ Environment = "${var.env_tag}" Name= "private_subnet" } }
Notice that I am enabling the DNS support. Now let's create and Internet Gateway and routing tables.
resource "aws_internet_gateway" "IG" { vpc_id = "${aws_vpc.vpc.id}" tags ={ Environment = "${var.env_tag}" Name= "IG" } } resource "aws_route_table" "public_route" { vpc_id = "${aws_vpc.vpc.id}" route { cidr_block = "0.0.0.0/0" gateway_id = "${aws_internet_gateway.IG.id}" } tags ={ Environment = "${var.env_tag}" Name= "RoutingTable" } }
To use our creations we have to associate them with the subnets.
resource "aws_route_table_association" "subnet_public" { subnet_id = "${aws_subnet.public_subnet.id}" route_table_id = "${aws_route_table.public_route.id}" } resource "aws_route_table_association" "public_route_subnet" { subnet_id = "${aws_subnet.public_subnet.id}" route_table_id = "${aws_route_table.public_route.id}" }
Let's create a security groups for wordpress and mysql ingress and egress rules.
resource "aws_security_group" "sg_wp" { name = "sg_wp" vpc_id = "${aws_vpc.vpc.id}" ingress { from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } ingress { protocol = "tcp" from_port = 80 to_port = 80 cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } tags ={ Environment = "${var.env_tag}" Name= "sg1" } } resource "aws_security_group" "sg_mysql" { name = "sg_mysql" description = "managed by terrafrom for mysql servers" vpc_id = "${aws_vpc.vpc.id}" ingress { protocol = "tcp" from_port = 3306 to_port = 3306 security_groups = ["${aws_security_group.sg_wp.id}"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } tags ={ Environment = "${var.env_tag}" Name= "sg_mysql" } }
Finally we'll set the instances.
resource "aws_instance" "wp_ec2_1" { ami = "ami-052c08d70def0ac62" instance_type = "t2.micro" subnet_id = "${aws_subnet.public_subnet.id}" vpc_security_group_ids = ["${aws_security_group.sg_wp.id}"] key_name = "enterme" tags ={ Environment = "${var.env_tag}" Name= "instance_wp" } } resource "aws_instance" "sql_ec2_1" { ami = "ami-0e9089763828757e1" instance_type = "t2.micro" subnet_id = "${aws_subnet.private_subnet.id}" vpc_security_group_ids = ["${aws_security_group.sg_mysql.id}"] key_name = "enterme" tags ={ Environment = "${var.env_tag}" Name= "instance_sql" } }
Note: The wordpress image might not work on free tier.
Now to apply your code run:
terraform apply
Finally open your public DNS of wordpress instance and set up wordpress.
You can find your sql details from the running instance console.
That's all... have a great day!