What is Terraform?

What is Terraform?

A deep dive into Terraform. It's components, workflow, expressions, state data, functions, workspaces and more

Introduction to Terraform

Terraform is an IAC tool, used primarily by DevOps teams to automate various infrastructure tasks. The provisioning of cloud resources, for instance, is one of the main use cases of Terraform. It's a cloud-agnostic, open-source provisioning tool written in the Go language and created by HashiCorp.

Provisioning Infrastructure

Provisioning is the process of setting up infrastructure. It can also refer to the steps required to manage access to data and resources, and make them available to users and systems. Provisioning is not the same thing as configuration, but they are both steps in the deployment process.

With Terrafrom you can -

  • Create vpcs and subnets

  • spin up servers

  • Create users and permissions

  • Install packages like docker etc.

Terraform vs Ansible

Ansible vs. Terraform: Key Differences and Comparison of Tools

Terraform Architecture

Terraform Architecture and Components through diagram - DevOpsSchool.com

Example configure file

provider "aws" {
  region = "us-west-2"
}

resource "aws_instance" "example" {
  ami           = "ami-0ff8a91507f77f867"
  instance_type = "t2.micro"

  tags = {
    Name = "example-instance"
  }
}

Declarative Programming

In declarative programming, you specify the name and properties of the infrastructure resources you wish to provision, and then the IaC tool figures out how to achieve that result on its own. You declare to your IaC tool what you want, but not how to get there. Some examples of popular IaC tools that use the declarative programming paradigm include Terraform.

Imperative programming = you specify a list of steps the IaC tool should follow to provision a new resource

Declarative vs Imperative

Declarative FileImperative File
Requires less coding skillRequires a lot of programming knowledge
Highly repeatableLess idempotent
Adapts well to configuration driftExplicitness makes it error-prone

Terraform Commands

  • terraform init — To prepare the working directory for use with Terraform, the terraform init the command performs Backend Initialization, Child Module Installation, and Plugin Installation.

  • terraform plan — Plan will generate an execution plan, showing you what actions will be taken without actually performing the planned actions.

  • terraform apply — Create or update infrastructure depending on the configuration files. By default, a plan will be generated first and will need to be approved before it is applied.

    terraform apply -auto-approve — Apply changes without having to interactively type ‘yes’ to the plan. Useful in automation CI/CD pipelines.

  • terraform destroy — Destroy the infrastructure managed by Terraform.

  • terraform destroy --auto-approve — Destroy the infrastructure without having to interactively type ‘yes’ to the plan. Useful in automation CI/CD pipelines.

  • terraform refresh — Modify the state file with updated metadata containing information on the resources being managed in Terraform. Will not modify your infrastructure.

Terraform Syntax

Provider -

In Terraform, a provider is a plugin that allows Terraform to interact with a specific infrastructure or service. The provider block in the Terraform configuration file is used to configure the provider and specify the provider-specific settings.

provider "aws" {
    access_key = "AKIAIOSFODNN7EXAMPLE"
    secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
    region = "us-west-2"
}

You can also use environment variables or external files to specify your credentials, for example using shared_credentials_file or profile instead of access_key and secret_key to reference the credentials.

Resources -

In Terraform, a resource block is used to create and manage a specific infrastructure resource, such as a virtual machine, a load balancer, or a database. Each resource block specifies the provider, the resource type and the configuration options for that resource.

provider "aws" {
  region = "us-west-2"
}

resource "aws_instance" "example" {
  ami           = "ami-0ff8a91507f77f867"
  instance_type = "t2.micro"

  tags = {
    Name = "example-instance"
  }
}
  • PROVIDER_NAME is the name of the provider you want to use. Examples include aws, azurerm, google, kubernetes, alicloud, etc.

  • RESOURCE_NAME is the unique identifier you choose to name the resource in your terraform configuration

  • RESOURCE_TYPE is the type of resource you want to create, this can vary from provider to provider, for example, for AWS it can be aws_instance, aws_s3_bucket, aws_security_group, etc.

Data Sources -

provider "aws" {
  region = "us-west-2"
}

data "aws_vpc" "example" {
  vpc_id = "vpc-01234567890abcdef0"
}

resource "aws_subnet" "example" {
  vpc_id                  = data.aws_vpc.example.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = "us-west-2a"
}

Here is an example of a Terraform configuration file that uses a data source to retrieve information about an existing Amazon Web Services (AWS) VPC:

This configuration file tells Terraform to use the AWS provider and then use the data "aws_vpc" block to retrieve information about the VPC with the ID "vpc-01234567890abcdef0".

Then, the resource "aws_subnet" block creates a new subnet in the specified VPC and availability zone, and assigns it the CIDR block 10.0.1.0/24.

The data.aws_vpc.example.id is used to reference the VPC id that we retrieved using the data source, this way Terraform knows which vpc it has to create the subnet.

Please note that this is a simple example, and you may need to include additional data sources and resources to provide a complete infrastructure, and also that you need to have the correct credentials and permissions to access the resources.

Output -

The output block in Terraform allows you to easily output the values of specific resources or variables in your Terraform configuration. These outputs can be displayed by running the terraform output command after running terraform apply.

resource "aws_instance" "example" {
  ami           = var.ami
  instance_type = var.instance_type

  tags = {
    Name = "example-instance"
  }
}

output "public_ip" {
  value = aws_instance.example.public_ip
}

In this example, the resource block creates an AWS EC2 instance and the output block outputs the public IP of this instance. After running terraform apply, you can run terraform output public_ip to see the public IP of the instance created.

You can also use the output to reference it in other terraform files, for example, if you have another terraform file that needs to access the created instances' public IP, you can use data "terraform_remote_state" "example" { } and then data.terraform_remote_state.example.outputs.public_ip

Outputs are useful when you need to pass information between Terraform configurations, or if you want to easily view the values of specific resources or variables in your Terraform configuration.

Variables -

Terraform allows for the use of variables to make your configuration more flexible and reusable. Variables can be defined in a separate file called variables.tf, or directly in the main configuration file.

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

variable "instance_type" {
  default = "t2.micro"
}

variable "ami" {
  default = "ami-0ff8a91507f77f867"
}

This file defines three variables: region, instance_type, and ami. These variables can be used in your main configuration file like this:

provider "aws" {
  region = var.region
}

resource "aws_instance" "example" {
  ami           = var.ami
  instance_type = var.instance_type

  tags = {
    Name = "example-instance"
  }
}

Here, the main configuration file is using the variables defined in the variables file to set the provider's region, the AMI and the instance type.

You can also set these variables at runtime by using the -var flag when running the terraform command for example terraform apply -var 'region=eu-west-1'

Using variables in this way allows you to change the behavior of your Terraform configuration without modifying the configuration file itself, making it more reusable and easier to manage.

Did you find this article valuable?

Support Abhishek K by becoming a sponsor. Any amount is appreciated!