Infrastructure as Code — Terraform on AWS
Tags: aws, cloud, terraform, iac
Published: 2023-03-13 09:40:12

![Architecture](https://cdn-images-1.medium.com/max/2000/1*V5MzcCE4ML6z1yqrgrK4ZQ.png)

**NOTE**: This article have associated with my article — [Monitoring — Prometheus and Grafana on AWS](https://dev.to/budionosan/monitoring-prometheus-and-grafana-on-aws-548h).

Hello everyone. I learn Infrastructure as Code for my future skill. When you create cloud (AWS and many more) resources using the console one time is okay, but creating cloud resources several times is wasting time. This can use the solution — Infrastructure as Code (IaC). With IaC, I have one code only for creating cloud resources. If want to modify the resources, can edit the IaC code only.

For this tutorial, I use [Terraform](https://www.terraform.io/) for IaC focused on AWS. Terraform is an open-source infrastructure as a code tool that can create, change, and improve resources in any environment. The majority of use cases when using Terraform — are infrastructure as code, multi-cloud deployment, managed Kubernetes, managed networking, integration with CI/CD, and more.

Terraform also has CDK (Cloud Development Kit) with language programming — Python, Java, Typescript, and many more. I will practice and write a tutorial about Terraform CDK. Terraform has a [workflow concept](https://developer.hashicorp.com/terraform/intro) of three stages:

* **Write:** You define resources, which may be across multiple cloud providers and services. For this tutorial, I create an EC2 instance and security groups for AWS.

* **Plan:** Terraform creates an execution plan describing the infrastructure it will create, update, or destroy based on the existing infrastructure and your configuration.

* **Apply:** Terraform performs the proposed operations in the correct order, respecting any resource dependencies. For this tutorial, if want to update the properties of an EC2 instance and change security groups, Terraform will recreate the EC2 instance and security groups.

Install Terraform o[n this link](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli). Choose Linux, choose Amazon Linux because I use AWS Cloud9 for my IDE.

    sudo yum install -y yum-utils
    sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/AmazonLinux/hashicorp.repo
    sudo yum -y install terraform

Check Terraform version — terraform -version and show Terraform version results. Create Terraform file to create AWS resources automatically (for Terraform file, upload it to my GitHub). This Terraform file — because VPC is the default, create a security group only.

[learnaws/main.tf at main · budionosan/learnaws (github.com)](https://github.com/budionosan/learnaws/blob/main/Terraform%20on%20AWS/main.tf)

    terraform {
      required_providers {
        aws = {
          source  = "hashicorp/aws"
          version = "~> 4.46"
        }
      }
      required_version = ">= 1.3.6"
    }

Terraform configurations must declare which providers (AWS and many more) they require. Provider requirements have variables — cloud provider, a source location, and a version by a cloud provider. For this tutorial, use AWS. It means the cloud provider is AWS, the source location is [hashicorp/aws](https://registry.terraform.io/providers/hashicorp/aws/latest) and the version by the cloud provider is 4.46.

    provider "aws" {
      region = "us-west-2"
    }

Use AWS as a cloud provider and choose us-west-2 (Oregon) region when creating Terraform files for creating AWS resources.

    resource "aws_security_group" "app_server" {
      name        = "Allow HTTP, SSH and custom TCP"
      description = "Allow HTTP, SSH and custom TCP"
      vpc_id      = "vpc-04c8a40e20cf7bbd6"
    
      ingress {
        description      = "HTTP"
        from_port        = 80
        to_port          = 80
        protocol         = "tcp"
        cidr_blocks      = ["0.0.0.0/0"]
      }
      
      ingress {
        description      = "SSH"
        from_port        = 22
        to_port          = 22
        protocol         = "tcp"
        cidr_blocks      = ["0.0.0.0/0"]
      }
      
      ingress {
        description      = "Custom TCP"
        from_port        = 3000
        to_port          = 3000
        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 HTTP, SSH and custom TCP"
      }
    }

Resource means creating cloud services (for this tutorial, create a security group and EC2 instance) of your infrastructure. The above code means is create security groups for EC2 instance — **aws_security_group**. For **app_server** is named only. The name and description are the same and **vpc_id** is based on my VPC is associated with this security group.

Security groups have a rule that controls the traffic based on protocols and port numbers. Security group rule — ingress means inbound traffic and egress means outbound traffic.

    resource "aws_instance" "app_server" {
      ami             = "ami-0ceecbb0f30a902a6"
      instance_type   = "t2.micro"
      vpc_security_group_ids = [aws_security_group.app_server.id]
    
      tags = {
        Name = "firstuseterraform"
      }
    }

The above code means creating an EC2 instance — **aws_instance** and **app_server** are named only. AMI is based when creating an EC2 instance on AWS Region Oregon and seeing AMI like this. **NOTE**: Terraform can not apply 64-bit Arm. For instance type choose t2.micro. For security group based on resource — **aws_security_group**. When may associate one resource with other resources, write **resource.name.id**. Tags — EC2 instance name.

![AMI](https://cdn-images-1.medium.com/max/2000/1*fLhDbcwTt1GFGZswg0yROA.jpeg)

After creating Terraform file and want deploy infrastructure with Terraform, have the step-by-step:

* **Init** — initialize Terraform plugins that need to manage your infrastructure.

* **Plan** — check the Terraform code before applying.

* **Apply** — apply your Terraform file for deployment to the cloud (AWS and many more).

Now, initialize the Terraform file — **terraform init**. When initialize process is successful, get confirm Terraform has been successfully initialized! For this tutorial, I did not use terraform plan but go to **terraform apply**.

![Terraform](https://cdn-images-1.medium.com/max/2000/1*FDfx7SlHX3otBhtMT9P4pA.jpeg)

When Terraform apply, show plan 2 to add — the security group and EC2 instance, 0 to change (if want to change the code), and 0 to destroy (if want to delete resources in AWS). When show **enter a value** — always **yes** for can create AWS resources. After yes, Terraform automatically creates an EC2 instance and security group and if already complete, show 2 added, 0 changed and 0 destroyed.

![](https://cdn-images-1.medium.com/max/2000/1*cX56iyrCYR5X4IeMdyQmmw.jpeg)

Go to EC2 and check EC2 instance are available or not. EC2 instance with name **firstuseterraform**, instance ID (check above screenshot) and instance type — t2.micro.

![EC2 instance](https://cdn-images-1.medium.com/max/2000/1*tdT-V-1vIJe0ExNRNOpw2w.jpeg)

Go to VPC, and scroll to Security group. Filter-based VPC ID to get the security group. Click security group ID for detail.

![Security group](https://cdn-images-1.medium.com/max/2412/1*zHEN0kP8sIJxcB-PmCoxNg.jpeg)

![Security group detail](https://cdn-images-1.medium.com/max/2288/1*BTv4QQve2jo39lwjekcYXA.jpeg)

![Inbound rules in security group](https://cdn-images-1.medium.com/max/2230/1*juqkg2Yj3wfBkdtkWF7Z6w.jpeg)

![Outbound rules in security group](https://cdn-images-1.medium.com/max/2200/1*5WvkXbO4v2zuDLaHV0t9rQ.jpeg)

If want to create VPC resources — VPC, subnet, internet gateway, route table, and many more can see [this link](https://github.com/budionosan/learnaws/tree/main/Terraform%20on%20AWS/terraform%20module).

![Terraform](https://cdn-images-1.medium.com/max/2000/1*Ck10XIajPd-mnw9Ad1ojAg.jpeg)

![EC2 instance](https://cdn-images-1.medium.com/max/2144/1*Z3JHU_-wfs8tGt7L6hDOmQ.jpeg)

![VPC](https://cdn-images-1.medium.com/max/2000/1*iq3aZ9H64cID0z5j-0q7sQ.jpeg)

![Subnet](https://cdn-images-1.medium.com/max/2000/1*6qxC1GOJGkzLY2BtYlrnTQ.jpeg)

Public subnet connected with internet gateway but private subnet can not connected with internet gateway.

![](https://cdn-images-1.medium.com/max/2000/1*OP6oJ2X0z6iatCEPjttttg.jpeg)

![LEFT — Public Subnet and RIGHT — Private Subnet](https://cdn-images-1.medium.com/max/2000/1*HHf0cJTjuU8F-ui5BoHEiA.jpeg)

![Inbound rules in security group](https://cdn-images-1.medium.com/max/2000/1*pOf6UqAO0ObFgdxQ5JRlEA.jpeg)

![Onbound rules in security group](https://cdn-images-1.medium.com/max/2000/1*MMl59FEl_o4dKK7tHV-BDA.jpeg)

If want to delete AWS resources very easy — **terraform destroy**. When show **enter a value** — always **yes** for can delete AWS resources.

![Destroy](https://cdn-images-1.medium.com/max/2000/1*_Z8d9srlYo3NMdN1Li5ddQ.jpeg)

![Destroyed](https://cdn-images-1.medium.com/max/2000/1*IQ5Vr2OnojkPdM8NA1HtMw.jpeg)

Finally, I can use Terraform to create AWS resources and also still learn Terraform with other AWS services like Amazon RDS and many more. Thank you very much :)