Category Archives: Terraform

Learn Terraform with DevOpsRoles.com. Access detailed guides and tutorials to master infrastructure as code and automate your DevOps workflows using Terraform.

Terraform build EC2 instance

Introduction

In this tutorial, How to build a simple environment with one EC2 instance base AWS. Terraform build EC2 instance. This time, I created as follows.

  • VPC
  • Internet Gateway
  • Subnet
  • Route Table
  • Security Group
  • EC2

My Environment for Terraform build EC2 instance

  • OS Window
  • Terraform

To install Terraform, By referring to the following.

If you are on Windows, you can install it as follows.

choco install terraform
terraform -help

Create a template file

First of all, Create a subdirectory and a Terraform template file in it. The name of the template file is arbitrary, but the extensions are *.tf

$ mkdir terraform-aws
$ cd terraform-aws
$ touch main.tf

Terraform Provider settings

We use the provided settings AWS. Terraform supports multiple providers.

provider "aws" {
    access_key = "ACCESS_KEY_HERE"
    secret_key = "SECRET_KEY_HERE"
    region = "us-west-2"
}

Credential information

Use of Terraform variables

variable "access_key" {}
variable "secret_key" {}

provider "aws" {
    access_key = "${var.access_key}"
    secret_key = "${var.secret_key}"
    region = "us-west-2"
}

Assigning a value to a variable

There are three ways to assign a value to a variable.

1.Terraform command

$ terraform apply \
-var 'access_key=AXXXXXXXXXXXXXXXXXXXXXX' \
-var 'secret_key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'

2.Value in the environment variable

$ export TF_VAR_access_key="AXXXXXXXXXXXXXXXXXXXXX"
$ export TF_VAR_secret_key="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

3.Pass the value in a file

For example, the content terraform.tfvars file.

aws_access_key = "AXXXXXXXXXXXXXXXXXXXXX"
aws_secret_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

How to set Default value of variable

For example, We can set default values for variables.

variable "aws_access_key" {}
variable "aws_secret_key" {}
variable "region" {
    default = "us-west-2"
}

provider "aws" {
    access_key = "${var.aws_access_key}"
    secret_key = "${var.aws_secret_key}"
    region = "${var.region}"
}

Provider: AWS –Terraform by HashiCorp

Terraform Resource settings.

In Terraform the resource type is aws_* predefined. Example aws_vpc a VPC, EC2 is aws_instance. Each AWS resource in the format of item name = value. Example the VPC settings.

resource "aws_vpc" "myVPC" {
    cidr_block = "10.1.0.0/16"
    instance_tenancy = "default"
    enable_dns_support = "true"
    enable_dns_hostnames = "false"
    tags = {
      Name = "myVPC"
    }
}

Refer other resources

Internet Gateway settings.

resource "aws_vpc" "myVPC" {
    cidr_block = "10.1.0.0/16"
    instance_tenancy = "default"
    enable_dns_support = "true"
    enable_dns_hostnames = "false"
    tags {
      Name = "myVPC"
    }
}

resource "aws_internet_gateway" "myGW" {
    vpc_id = "${aws_vpc.myVPC.id}"
}

Dependencies between resources

For example, set up a dependency between the VPC and Internet Gateway.

resource "aws_vpc" "myVPC" {
    cidr_block = "10.1.0.0/16"
    instance_tenancy = "default"
    enable_dns_support = "true"
    enable_dns_hostnames = "false"
    tags {
      Name = "myVPC"
    }
}

resource "aws_internet_gateway" "myGW" {
    vpc_id = "${aws_vpc.myVPC.id}"
    depends_on = "${aws_vpc.myVPC}"
}

We mentioned above how to set the default value for a variable. we use of Map as follows

variable "images" {
    default = {
        us-east-1 = "ami-1ecae776"
        us-west-2 = "ami-e7527ed7"
        us-west-1 = "ami-d114f295"
    }
}

The values of variables defined as var.images.us-east-1

Output on the console

output "public ip of aws-test" {
  value = "${aws_instance.aws-test.public_ip}"
}

Terraform build EC2 instance summary

variable "aws_access_key" {}
variable "aws_secret_key" {}
variable "region" {
    default = "us-west-2"
}

variable "images" {
    default = {
        us-east-1 = "ami-1ecae776"
        us-west-2 = "ami-e7527ed7"
        us-west-1 = "ami-d114f295"
    }
}

provider "aws" {
    access_key = "${var.aws_access_key}"
    secret_key = "${var.aws_secret_key}"
    region = "${var.region}"
}

resource "aws_vpc" "myVPC" {
    cidr_block = "10.1.0.0/16"
    instance_tenancy = "default"
    enable_dns_support = "true"
    enable_dns_hostnames = "false"
    tags {
      Name = "myVPC"
    }
}

resource "aws_internet_gateway" "myGW" {
    vpc_id = "${aws_vpc.myVPC.id}"
}

resource "aws_subnet" "public-a" {
    vpc_id = "${aws_vpc.myVPC.id}"
    cidr_block = "10.1.1.0/24"
    availability_zone = "us-west-2a"
}

resource "aws_route_table" "public-route" {
    vpc_id = "${aws_vpc.myVPC.id}"
    route {
        cidr_block = "0.0.0.0/0"
        gateway_id = "${aws_internet_gateway.myGW.id}"
    }
}

resource "aws_route_table_association" "puclic-a" {
    subnet_id = "${aws_subnet.public-a.id}"
    route_table_id = "${aws_route_table.public-route.id}"
}

resource "aws_security_group" "admin" {
    name = "admin"
    description = "Allow SSH inbound traffic"
    vpc_id = "${aws_vpc.myVPC.id}"
    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"]
    }
}

resource "aws_instance" "aws-test" {
    ami = "${var.images.us-west-2}"
    instance_type = "t2.micro"
    key_name = "aws.devopsroles.com"
    vpc_security_group_ids = [
      "${aws_security_group.admin.id}"
    ]
    subnet_id = "${aws_subnet.public-a.id}"
    associate_public_ip_address = "true"
    root_block_device = {
      volume_type = "gp2"
      volume_size = "20"
    }
    ebs_block_device = {
      device_name = "/dev/sdf"
      volume_type = "gp2"
      volume_size = "100"
    }
    tags {
        Name = "aws-test"
    }
}

output "public ip of aws-test" {
  value = "${aws_instance.aws-test.public_ip}"
}

Dry-Run Terraform command

$ terraform plan

terraform plan command will check for syntax errors and parameter errors set in the block, but will not check for the correctness of the parameter values.

Applying a template

Let’s go we apply the template and create a resource on AWS.

$ terraform apply

Use terraform to show the display the content

$ terraform show

Resource changes

  • We add the content in main.tf file.
  • Use terraform plan to check the execution plan. marked with a ” -/ + “. This indicates that the resource will be deleted & recreated as the attribute changes .
  • terraform apply command for creating.

Delete resource

terraform destroy command can delete a set of resources in the template. terraform plan -destroy you can find out the execution plan for resource deletion.

$ terraform plan -destroy
$ terraform destroy

How to split template file

I have settings together in one template file main.tf

You can be divided into 3 files as below

main.tf

provider "aws" {
    access_key = "${var.aws_access_key}"
    secret_key = "${var.aws_secret_key}"
    region = "${var.region}"
}

## Describe the definition of the resource
resource "aws_vpc" "myVPC" {
    cidr_block = "10.1.0.0/16"
    instance_tenancy = "default"
    enable_dns_support = "true"
    enable_dns_hostnames = "false"
    tags {
      Name = "myVPC"
    }
}

...

variables.tf

variable "aws_access_key" {}
variable "aws_secret_key" {}
variable "region" {
    default = "us-west-2"
}

variable "images" {
    default = {
        us-east-1 = "ami-1ecae776"
        us-west-2 = "ami-e7527ed7"
        us-west-1 = "ami-d114f295"
    }
}

outputs.tf

output "public ip of aws-test" {
  value = "${aws_instance.aws-test.public_ip}"
}

Conclusion

You have to use Terraform build EC2 instance. I hope will this your helpful. Thank you for reading the DevopsRoles page!

How to install Terraform on Linux

In this tutorial, How to install Terraform on Centos and Ubuntu. Terraform an Open Source tool. It is safely and predictably create, improve and change Infrastructure.

Feature Key

  • Infrastructure as Code
  • Change Automation
  • Execution Plans
  • Resource Graph

Install Terraform on Centos 7

Link download Terraform here. In this tutorial, The current version of Terraform is 0.12.16

$ sudo yum install wget unzip
$ wget https://releases.hashicorp.com/terraform/0.12.16/terraform_0.12.16_linux_amd64.zip
$ sudo unzip ./terraform_0.12.16_linux_amd64.zip -d /usr/local/bin/

Check Terraform has been installed on your system

$ terraform -v

The output terraform version as below

[vagrant@DevopsRoles ~]$ terraform -v
Terraform v0.12.16

Install Terraform on Ubuntu 18.04

$ sudo apt-get install wget unzip
$ wget https://releases.hashicorp.com/terraform/0.12.16/terraform_0.12.16_linux_amd64.zip
$ sudo unzip ./terraform_0.12.16_linux_amd64.zip -d /usr/local/bin/

Check Terraform has been installed on your system

$ terraform -v

Build an EC2 instance with Terraform

Terraform supports various providers. Example create main.tf file.

$ vi main.tf

# The content as below:
provider "aws" {
    access_key = "ACCESS_KEY"
    secret_key = "SECRET_KEY"
    region = "us-east-2a"
}

Resource settings

The syntax is the resource “resource type” “resource name”.

Details: https://www.terraform.io/docs/providers/aws/index.html

Example like this

[vagrant@DevopsRoles terraform]$ cat main.tf  
 provider "aws" {
     access_key = "ACCESS_KEY"
     secret_key = "SECRET_KEY"
     region = "us-east-2"
 }
 resource "aws_instance" "testEC2" {
     ami = "ami-0c64dd618a49aeee8"
     instance_type = "t2.micro"
     #key_name = "AWS-HUUPV"
     vpc_security_group_ids = [   
        "sg-00c448cd3e48ba684" 
       ] 
     associate_public_ip_address = "true" 
     root_block_device {   
        volume_type = "gp2"   
        volume_size = "20" 
     }
 # EBS
     ebs_block_device {
       device_name = "/dev/sdf"
       volume_type = "gp2"
       volume_size = "10"
     }
     tags = {
         Name = "testEC2"
     }
 }
 output "public_ip_of_testEC2" {
   value = "${aws_instance.testEC2.public_ip}"
 }

Note

ami

Access_key and Secure_key. You click IAM –> Roles

Build on AWS

[vagrant@DevopsRoles terraform]$ terraform init
[vagrant@DevopsRoles terraform]$ terraform plan
[vagrant@DevopsRoles terraform]$ terraform apply

The log console terraform as below

[vagrant@DevopsRoles terraform]$ terraform plan
 Refreshing Terraform state in-memory prior to plan…
 The refreshed state will be used to calculate this plan, but will not be
 persisted to local or remote state storage.
 
 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.testEC2 will be created
 resource "aws_instance" "testEC2" {
 ami                          = "ami-0c64dd618a49aeee8"
 arn                          = (known after apply)
 associate_public_ip_address  = true
 availability_zone            = (known after apply)
 cpu_core_count               = (known after apply)
 cpu_threads_per_core         = (known after apply)
 get_password_data            = false
 host_id                      = (known after apply)
 id                           = (known after apply)
 instance_state               = (known after apply)
 instance_type                = "t2.micro"
 ipv6_address_count           = (known after apply)
 ipv6_addresses               = (known after apply)
 key_name                     = (known after apply)
 network_interface_id         = (known after apply)
 password_data                = (known after apply)
 placement_group              = (known after apply)
 primary_network_interface_id = (known after apply)
 private_dns                  = (known after apply)
 private_ip                   = (known after apply)
 public_dns                   = (known after apply)
 public_ip                    = (known after apply)
 security_groups              = (known after apply)
 source_dest_check            = true
 subnet_id                    = (known after apply)
 tags                         = {
 "Name" = "testEC2"
 }
 tenancy                      = (known after apply)
 volume_tags                  = (known after apply)
 vpc_security_group_ids       = [
 "sg-00c448cd3e48ba684",
 ]
 ebs_block_device {
 delete_on_termination = true
 device_name           = "/dev/sdf"
 encrypted             = (known after apply)
 iops                  = (known after apply)
 kms_key_id            = (known after apply)
 snapshot_id           = (known after apply)
 volume_id             = (known after apply)
 volume_size           = 10
 volume_type           = "gp2"
 }
 ephemeral_block_device {
 device_name  = (known after apply)
 no_device    = (known after apply)
 virtual_name = (known after apply)
 }
 network_interface {
 delete_on_termination = (known after apply)
 device_index          = (known after apply)
 network_interface_id  = (known after apply)
 }
 root_block_device {
 delete_on_termination = true
 encrypted             = (known after apply)
 iops                  = (known after apply)
 kms_key_id            = (known after apply)
 volume_id             = (known after apply)
 volume_size           = 20
 volume_type           = "gp2"
 }
 } 
 Plan: 1 to add, 0 to change, 0 to destroy.
 
 Note: You didn't specify an "-out" parameter to save this plan, so Terraform
 can't guarantee that exactly these actions will be performed if
 "terraform apply" is subsequently run.
 [vagrant@DevopsRoles terraform]$ terraform apply
 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.testEC2 will be created
 resource "aws_instance" "testEC2" {
 ami                          = "ami-0c64dd618a49aeee8"
 arn                          = (known after apply)
 associate_public_ip_address  = true
 availability_zone            = (known after apply)
 cpu_core_count               = (known after apply)
 cpu_threads_per_core         = (known after apply)
 get_password_data            = false
 host_id                      = (known after apply)
 id                           = (known after apply)
 instance_state               = (known after apply)
 instance_type                = "t2.micro"
 ipv6_address_count           = (known after apply)
 ipv6_addresses               = (known after apply)
 key_name                     = (known after apply)
 network_interface_id         = (known after apply)
 password_data                = (known after apply)
 placement_group              = (known after apply)
 primary_network_interface_id = (known after apply)
 private_dns                  = (known after apply)
 private_ip                   = (known after apply)
 public_dns                   = (known after apply)
 public_ip                    = (known after apply)
 security_groups              = (known after apply)
 source_dest_check            = true
 subnet_id                    = (known after apply)
 tags                         = {
 "Name" = "testEC2"
 }
 tenancy                      = (known after apply)
 volume_tags                  = (known after apply)
 vpc_security_group_ids       = [
 "sg-00c448cd3e48ba684",
 ]
 ebs_block_device {
 delete_on_termination = true
 device_name           = "/dev/sdf"
 encrypted             = (known after apply)
 iops                  = (known after apply)
 kms_key_id            = (known after apply)
 snapshot_id           = (known after apply)
 volume_id             = (known after apply)
 volume_size           = 10
 volume_type           = "gp2"
 }
 ephemeral_block_device {
 device_name  = (known after apply)
 no_device    = (known after apply)
 virtual_name = (known after apply)
 }
 network_interface {
 delete_on_termination = (known after apply)
 device_index          = (known after apply)
 network_interface_id  = (known after apply)
 }
 root_block_device {
 delete_on_termination = true
 encrypted             = (known after apply)
 iops                  = (known after apply)
 kms_key_id            = (known after apply)
 volume_id             = (known after apply)
 volume_size           = 20
 volume_type           = "gp2"
 }
 } 
 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.testEC2: Creating…
 aws_instance.testEC2: Still creating… [10s elapsed]
 aws_instance.testEC2: Still creating… [20s elapsed]
 aws_instance.testEC2: Still creating… [30s elapsed]
 aws_instance.testEC2: Creation complete after 36s [id=i-0501a62ccf6380761]
 Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
 Outputs:
 public_ip_of_testEC2 = 18.191.123.168

Check on the AWS console!

Have a good nice! Thank you for reading the DevopsRoles page!