-
Deploying AWS resources using Terraform:
- Prerequisites:
- Create Terraform configuration files:
- Configure Terraform AWS provider block:
- Create a vpc resource in AWS:
- Create an Internet gateway resource in AWS:
- Create a public subnet resource in AWS:
- Create a route table resource in AWS:
- Create and store SSH key pair using terraform:
- Creating AWS key pair using our SSH public key:
- Create a security group resource in AWS:
- Create an EC2 Instance(Ubuntu) and Install Nginx in AWS:
- Explanation:
- Create Output Variable for Ubuntu IP Address:
- Initialize your Terraform Configuration:
- Plan the Infrastructure Changes:
- Apply the Configuration:
- Check through AWS UI:
- Access Through Port 8080 in Your Browser:
- Destroy the Infrastructure:
- Conclusion
Terraform is an Infrastructure as Code (IaC) tool developed by HashiCorp. It enables users to define, provision, and manage infrastructure across multiple cloud platforms like AWS, Azure, and Google Cloud using declarative configuration files. With Terraform, infrastructure can be automated, version-controlled, and shared, ensuring consistency and scalability across environments.
As organizations increasingly adopt cloud services, managing infrastructure becomes more complex. Terraform simplifies this process by allowing users to define the desired infrastructure state in code and letting the tool handle the underlying provisioning. Its multi-cloud support, robust state management, and reusable modules make Terraform a go-to solution for modern cloud infrastructure management.
Terraform Simple Commands:
-
terraform init
– Initializes the working directory and downloads necessary provider plugins. -
terraform plan
– Previews the actions Terraform will take without applying changes. -
terraform apply
– Executes the changes required to reach the desired state of the configuration. -
terraform destroy
– Destroys the managed infrastructure and removes all resources defined in the configuration.
Why Use Terraform on AWS?
Terraform offers several key benefits when managing AWS infrastructure, making it a powerful tool for developers and operations teams:
- Multi-cloud compatibility: Terraform works across many cloud platforms, including AWS, Azure, and Google Cloud, making it easier to manage multi-cloud environments from a single tool.
-
Readable configurations: You can define your infrastructure using human-readable, declarative
.tf
files, which simplifies how you describe and manage your cloud resources. - Declarative infrastructure management: By defining the desired state of your AWS infrastructure, Terraform figures out the necessary actions to achieve that state, eliminating manual processes.
- State management: Terraform keeps track of your current infrastructure in a state file, ensuring consistent and reliable updates and preventing infrastructure drift.
-
Change previews: With the
terraform plan
command, you can preview any changes before applying them, helping to catch potential issues and verify that everything works as expected. - Automation-friendly: Terraform integrates well with CI/CD pipelines, allowing teams to automate provisioning and infrastructure management as part of their development workflows.
- Modular and reusable: You can break down your infrastructure into reusable modules, making it easier to standardize and manage across different environments or teams.
- Orchestrates complex setups: Terraform handles dependencies between resources, ensuring they are created, updated, or destroyed in the right order for seamless deployments.
- Efficient resource management: By building a dependency graph, Terraform optimizes the creation and management of resources, ensuring operations are safe, predictable, and efficient.
Deploying AWS resources using Terraform:
Using Terraform to deploy AWS resources exemplifies the power of Infrastructure as Code (IaC), making cloud infrastructure management more efficient, repeatable, and scalable. In this guide, we’ll walk you through the process of using Terraform to set up, configure, and manage AWS services in a streamlined manner.
The goal of this post is to demonstrate how to create an EC2 instance and deploy Nginx on it, turning the instance into a functional web server. By the end, you’ll have a fully automated setup where your web server is ready to serve content—illustrating the simplicity and power of IaC using Terraform.
If you get stuck at any point, you can refer to the code examples and configurations in my GitHub repo for this blog: Nginx_on_Ubuntu_EC2_Instance.
Prerequisites:
- Install Terraform: This blog may help you to install terraform. Download & Install Terraform on Windows, MacOS, Linux
- AWS CLI Configured: This blog may help you to install and configure aws cli. How to Configure & Install AWS CLI?
Create Terraform configuration files:
In the first step we have to tell terraform that we will be deploying infrastructure on AWS. We can do this by configuring the AWS cloud provider plugin.
Create a file main.tf
, and add the below given code block.
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.56"
}
}
}
This configuration tells Terraform to use the AWS provider and ensures compatibility with Terraform version 1.0 or higher. The provider version is locked to maintain stability and prevent unexpected updates.
Configure Terraform AWS provider block:
The next step is to configure the AWS provider block, which accepts various config parameters. We will start by specifying the region to deploy the infra in, us-east-1
.
provider "aws" {
region = "us-east-1"
}
Create a vpc resource in AWS:
Next, let's create a Virtual Private Cloud (VPC) to serve as the foundation for our AWS infrastructure:
resource "aws_vpc" "main_vpc" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "main-vpc"
}
}
This will provision a VPC with the specified CIDR block, providing isolated networking for our resources.
Create an Internet gateway resource in AWS:
To allow internet access, we need to create an Internet Gateway and attach it to our VPC:
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.main_vpc.id
tags = {
Name = "main-igw"
}
}
This setup creates an Internet Gateway and associates it with our VPC, enabling communication between the VPC and the internet.
Create a public subnet resource in AWS:
To ensure that our VPC has public access, we'll create a public subnet within it:
resource "aws_subnet" "public_subnet" {
vpc_id = aws_vpc.main_vpc.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-east-1a"
map_public_ip_on_launch = true
tags = {
Name = "public-subnet"
}
}
This configuration sets up a subnet that will automatically assign public IP addresses to instances launched in it, enabling them to communicate with the internet.
Create a route table resource in AWS:
To ensure that our public subnet can route traffic to the internet, we'll create a route table and associate it with our subnet:
resource "aws_route_table" "public_rt" {
vpc_id = aws_vpc.main_vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
}
resource "aws_route_table_association" "public_rt_association" {
subnet_id = aws_subnet.public_subnet.id
route_table_id = aws_route_table.public_rt.id
}
This configuration sets up a route table with a route to the internet through the Internet Gateway and associates it with our public subnet, enabling outgoing traffic to reach the internet.
Create and store SSH key pair using terraform:
To enable secure access to our AWS resources, we'll generate an SSH key pair. This key pair will be used for accessing instances securely:
resource "tls_private_key" "ssh_key" {
algorithm = "RSA"
rsa_bits = 4096
}
resource "local_file" "private_key" {
content = tls_private_key.ssh_key.private_key_pem
filename = "./.ssh/terraform_rsa"
}
resource "local_file" "public_key" {
content = tls_private_key.ssh_key.public_key_openssh
filename = "./.ssh/terraform_rsa.pub"
}
This configuration generates an RSA key pair with a 4096-bit key length. The private and public keys are then saved to files in the .ssh
directory, ready for use in connecting to our AWS instances.
Creating AWS key pair using our SSH public key:
Next, we'll create an AWS key pair using the public SSH key we generated:
resource "aws_key_pair" "deployer" {
key_name = "ubuntu_ssh_key"
public_key = tls_private_key.ssh_key.public_key_openssh
}
This resource uploads the public key to AWS, allowing you to securely access your EC2 instances using the corresponding private key.
Create a security group resource in AWS:
To control access to our AWS resources, we need to configure a security group that allows inbound traffic for SSH, HTTP, and HTTPS:
resource "aws_security_group" "allow_ssh_http_https" {
vpc_id = aws_vpc.main_vpc.id
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 443
to_port = 443
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 = "allow-ssh-https-8080"
}
}
This security group allows SSH (port 22), HTTP (port 8080), and HTTPS (port 443) traffic, while permitting all outbound traffic. This setup ensures that your instances can be accessed and managed securely.
Create an EC2 Instance(Ubuntu) and Install Nginx in AWS:
To provision an EC2 instance with the required configuration, we can define the following resource in Terraform:
resource "aws_instance" "ubuntu_instance" {
ami = "ami-0a0e5d9c7acc336f1"
instance_type = "t2.micro"
subnet_id = aws_subnet.public_subnet.id
vpc_security_group_ids = [aws_security_group.allow_ssh_http_https.id]
key_name = aws_key_pair.deployer.key_name
associate_public_ip_address = true
depends_on = [
aws_security_group.allow_ssh_http_https,
aws_internet_gateway.igw
]
user_data = <<-EOF
#!/bin/bash
sudo apt update -y
sudo apt install -y nginx
# Create index.html with H1 tag in the default NGINX web directory
echo "<h1>Hello From Ubuntu EC2 Instance!!!</h1>" | sudo tee /var/www/html/index.html
# Update NGINX to listen on port 8080
sudo sed -i 's/listen 80 default_server;/listen 8080 default_server;/g' /etc/nginx/sites-available/default
# Restart NGINX to apply the changes
sudo systemctl restart nginx
EOF
tags = {
Name = "ubuntu-instance"
}
}
Explanation:
-
AMI and Instance Type:
- The
ami
attribute specifies the Amazon Machine Image (AMI) ID to use for the instance. This particular AMI is a standard Ubuntu image. - The
instance_type
attribute specifies the type of instance to launch, in this case, at2.micro
, which is a low-cost, general-purpose instance.
- The
-
Subnet and Security Group:
-
subnet_id
assigns the instance to the public subnet we created earlier, ensuring it has network access. -
vpc_security_group_ids
associates the instance with the security group, allowing access on ports 22 (SSH), 8080 (HTTP), and 443 (HTTPS).
-
-
Key Pair:
-
key_name
specifies the SSH key pair used for secure access to the instance. This key pair was created earlier and allows you to log in to the instance.
-
-
Public IP:
-
associate_public_ip_address = true
ensures that the instance is assigned a public IP address, enabling external access.
-
-
Dependency Management:
- The
depends_on
attribute ensures that the instance creation waits until the security group and internet gateway are properly set up, ensuring the instance can properly communicate with the internet.
- The
-
User Data Script:
- The
user_data
attribute contains a shell script that runs when the instance launches. It performs the following actions:- Updates the package lists with
sudo apt update -y
. - Installs NGINX with
sudo apt install -y nginx
. - Creates an
index.html
file in the NGINX web directory with a greeting message. - Configures NGINX to listen on port 8080 instead of the default port 80.
- Restarts the NGINX service to apply the new configuration.
- Updates the package lists with
- The
-
Tags:
- The
tags
attribute assigns a name to the instance, making it easier to identify and manage within the AWS Management Console.
- The
This setup ensures that your instance is correctly configured to serve web traffic on port 8080 and is accessible with the necessary security configurations in place.
Create Output Variable for Ubuntu IP Address:
To display the public IP address of the newly created EC2 instance, use the following output configuration in Terraform:
output "ubuntu_instance_public_ip" {
value = aws_instance.ubuntu_instance.public_ip
}
This configuration will provide the public IP of your instance, allowing you to easily access it and verify that everything is set up correctly.
Initialize your Terraform Configuration:
Once you have your main.tf
and other necessary files in place, the next step is to initialize your Terraform environment. Run the following command in your project directory:
terraform init
This command initializes the working directory containing your Terraform configuration files. It downloads the necessary provider plugins, sets up the backend, and prepares the environment for future Terraform operations.
Plan the Infrastructure Changes:
To preview the actions Terraform will take without actually applying any changes, run:
terraform plan
This command generates an execution plan, which shows you what resources will be created, modified, or destroyed. It helps you ensure that everything is configured correctly before applying any changes.
Apply the Configuration:
Once we verify the planned changes. We will deploy the changes to AWS via the terraform apply
command.
Confirm the changes by typing “yes”.
Awesome! You just created your Ubuntu EC2 instance via Terraform.
Check through AWS UI:
Navigate to the AWS Management Console to verify your instance and other resources. You can now view the public IP address and other details directly in the console.
Access Through Port 8080 in Your Browser:
Open your web browser and enter http://<your-public-ip>:8080
in the address bar, replacing <your-public-ip>
with the EC2 instance's public IP. You should see your "Hello From Ubuntu EC2 Instance!!!" message.
Destroy the Infrastructure:
If you want to tear down the infrastructure you created, use the terraform destroy
command:
terraform destroy
Confirm the changes by typing “yes”.
Delete all the resources defined in your configuration, ensuring a clean removal of everything Terraform created.
Conclusion
In this guide, we have successfully utilized Terraform to automate the deployment of an AWS infrastructure, including a VPC, subnet, security group, and EC2 instance. By leveraging Terraform’s capabilities, we streamlined the process of provisioning and configuring resources, ensuring a consistent and efficient setup. Accessing the EC2 instance via port 8080 allows you to verify the deployment and confirm that your configuration is working as expected. This approach exemplifies the power of Infrastructure as Code (IaC) in managing cloud resources effectively and paves the way for scalable and manageable infrastructure solutions.
Stay tuned for our upcoming blogs where we’ll dive deeper into advanced Terraform concepts, including modules, remote backends, state management, and more. We’ll explore how these features can further enhance your infrastructure management and automation practices.
Top comments (6)
Hello,
Does the Ubuntu instance work for windows?
If Terraform and AWS CLI are properly installed and configured on a Windows machine, the EC2 instance should function as expected. The operating system of your local machine does not impact the performance of the EC2 instance, as the instance operates independently in the cloud. Since we are accessing the application on port 8080, there should be no issues related to your local OS. The key factors for successful access are ensuring that your security groups allow traffic on port 8080 and that the EC2 instance is correctly configured and running.
Great. Have been want to do this for sometime!
I'm glad to hear that! If you have any more questions or need further assistance, feel free to ask.
Panchanan:
Hello - With a few local hiccups, your terraform exercise worked like a charm,
I am balancing between terraform and FM/AI learning.
Thanks for the help!
I'm glad to hear it worked well for you despite the hiccups! Balancing Terraform and AI learning sounds exciting—keep up the great work!