Terraform in a nutshell

Lal Zada
5 min readJul 31, 2022

--

Terraform is an open source tool from Hashicorp, used for Infrastructure As Code (IAC). It works with almost each of the Cloud service providers i.e

  • AWS
  • GCP
  • Azure
  • Digital Ocean
  • Heroku

etc. It use its custom syntax with file extension of .tf. You define your cloud service provider, what resources you want to create, how all of these resources inter connected, what attributes should come from variables and what should be the desired infrastructure after execution.

main.tf

Cloud Provider

provider "aws" {
region = "us-east-1"
}

Define you resources on AWS

resource "aws_instance" "my_web" {
ami = "ami-xxxx"
instance_type = "t2.micro"
availability_zone = "us-east-1"
vpc_security_group_ids = [aws_security_group.my_sg.id]
key_name = "mykey.pem"
associate_public_ip_address = true
}
resource "aws_security_group" "my_sg" {
name = "my-web-sg"
ingress {
description = "Allow traffic on port 80"
from_port = 80
to_port = 80
protocol = "tcp"
}
}

With these few lines of code, you can up your EC2 instance on AWS with port 80 enabled on EC2 instance public IP.

Next you have to run few terraform commands to get things ready.

Terraform doesn’t come with providers in hands instead it does it once it see what providers do you need i.e first piece of code define the cloud provider.

provider "aws" {
region = "us-east-1"
}

To download the respective plugin for the AWS provider you have to run the command

terraform init

which will download the AWS provider plugin code into .terraformfolder inside your project root dir.

Now everything is ready to ship BUT wait… you should make sure what will be executed by terraform using this command

terraform plan

This will give you the whole picture of what resources will be created on your cloud by terraform. This is just a plan and not the actual result.

To execute the plan you saw above, run the next command

terraform apply

This command should execute the plan and show you the detailed progress of what is being creating and created.

If you want to delete all of the created resources back, just run

terraform destroy

Terraform State Backend

Terraform keeps the latest state of your infrastructure in a local file terraform.tfstate. This state file is used each time you run a terraform plan, apply or destroy command to make sure your terraform code is synced with your cloud actual infrastructure.

BUT… you should never push this state file into your code repository as it may have sensitive data related to your resources.

Wait.. what if multiple team members work on the same terraform project? How i should share this state file with others members then?

Terraform provides state backends where you could store your infrastructure state i.e S3, Google Cloud Storage, Consul, Azurerm etc.

terraform {
backend "s3" {
bucket = "mybucket"
key = "path/to/my/key"
region = "us-east-1"
}
}

Now other team members should have access to this S3 bucket and run this terraform command to get the updated infrastructure state from S3 before adding more resources.

terraform init

Variables

You can define variables and use them in resources instead of static data from this resource definition

resource "aws_instance" "my_web" {
ami = var.ec2_ami
instance_type = var.ec2_instance_type
availability_zone = var.region
vpc_security_group_ids = [aws_security_group.my_sg.id]
key_name = "mykey.pem"
associate_public_ip_address = true
}

Just create a file called variables.tf with your desired variables

variable "ec2_ami" {
type = string
default = "ami-xxxx"
}
variable "ec2_instance_type" {
type = string
default = "t2.micro"
}
variable "region" {
type = string
default = "us-east-1"
}

Terraform supports

  • string
  • int
  • bool
  • list
  • set
  • map
  • tuple
  • object

as variable data types.

variable "my_list"{
type = list
default = [1, 2, 3]
}
variable "assign_public_ip"{
type = bool
default = true
}
variable "my_config"{
type = map
default = {
debug = true
database_url = "https://postgres......"
}
}

You can validate variable values as well inside variable definition.

variable "iam_role_name" {
description = "(required) iam role"
type = string
validation {
condition = length(var.iam_role_name) > 2
error_message = "Role name must contain more than 2 characters."
}
}

If you don’t want to define default values here, you can set all these in a separate file by keeping the file extension to .auto.tfvars i.e variables.auto.tfvars

ec2_ami           = "ami-xxxx"
ec2_instance_type = "t2.micro"
assign_public_ip = true
...
...

So at the end, you should have this directory structure

You can define your variables as env vars by prepending TF_VAR i.e

export TF_VAR_ec2_instance_type

OR by passing as command line args when running terraform plan or terraform apply command

terraform plan -var=”ec2_ami=ami-xxxx” -var “region=us-east-1”

Or if you want to load variable values form another file, you can pass variables file as command line args

terraform plan -var-file="myvariables.tfvars"

Other useful commands

validate your terraform scripts

terraform validate

format and indent your terraform scripts

terraform fmt

show what is being created after the terraform apply command

terraform show

Thank you for making it till the end 🎉

If this article helped you, make sure to:

--

--

Lal Zada

Tech article every week - A software engineer over a decade experience in building apps, infrastructure and CI/CDs