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)