Terraform is Infra Building and Managing Tool on cloud platform |
Terraform Installed on Machine. |
Ansible, Chef, Pupper etc were designed for OS level configuration but Terraform is Infra level building. |
Teraform was prepared by Mitchell HashiMoto and launched by Hashicorp in 28 July 2014. |
Terraform is Open Source. Terraform script is written in HCL language. |
Terraform communicate with Cloud Provider through API
Terraform configuration file is written in .tf format

We create a .tf file and run it |
First download Terraform on EC2 server using the link https://www.terraform.io/downloads |
To check If Terraform has been installed..run command Terraform version. Example: create a file by command ….vim aws.tf eg: provider “aws” { region = “us-west-2” access_key = “AKIA5IIQ3TJPQBDYIS7Y” secret_key = “9fHyLwgqQmvUQ4+4Eohn4YkiyVaED3b2wGSDMk7T” } resource “aws_instance” “test” { ami = “ami-0cea098ed2ac54925” instance_type = “t3.micro” tags = { Name = “HelloWorld” } } |
Commonly used Terraform commands:
init Prepare your working directory for other commands |
validate Check whether the configuration is valid |
plan Show changes required by the current configuration.It is blueprint of the changes that would happen when apply is executed. |
apply Create or update infrastructure |
destroy Destroy previously-created infrastructure |
All other commands: |
console Try Terraform expressions at an interactive command prompt |
fmt Reformat your configuration in the standard style |
force-unlock Release a stuck lock on the current workspace |
get Install or upgrade remote Terraform modules |
graph Generate a Graphviz graph of the steps in an operation |
import Associate existing infrastructure with a Terraform resource |
login Obtain and save credentials for a remote host |
logout Remove locally-stored credentials for a remote host |
output Show output values from your root module |
providers Show the providers required for this configuration |
refresh Update the state to match remote systems |
show Show the current state or a saved plan |
state Advanced state management |
taint Mark a resource instance as not fully functional |
test Experimental support for module integration testing |
untaint Remove the ‘tainted’ state from a resource instance |
version Show the current Terraform version |
workspace Workspace management |
Terraform Resource configuration Example
Create instance, Default VPC, SSH key, Secuity group | provider “aws” { region = “us-west-2” access_key = “xxxxxxxxxxxxxx” secret_key = “xxxxxxxxxxxxxxx” } resource “aws_instance” “foo” { ami = “ami-005e54dee72cc1d00” # us-west-2 instance_type = “t2.micro” key_name =”techcurious” vpc_security_group_ids =[aws_security_group.techcurious.id] } resource “aws_key_pair” “deployer” { key_name = “techcurious” public_key = “ssh-rsa xxxxxxxxxxxxroot@ip-172-31-32-25” } resource “aws_default_vpc” “default” { tags = { Name = “Default VPC” } } resource “aws_security_group” “techcurious” { name = “techcurious” description = “Allow TLS inbound traffic” vpc_id = aws_default_vpc.default.id ingress { description = “TLS from VPC” from_port = 443 to_port = 443 protocol = “tcp” cidr_blocks = [“0.0.0.0/0”] ipv6_cidr_blocks = [“::/0”] } egress { from_port = 0 to_port = 0 protocol = “-1” cidr_blocks = [“0.0.0.0/0”] ipv6_cidr_blocks = [“::/0”] } tags = { Name = “allow_tls” } } |
How to create AMI using Terraform from Snapshot | resource
“aws_ami” “example” { name = “terraform-example” virtualization_type = “hvm” root_device_name = “/dev/sda1” ebs_block_device { device_name = “/dev/sda1” snapshot_id = “snap-0fe45a80736ee3525” volume_size = 8 } } |
Copy ami to anaother region | provider
“aws” { region = “ap-south-1” access_key = “AKIA5IIQ3TJPQBDYIS7Y” secret_key = “9fHyLwgqQmvUQ4+4Eohn4YkiyVaED3b2wGSDMk7T” } resource “aws_ami_copy” “example” { name = “terraform-example-copy” description = “A copy of ami-xxxxxxxx” source_ami_id = “ami-0f8b5c8a48d8424ca” source_ami_region = “us-west-2” tags = { Name = “HelloWorld” } } |
copy ami from instance | resource
“aws_ami_from_instance” “example” { name = “terraform-example” source_instance_id = “i-xxxxxxxx” } |
Modify ami permission | resource
“aws_ami_from_instance” “example” { name = “terraform-example” source_instance_id = “i-xxxxxxxx” } |
Terraform Variable
Variable–When the values assigned to resources frequently changes, we can use variables. |
Steps in Creating Terraform Variable: |
First we have to define variable |
Then we have to call variable |
Variable example | varaible “Instancetype” { Default=”t2.small” } |
How to map variable to resolurcce | resource “aws instance” “new” ami =var.image instance=var.instancetype |
How to create separate variable file | Both resource file and variable file should be under same folder if a separate variable file is created. Terraform automatically picks up variable file |
Creating a separate variable file | vim variable.tf |
variable
“instancetype” { default=t2.micro } variable “image” { image=abbcvd } tarraform apply |
To have variable value define in terminal remove default values | variable “instancetype” { } variable “image” { } tarraform apply |
We can have variable and value in different files.Value file should always be terrafor.tfvars. Variable file canbe named anyting. If you don’t want to get desired value, you can keep the values as blank in .tfvars file, this will then take the default value from the variable file. | vim terraform.tfvars instancetype=t2.nano image=abcdef |
Variable Example

List Variable Example
provider “aws” { region = “ap-south-1” access_key = “xxxxxxxx” secret_key = “xxxxxxxxx” } variable “instancetype” { type= list default =[“t2.micro”,”t2.medium”,”t3.small”] } resource “aws_instance” “dev-team” { ami = “ami-06489866022e12a14” instance_type = var.instancetype[0] tags = { Name = “dev-team” } } resource “aws_instance” “test-team” { ami = “ami-06489866022e12a14” instance_type = var.instancetype[1] tags = { Name = “test-team” } } resource “aws_instance” “prod-team” { ami = “ami-06489866022e12a14” instance_type = var.instancetype[2] tags = { Name = “prod-team” } } |
Map Variable Example

Count Parameter:
resource “aws_instance” “dev-team” {
ami=”ami-abcded”
instance_type=”t2.micro”
count=3
}
tags={
Name=”dev.$(count.index)“
}
This will create instance as This will create tag as
1st tag–dev0
2nd tag–dev1
3rd tag-dev2
List with Count Variable
example-
provider “aws” {
region = “ap-south-1”
access_key = “xxxxxxxx”
secret_key = “xxxxxxxxx”
}
variable “instancetag” {
type =list
default =[“dev-dep”,”test-dep”,”prod-dep”]
}
variable “instancetype” {
type =list
default=[“t2.small”, “t2.nano”, “t2.medium”]
}
resource “aws_instance” “dev-team” {
ami = “ami-06489866022e12a14”
instance_type =var.instancetype[count.index]
count =3
tags= {
Name=var.instancetage[count.index]
}
}
This will assign the default values mentioned in list by sequence.
Terraform condition statement
Count parameter is used to set conditions.
Example
In the below example we define a variable named input and do not assign any values and then use the count parameter to set the condition statement to create the resources.

In the above example, in the statement count =var.input==”dev”?1:0 if the value of variable input is “dev”, then the condition is set to create 1 instance and if not dev, then no instance.
Example : Setting condition statement with greater than operator

count =var.input>=”2″?1:0 (greater than and equal)
count =var.input<=”2″?1:0 (Less than and equal)
count =var.input<“2”?1:0 (Less than)
count =var.input!=”2″?1:0 (not equal)
count =var.input!=””?1:0 (what if variable value is not entered)
Local Value in Terraform
Using Local Value, we can define tag once and call it for number of resources.
provider “aws” {
region = “ap-south-1”
access_key = “xxxxxxxx”
secret_key = “xxxxxxxx”
}
locals {
comman_tag ={
Name =”UK-Project”
owner =”Rajeev Mishra”
}
}
Example: How to use Local Value.

Terraform Output Values
To see the information of resources without login to console, instead of running Terraform apply we can run Terraform output to see the outputs.
Syntax is
Output “instance_ami” { |
value=aws_instance.web.arn |
} |
terraform output |
tarraform output-json (to see the output in Json format) |
We can create a separate file for output as well in same folder. |
we can see the output value on terraform apply command or on terraform output command. |
To see specific output only example- terraform output instance-cpu terraform output instance-arn terraform output instance-arn |
Output Example- |
terraform output -json (to see the information in json format} |

If you do not want to show any particular information in output,mark it as sensitive. |
eg: output “instance-arn” value=aws_instance.web.arn sensitive=true } |
Terraform .tfstate file:
Whichever folder has .tf resource file, in same folder .tfstate fill will be created. |
Once resources are updated in .tfstate file, it creates a backup of previous file terraform.tfstate backup. |
Use case of .tfstate file |
When we apply Terraform apply , it searces .tfstate file and if it did not get any resource details it considers the resources are fresh and it creates new resouces. |
When terraform.tfstate file is there, it compares with that file and for any new resources creates a new terraform.tfstate file and creates backup. |
Terraform.tfstate fill is in json format and contains all the proviosioned resource information and can be shared with any one who wants to know the resources |
terraform.tfstate file will contain information regarding all the resources–it is in json format and can be sent to whomever want to know the resources. |
terraform.tfstate file is stored on local folder, but if multiple people are working on the project,–then solution is to create a shared folder and upload .tfstate file there.or create a repository in Gitgub and push .tfstate file there. |
Hasicorp provided the solution that .tfstate file can be stored in hasicorp storage.–Terraform enterprises cloud or AWS |
Best recommended option is s3 Storage on AWS cloud as it has versioning control, Locking with the help of dynamodb table and security. |
How to keep .tfstate file to cloud storage |
terraform { |
backend “s3” { |
bucket = “mybucket” |
key = “path/to/my/key” |
region = “us-east-1” |
access key: |
secret key; |
Dynamodb_table:”table name” |
} |
} |
Terraform Provisionar: Application provisioning through terraform.
Provisoner always needs to be defined under resource parameter.
Syntax example:

Types of Provisioners: | |
Local-exec provisioner | When we want to execute the command on local system |
remote-exec proviisioner | Command which we need to run same location where we are running resource file eg AWS Cloud Command we want to execute on remote system. Need to define connection as well in remote-exec provisioiner. |
File proviosioner | To copy file from local system to remote system. In remote system, file will be copied only in destination/temp. Need to define connection as well in file provisioiner. |

Vendor Provisioners–Chef, Puppet, Habitat, Salt states -supported by Terraform Provisioners which can define during setting up resource files
Example of Local-exec provisioner.
Please note when we are using Local-exec provisioner we still need to create remote-exec provisioner and establish a connection or else the local-exec provisioner will not execute.

Packers:
Packer is built by Hashicorp. Packer is built to use system AMI.
Advantages of Packer:
If AMI is saved, any new server with same configuration can be configured quickly.
Packer can be used to create image for the multiple platforms using single configuration file.
How does Packer Works:
Packer can be configured in Json and Hasicorp.
Main components of Packer Json file are builders and provisioners.
Builders– Contains the instance type details, Source image , Destination image etc.
Provisioner–Contains the configuration to be done inside the instance.
Once the image is created, instance is terminated.
In the same configuration file, we can define to create image for AWS, Azure, GCP etc.

To check for any error in the packer JSON file, use the command packer validate filename.json
To build the AMI, run the command packer build filename.json
syntax example
vim test.json
“builders”:[
{
“type”:”amazon-ebs”,
“access_key”:”AKIA5IIQ3TJPQBDYIS7Y”, “secret_key”:”9fHyLwgqQmvUQ4+4Eohn4YkiyVaED3b2wGSDMk7T”
“region”:”ap-south-1″,
“source_ami”:”ami-06489866022e12a14″,
“instance_type”:”t2.micro”,
“ssh_username”:”ec2-user”,
“ami_name”:”techcuriousami”
}
]
Leave a Reply