DEV Community

loading...

Terraform for Beginner - AWS

anthonylaw profile image Anthony Law ・5 min read

Learning journey #RoadToDevOps

Last week I pick Terraform as my study and learning topic.

Terraform are very useful and powerful tools for DevOps development, it allows you writing a plan (Infrastructure as Code) and manage your cloud service.

which mean you can write a cloud infrastructure in coding, such as define how many instanse services, what port number you should active in the firewall. It's interesting to handling so many servers just a few lines of code.

Introduction

By using Terrafrom to deploy a virtual machine (ubuntu OS) in AWS EC2.

Objectives

In this article, you should able:

  • Setup AWS account
  • Use Basic Terraform-CLI command
  • Writing Terraform Language (HCL)
  • Deploy Virtual machine (EC2) in AWS cloud.

AWS Setup

If you are new in AWS please sign up here enjoy AWS Free Tier

We need User's Access Key ID and Secret Key ID from AWS User, and grant promission to User with AmazonEC2FullAccess.

if you dont know how to create user -> watch this

Terraform

Ensure your machine are Install Terraform.

We know if you writing in javascript programming, you will name the file extension as *.js. In Terraform the will define the extension as *.tf and using JSON format or HCL (HashiCorp Configuration Language).

You may feel strange what is HCL (HashiCorp Configuration Language). No worry, It's not complicated and easy to learn and understand. HCL Docs

Once you have done your *.tf script, you have to use Terrform-CLI to execute tf files.

Hands-on

We will use keywords from HCL.

keywords description example
provider define cloud service provider aws, google
resource define the resource we will use aws_instance, google_compute_instance
variable define variable -
output print output after executed -

We will use keywords from Terraform CLI.

keywords description
init To init terraform project in the folder
plan To evaluate current your infrastructure from *.tf
apply To add all define resources.
show To list resource infomation and current state
destroy To remove all defined resources.

start

  1. Create a folder in your machine.

  2. create a files my-first-vm.tf.

  3. Open the files in the editor and start code.

# my-first-vm.tf

# We are pointing "aws" as our provider.

provider "aws" {
    region = "ap-southeast-1"
    access_key = "<access-key-from-aws-user>"
    secret_key = "<secret-key-from-aws-user>"
}

command:

$ terraform init

Initializing provider plugins...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

* provider.aws: version = "~> 2.12"

Terraform has been successfully initialized!

append resource "aws_instance" in my-first-vm.tf

provider "aws" {...}

resource "aws_instance" "ec2" { # I called name "ec2", you can change it
  ami = "ami-0dad20bd1b9c8c004" # Image: Ubuntu Server 18.04 LTS (HVM), SSD Volume Type
  instance_type = "t2.micro" # VM Spec
}

command:

$ terraform plan

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + aws_instance.ec2
      id:                           <computed>
      ami:                          "0dad20bd1b9c8c004"
      arn:                          <computed>
      associate_public_ip_address:  <computed>
      availability_zone:            <computed>
      cpu_core_count:               <computed>
      cpu_threads_per_core:         <computed>
      ebs_block_device.#:           <computed>
      ephemeral_block_device.#:     <computed>
      get_password_data:            "false"
      host_id:                      <computed>
      instance_state:               <computed>
      instance_type:                "t2.micro"
      ipv6_address_count:           <computed>
      ipv6_addresses.#:             <computed>
      key_name:                     <computed>
      network_interface.#:          <computed>
      network_interface_id:         <computed>
      password_data:                <computed>
      placement_group:              <computed>
      primary_network_interface_id: <computed>
      private_dns:                  <computed>
      private_ip:                   <computed>
      public_dns:                   <computed>
      public_ip:                    <computed>
      root_block_device.#:          <computed>
      security_groups.#:            <computed>
      source_dest_check:            "true"
      subnet_id:                    <computed>
      tenancy:                      <computed>
      volume_tags.%:                <computed>
      vpc_security_group_ids.#:     <computed>


Plan: 1 to add, 0 to change, 0 to destroy.

it showing infrastructure going to execute, you will see computed it's because the terraform will help you assign the value, if you are not defined.

In additional, you see Plan: 1 to add, 0 to change, 0 to destroy. it mean 1 resource will be executed.

So in this stage, actually you already completed setup an instance.

command:

$ terraform apply
Terraform will perform the following actions:

  + aws_instance.ec2

...

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

...

aws_instance.ec2: Still creating... (10s elapsed)
aws_instance.ec2: Still creating... (20s elapsed)
aws_instance.ec2: Creation complete after 22s (ID: i-083d6c6c7b01d1640)

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Congratulations, you are successful setup an instance EC2 in AWS, you may login and check it out in AWS dashboard.

Try on this command to get resource infomation.

$ terraform show 

aws_instance.ec2:
  id = i-083d6c6c7b01d1640
  ami = ami-0dad20bd1b9c8c004
  arn = arn:aws:ec2:ap-southeast-1:907443295242:instance/i-083d6c6c7b01d1640
  associate_public_ip_address = true
...
...

!!!!

But wait, how you able to access without setup ssh in the firewall.

let append resource "aws_security_group" in my-first-vm.tf

provider "aws" {...}

resource "aws_instance" "ec2" {...}

# Setup aws_security_group with SSH access

resource "aws_security_group" "allow_ssh" {
  name        = "allow ssh"
  description = "only ssh"

  ingress {
    from_port   = 22
    to_port     = 22
    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"]
  }
}

Now we have let our "ec2" instance to apply "aws_security_group" we define, and also assign keypair for the instance.

so we can use the keypair to access instance with port ssh 22.

if you dont know how to create keypair in AWS, watch this

provider "aws" {...}

resource "aws_instance" "ec2" { # I called name "ec2", you can change it
  ami = "ami-0dad20bd1b9c8c004" # Image: Ubuntu Server 18.04 LTS (HVM), SSD Volume Type
  instance_type = "t2.micro" # VM Spec
  security_groups = ["${aws_security_group.allow_ssh.name}"]
  key_name = "aws-anthony"
}

# Setup aws_security_group with SSH access

resource "aws_security_group" "allow_ssh" {...}

command:

$ terraform apply
aws_instance.ec2: Refreshing state... (ID: i-083d6c6c7b01d1640)

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create
-/+ destroy and then create replacement

Terraform will perform the following actions:

-/+ aws_instance.ec2 (new resource required)
...
...

+ aws_security_group.allow_ssh
...
...

Plan: 2 to add, 0 to change, 1 to destroy.
...
...
...
aws_instance.ec2: Still creating... (10s elapsed)
aws_instance.ec2: Still creating... (20s elapsed)
aws_instance.ec2: Creation complete after 32s (ID: i-079e9b8c1d98e4af5)

Apply complete! Resources: 2 added, 0 changed, 1 destroyed.

You may see it's different from just now, because terraform will keep track all resource status in *.tfstate.
So it shows that, it will destroy the previous instance and recreate again.

great, you now can check it out in your AWS dashboard.

finally, you successfully create an instance in Ubuntu OS. It's trouble to login AWS dashboard and checking what is the instance public ip address.

you may use output keywords to display the public IP address.

provider "aws" {...}

resource "aws_instance" "ec2" {...}

resource "aws_security_group" "allow_ssh" {...}

output "showPublicIP" {
  value = "${aws_instance.ec2.*.public_dns}"
}
$ terraform apply 

aws_security_group.allow_ssh: Refreshing state... (ID: sg-0ca7e9133a701f216)
aws_instance.ec2: Refreshing state... (ID: i-079e9b8c1d98e4af5)

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

showPublicIP = [
    ec2-3-0-184-126.ap-southeast-1.compute.amazonaws.com
]

ssh -i aws-anthony.pem ubuntu@ec2-3-0-184-126.ap-southeast-1.compute.amazonaws.com

Summary

Terraform always execute the *tf in folder, each infrastructure should create a folder, such as aws-instance or google-instance.

if you feel put everything in 1 .tf file is to mess, you may seperate in different .tf such as aws_provider.tf , aws_security.tf

example code

store sepearte example

Discussion

pic
Editor guide
Collapse
cescquintero profile image
Francisco Quintero 🇨🇴

Terraform is a super cool and useful tool to setup infra in cloud providers.

It's way powerful. I remind a setup I did for a mini project inside a big project where I launched a complete infra in AWS with just terraform apply and saving me tons or clicks 😂😂

Keep practicing Terraform and lear more about it.

Collapse
anthonylaw profile image
Anthony Law Author

You are right, even AWS provide UI base to setup, but if you have handle complicate infra and more than one server, terraform always best :D