Terraform: Creating a very basic EC2 module using “aws_ami” data source — 1

awsmine

Revathi Joshi

Posted on October 4, 2022

Terraform: Creating a very basic EC2 module using “aws_ami” data source — 1

Image description

My organization wants to use a template to create a very basic non-fuctional re-usable EC2 instance module with an amazon linux 2 ami ID. A simple file — ec2.tf has been provided to me. I need to modify this simple file into a re-usable module for the other team members.

In the my next article, I plan to modify this project making the EC2 module fully functionable by adding more resources like VPC and its networking components so that you can SSH into it.

Requirements:

  1. Fork and locally clone a GitHub repository with an ec2.tf template as a starting point to create the EC2 module: https://github.com/LevelUpInTech/terraformec2
  2. Create a custom module for EC2 out of the resource block that you can use as repeatable infrastructure.
  3. Push the new created module and the ec2.tf file to your Github repository.

For building this EC2 module, I have used a data source for pulling in an AMI ID instead of a hard-coded value. I have spent so much time to make this work, and after many, many attempts, I succeeded! I have also used Terraform documentation for this purpose.

Modules:

A module is nothing but a collection of Terraform files in a single folder. You can group many resources into a module to be used over and over again.

In short, modules are the key ingredient to writing reusable, maintainable, and testable Terraform code, especially complex configurations making them easier to navigate, read, understand, and make changes.

I have used Terraform documentation (use the navigation to the left to read about the available resources), Derek Morgan’s course and Morethancertified course for this project.

Follow the basic Terraform workflow: write, plan, deploy.

Pre-Requisites:

  • Access to AWS Console with an AWS Account (not root account).

  • Cloud9 IDE

  • GitHub account

  • Install Terraform


Let’s begin!

Fork and locally clone a GitHub repository
Navigate to https://github.com/LevelUpInTech/terraformec2 and click the Fork button in the top right corner of the browser.

Image description

Now, you can see a new repository in your GitHub.

Next, I will clone the repository in my IDE, I am using Cloud9:

  • Open up the cloned repository
  • Click on “Code” and copy the “HTTPS” URL

Image description

Open up Cloud9 IDE terminal and clone the forked repository


git clone https://github.com/LevelUpInTech/terraformec2.git


Enter fullscreen mode Exit fullscreen mode

Now you should see a new directory under your current working directory named terraformec2.

Change the name “terraformec2” to “basic_ec2_module_1”.

Change your working directory to basic_ec2_module_1.

cd basic_ec2_module_1

Start working on the Module

I am going to implement this using a modular approach with Terraform modules.

To get started, let’s create the following organizational structure as shown below.

Image description

This infra has only 1 module “ec2_instance

In the ec2_instance directory create main.tf, outputs.tf, and variables.tf files.

The ec2.tf file has a provider and a resource section.

Image description

  • main.tf :

Cut and paste the resource information from ec2.tf into this file. Make neccessary changes to the resources section. I have used a data source for pulling in an AMI ID instead of a hard-coded value. I have spent so much time to make this work, and after many, many attempts, I succeeded! I have also used Terraform documentation for this purpose.

Image description

# --- Terraform_projects/basic_ec2_module_1/ec2_instance/main.tf ---
# --- used this link to get information for aws_ami ---
# --- https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance ---

data "aws_ami" "linux" {
   most_recent = true
   owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-*-x86_64-gp2"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
}



resource "aws_instance" "my_ec2" {
  ami                = data.aws_ami.linux.id
  instance_type      = var.instance_type

  tags = {
    Name = "my_ec2"
  }
}
Enter fullscreen mode Exit fullscreen mode
  • variables.tf:

create variables so that they are not hard coded in the parent module

# --- Terraform_projects/basic_ec2_module_1/ec2_instance/variables.tf ---

variable "aws_region" {
    type     = string
    default  = "us-east-1"
}



variable "instance_type" {
    type     = string
    default  = "t2.micro"
}
Enter fullscreen mode Exit fullscreen mode
  • outputs.tf:

As the name indicates, after executing Terraform apply, it outputs — the public ip and ec2 name tag values.

# --- Terraform_projects/basic_ec2_module_1/ec2_instance/outputs.tf ---

output "ec2_public_ip" {
  value = aws_instance.my_ec2.public_ip
}

output "my_ec2_name" {
  value = aws_instance.my_ec2.tags_all.Name
}
Enter fullscreen mode Exit fullscreen mode
  • providers.tf :

cut and paste the Provider information from ec2.tf into this file.

Image description

Make changes in the providers.tf file to get the latest version for Terraform. Get the variables from the variables.tf file so that they are not hard-coded and reference them in the main.tf.

# --- Terraform_projects/basic_ec2_module_1/providers.tf ---

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.23"
    }
  }
  required_version = ">= 1.2.0"
}

provider "aws" {
  region = var.aws_region
}
Enter fullscreen mode Exit fullscreen mode
  • ec2.tf:

Now make this file to reference instance module — ec2_instance.

# --- Terraform_projects/basic_ec2_module_1/ec2.tf ---

module "ec2_instance" {
  source = "./ec2_instance"
}
Enter fullscreen mode Exit fullscreen mode
  • outputs.tf:

After executing Terraform apply, the values for public ip and ec2 name tag will be displayed.

# --- Terraform_projects/basic_ec2_module_1/outputs.tf ---

output "ec2_public_ip" {
  value = module.ec2_instance.ec2_public_ip
}

output "my_ec2_name" {
  value = module.ec2_instance.my_ec2_name
}
Enter fullscreen mode Exit fullscreen mode

Now run these Terraform commands in the following order:

Run terraform init to initialize Terraform.
Run terraform fmt to format the code.
Run terraform validate to check for any syntax errors.
Run terraform plan to see what resources will be created.
Run terraform apply and type yes when prompted.

Image description

Image description

Image description

Image description

To check ec2 instance from AWS Console

Login to your AWS account and navigate to the us-east-1 region > EC2 > Instances to see if our instance was created.

Push To GitHub

Run these Git commands in the following order from the Cloud9 IDE terminal from the directory Terraform_projects/basic_ec2_module_1 — which has all the files for this project.

Run git status to verify all your files are accounted for.
Run git add ec2_instance This will add your files to a staging area.
Run git add ec2.tf This will add your files to a staging area.
Run git add outputs.tf This will add your files to a staging area.
Run git add providers.tf This will add your files to a staging area.
Run git commit -m “initial commit” . This will commit your files.
run git push origin to push your code changes to your GitHub repository.

Open the GitHub repository to verify all the files that have been added.

Run a terraform destroy from the Cloud9 IDE terminal to remove our instance. Type yes when prompted.

Image description

Thanks for reading ! More in my next article…

💖 💪 🙅 🚩
awsmine
Revathi Joshi

Posted on October 4, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related