In the journey of Cloud learning, I've used the console, cli and SAM cli to deploy the resources in AWS, always wanted to try vendor neutral platform like Terraform due to it declarative statements and CRUD (Create, Read, Update, Delete) actions. Terraform provides the same result as with SAM but makes it easier to manage the resources using the Terraform STATE file.
Terraform allows resource deployment in the cloud for several cloud providers such as AWS, Google Cloud, Azure etc. using provider specific plugins. Hence the first step is to declare the cloud provider which sets up the provider specific environment.
It's always a good idea to draw a simple map to understand a deployment, as deploying multiple resources can quickly become complicated to manage and track. Here is a simple design of the planned deployment.
The code below shows a simple deployment of a custom VPC in AWS with a cidr block of 10.0.0.0/16.
terraform { required_providers { - aws = { - source = "hashicorp/aws" - Declare Provider Specific Plugins version = "> 4.16" - } - } } provider "aws" { region = "eu-north-1" - Declare key variables } # Create a Custom VPC resource "aws_vpc" "vpc_c9" { cidr_block = "10.0.0.0/16" tags = { Name = "vpc_c9" } }
Once we have a VPC the next step is to create key resources which are:
# Create a Subnet inside the VPC resource "aws_subnet" "sub_c9" { vpc_id = aws_vpc.vpc_c9.id cidr_block = "10.0.1.0/24" availability_zone = "eu-north-1b" tags = { Name = "subnet_c9" } map_public_ip_on_launch = true } # Create a Internet Gateway for the VPC resource "aws_internet_gateway" "ig_c9" { vpc_id = aws_vpc.vpc_c9.id depends_on = [aws_vpc.vpc_c9] tags = { Name = "gateway_c9" } } # Create a Route Table for the VPC resource "aws_route_table" "rt_c9" { vpc_id = aws_vpc.vpc_c9.id tags = { Name = "route_table_c9" } } # Associate the route table to the devices inside the Subnet resource "aws_route_table_association" "public" { subnet_id = aws_subnet.sub_c9.id route_table_id = aws_route_table.rt_c9.id } # Create a route to the Internet by pointing to the Internet Gateway resource "aws_route" "rt_internet" { destination_cidr_block = "0.0.0.0/0" route_table_id = aws_route_table.rt_c9.id gateway_id = aws_internet_gateway.ig_c9.id } # Create security group to allow traffic for EC2 instances # Custom VPC's block all incoming/outgoing traffic by default resource "aws_security_group" "sg_c9" { name = "sg_c9vpc" description = "Security group to allow traffic to ec2 instances" vpc_id = aws_vpc.vpc_c9.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 = "security_grp_c9" } }
The last step is to create a couple of ec2 instances to check the VPC and its accessibility from the internet. I've used ec2 instances based on different AMI's which could be changed according to the requirement. An user script is added to both the instances to install a Web Server which is used to check the functionality from the internet. The scripts can be found in the Github resorces.
The code to deploy the ec2 instances is shown below.
# Create instance to act as a web server using UBUNTU AMI resource "aws_instance" "test_server_ubulnx" { ami = "ami-0914547665e6a707c" instance_type = "t3.micro" vpc_security_group_ids = [aws_security_group.sg_c9.id] subnet_id = aws_subnet.sub_c9.id key_name = "terraform-demo" user_data = file("${path.module}/ubuntu_script.sh") tags = { Name = "Ubuntu_web_server" } } # Create instance to act as a web server using AMAZON LINUX AMI resource "aws_instance" "test_server_amzlnx" { ami = "ami-01dad638e8f31ab9a" instance_type = "t3.micro" vpc_security_group_ids = [aws_security_group.sg_c9.id] subnet_id = aws_subnet.sub_c9.id key_name = "terraform-demo" user_data = file("${path.module}/amzlnx_script.sh") tags = { Name = "AmzLnx_web_server" } }
Now we have a VPC with a route to the internet using the Internet Gateway, route tables to route the traffic in the subnet, an Ubuntu and an Amazon Linux web servers which are accessible from the internet. The servers are accessible using the public_ip of the instances in any browser using the following format.
public_ip/index.html