day-04-Terraform

Day-04

Terraform Terraform Variable and Datasources

-> Create a terraform-key in AWS ec2 key-pairs which we will reference in our EC2 instance.

Step-01: Introduction

Terraform Concepts;

-> terraform Input variables
-> Terraform Datasources
-> Terraform Output Values

What are we Going to Learn?

  1. Learn about Terraform Input Variable basics

    • AWS Region

    • Instance Type

    • Key Name

  2. Define Security Groups and Associate them as a list item to AWS EC2 Instance

    • vpc-ssh

    • vpc-web

  3. Learn about Terraform Output Values

    • Public IP

    • Public DNS

  4. Get the latest EC2 AMI ID using Terraform Datasources concept

  5. we are also going to use the existing EC2 Key pair terraform-key

  6. Use all the above to create an EC2 Instance in Default VPC

Step-02: c2-variables.tf - Define Input Variables in Terraform

# AWS Region

Variable "aws_region" {
  description = "Region in which AWS resources to be created"
  type= string
  default = "ap-northeast-1"
}

# AWS EC2 Instance Type
Variable "instance_type" {
   description = "EC2 instance type"
   type = string
   default = "t3.micro"
}

# AWS EC2 Instance Key-pair, *terraform-key* contains the newly generated public-key content
variable "instance_keypair" {
   description = "AWS EC2 key-pair that needs to be associated with EC2 Instance"
   type= string
   default = "terraform-key"
}
  • Reference the variables in respective .tf files
    # c1-versions.tf
    region = var.aws_region
    #c5-ec2instance.tf
    instance_type = var.instance_type key_name = var.instance_keypair

Step-03: c3-ec2Securitygroups.tf - Define Security Group Resources in Terraform

# Create Security Group - SSH Traffic
resource "aws_security_group" "vpc-ssh" {
  name = "vpc-ssh"
  description = "Dev VPC SSH"
  ingress {
    description = "Allow port 22"
    from_port = 22
    to_port = 22
    protocol = "tcp"
    cidr_blocks = ["0:.0.0.0/0"]
  }
  egress {
    description = "Allow all ip and ports outbound"
    from_port = 0
    to_port = 0
    protocol = "-1"
    cidr_blocks = ["0.0.0.0/0"]
 }
}

# Create Security Group - Web Traffic
resource "aws_security_group" "vpc-web" {
  name = "vpc-ssh"
  description = "Dev VPC SSH"
  ingress {
    description = "Allow port 80"
    from_port = 80
    to_port = 80
    protocol = "tcp"
    cidr_blocks = ["0:.0.0.0/0"]
}

  ingress {
    description = "Allow port 443"
    from_port = 443
    to_port = 443
    protocol = "tcp"
    cidr_blocks = ["0:.0.0.0/0"]
}
   egress {
    description = "Allow all ip and ports outbound"
    from_port = 0
    to_port = 0
    protocol = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

In the above code, we are repeating the Resource Block to open every port, like we have a block for port 22 to open and 80 & 443. which is similar to looping.
To overcome this type of repetition or looping of code (it makes code complex, having a big code) we learn about the concept of Terraform Dynamic Block

Terraform Dynamic Block: Terraform dynamic blocks are a way to dynamically generate Terraform configuration code based on the values of variables or maps. Dynamic blocks enable you to generate Terraform resources based on input values and make your configurations more flexible, reusable, and easier to manage.

Let's re-write the above code of Security Groups using Dynamic Block

resource "aws_security_group" "allow_tls" {
  name        = "allow_tls"
  description = "Allow TLS inbound traffic"

  dynamic "ingress" {
    for_each = [22, 80, 443, 3306]
    iterator = port
    content {
      description = "TLS from VPC"
      from_port   = port.value
      to_port     = port.value
      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_tls"
  }
}

#here we have opened four ports, in the same you can add 'n' number of ports to open
  • Reference the Security groups in c5-ec2instance.tf file as list item

# list item
#this is for the first code of Security Group Code
vpc_security_group_ids= [aws_security_group.vpc-ssh.id, aws_security_group.vpc-web.id] or

#this is for the second code of security Group code using dynamic block one
vpc_security_group_ids = [aws_security_group.allow_tls.id]

Step-04: c4-ami-datasource.tf - Define Get latest AMI ID for Amazon Linux2 OS

data "aws_ami" "amazonlinux" {
  most_recent = true

  owners = ["137112412989"]

  filter {
    name   = "name"
    values = ["al2023-ami-2023.0.*-kernel-6.1-x86_64"]
  }

  filter {
    name   = "root-device-type"
    values = ["ebs"]
  }


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

Note : Find the values of above attributes like 'owners' , 'name' frm the below screenshot

  • Reference datasource to get the latest AMI ID
    ami= data.aws_ami.amazonlinux.id

Step-05: c5-ec2instance.tf - Define EC2 Instance resource

# EC2 Instance
resource "aws_instance" "myec2vm" {
  ami = data.aws_ami.amazonlinux.id
  instance_type = var.instance_type
  user_data = file("${path.module}/script.sh")
  key_name = var.instance_keypair
  vpc_security_group_ids = [aws_security_group.vpc-ssh.id, aws_security_group.vpc-web.id]
# vpc_security_group_ids = [aws_security_group.allow_tls.id]
# use any one of the security group Argument. Here, we have used first one
  tags = {
    "name" = "EC2 demo 2"
  }
}

Step-06: c6-outputs.tf - Define Output Values

# Terraform Output Values
output "instance_publicip" {
  description = "EC2 Instance Public IP"
  value = aws_instance.myec2vm.public_ip
}

 output "instance_publicDNS" {
   description = "EC2 instance public DNS"
   value = aws_instance.myec2vm.public_dns
}

Step-07: Execute Terraform Commands

terraform init -> terraform validate -> terraform plan -> terraform apply or terraform apply --auto-approve

when you give terraform plan
Observations:
-> Verify the latest AMI ID picked and displayed in the plan
-> Verify the number of resources that going to get created
-> Verify the Variable replacements worked as expected

when you give terraform apply Observations:
-> Create resources on cloud
-> created terraform.tfstate file when you run the terraform apply command
-> Verify the EC2 Instance AMI ID which got Created

Step-08: Acess Application

# Access the nginx in the browser
http://<PUBLIC-IP>

Step-09: Clean-UP

terraform destroy
rm -rf .terraform*
rm -rf terraform.tfstate*