In our earlier post, we walked through the process of setting up a beginner's environment on AWS using Terraform. Now, let's dive into the basic services of AWS cloud - network and compute.
In this post, I will guide you through the steps of launching a simple website on an EC2 Linux instance using Terraform. It will use single AZ, single EC2 server without auto-scaling.
We'll break down the process into manageable components by creating Terraform modules for network and web server.
Architecture Overview:
Before we get started, let's take a quick look at the architecture we'll be working with:
Step 1: Creating the VPC and Network Components
The first step is to set up the foundational elements. We'll create a Virtual Private Cloud (VPC) with an Internet Gateway, a public subnet, and a route table. Additionally, we'll set up a security group to manage access to the compute resources.
Variables used throughout the modules are mentioned in variables.tf file.
variables.tf
variable "aws_region" { type = string description = "AWS region to use for resources." default = "us-east-1" } variable "aws_azs" { type = string description = "AWS Availability Zones" default = "us-east-1a" } variable "enable_dns_hostnames" { type = bool description = "Enable DNS hostnames in VPC" default = true } variable "vpc_cidr_block" { type = string description = "Base CIDR Block for VPC" default = "10.0.0.0/16" } variable "vpc_public_subnets_cidr_block" { type = string description = "CIDR Block for Public Subnets in VPC" default = "10.0.0.0/24" } variable "instance_type" { type = string description = "Type for EC2 Instance" default = "t2.micro" } variable "instance_key" { default = "MyKeyPair" }
main.tf in VPC module
Create VPC
# Create the VPC resource "aws_vpc" "app_vpc" { cidr_block = var.vpc_cidr_block enable_dns_hostnames = var.enable_dns_hostnames }
Create internet gateway
# Create the internet gateway resource "aws_internet_gateway" "igw" { vpc_id = aws_vpc.app_vpc.id }
Create public subnet, route table and association
# Create the public subnet resource "aws_subnet" "public_subnet" { vpc_id = aws_vpc.app_vpc.id cidr_block = var.vpc_public_subnets_cidr_block map_public_ip_on_launch = true availability_zone = var.aws_azs } # Create the route table resource "aws_route_table" "public_rt" { vpc_id = aws_vpc.app_vpc.id route { cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.igw.id } } # Assign the public route table to the public subnet resource "aws_route_table_association" "public_rt_asso" { subnet_id = aws_subnet.public_subnet.id route_table_id = aws_route_table.public_rt.id }
Create security group which allows inbound SSH and HTTP traffic and all outbound traffic. (SSH just to connect and check EC2!)
# Create the security group resource "aws_security_group" "sg" { name = "allow_ssh_http" description = "Allow ssh http inbound traffic" vpc_id = aws_vpc.app_vpc.id ingress { description = "SSH from VPC" from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] ipv6_cidr_blocks = ["::/0"] } ingress { description = "HTTP from VPC" from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] ipv6_cidr_blocks = ["::/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] ipv6_cidr_blocks = ["::/0"] } }
Step 2: Launching an EC2 Instance with Apache Web Service
With the network components in place, we'll proceed to launch an EC2 instance. We'll use the Amazon Linux 2 AMI and configure it to run an Apache web service. We will use userdata to install apache and create an index.html which displays instance metadata.
main.tf of WEB module
# Get latest Amazon Linux 2 AMI data "aws_ami" "amazon-linux-2" { most_recent = true owners = ["amazon"] filter { name = "name" values = ["amzn2-ami-hvm*"] } } # Create the Linux EC2 Web server resource "aws_instance" "web" { ami = data.aws_ami.amazon-linux-2.id instance_type = var.instance_type key_name = var.instance_key subnet_id = var.subnet_id security_groups = var.security_groups user_data = <<-EOF #!/bin/bash yum update -y yum install -y httpd.x86_64 systemctl start httpd.service systemctl enable httpd.service instanceId=$(curl http://169.254.169.254/latest/meta-data/instance-id) instanceAZ=$(curl http://169.254.169.254/latest/meta-data/placement/availability-zone) pubHostName=$(curl http://169.254.169.254/latest/meta-data/public-hostname) pubIPv4=$(curl http://169.254.169.254/latest/meta-data/public-ipv4) privHostName=$(curl http://169.254.169.254/latest/meta-data/local-hostname) privIPv4=$(curl http://169.254.169.254/latest/meta-data/local-ipv4) echo "<font face = "Verdana" size = "5">" > /var/www/html/index.html echo "<center><h1>AWS Linux VM Deployed with Terraform</h1></center>" >> /var/www/html/index.html echo "<center> <b>EC2 Instance Metadata</b> </center>" >> /var/www/html/index.html echo "<center> <b>Instance ID:</b> $instanceId </center>" >> /var/www/html/index.html echo "<center> <b>AWS Availablity Zone:</b> $instanceAZ </center>" >> /var/www/html/index.html echo "<center> <b>Public Hostname:</b> $pubHostName </center>" >> /var/www/html/index.html echo "<center> <b>Public IPv4:</b> $pubIPv4 </center>" >> /var/www/html/index.html echo "<center> <b>Private Hostname:</b> $privHostName </center>" >> /var/www/html/index.html echo "<center> <b>Private IPv4:</b> $privIPv4 </center>" >> /var/www/html/index.html echo "</font>" >> /var/www/html/index.html EOF }
Steps to run Terraform
Now we will see how to run the above created terraform infrastructure automation
terraform init terraform plan terraform apply -auto-approve
Once the terrform apply completed successfully it will show the public ipaddress of the apache server as output
Apply complete! Resources: 7 added, 0 changed, 0 destroyed. Outputs: instance_id = "i-0d32ce14df3987030" public_ip = "http://54.165.140.50/"
Running Website
And there you have it – a basic website running on an EC2 Linux instance in AWS, all orchestrated using Terraform.
Cleanup
Remember to stop AWS components to avoid large bills.
terraform destroy -auto-approve
In our next module, we'll take it a step further and explore launching the same website on a Windows Server. Happy coding!
Resources
GitHub Link: https://github.com/chinmayto/terraform-aws-linux-webserver
EC2 Documentation: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/concepts.html
Top comments (0)