Terraform

  1. 1. Terraform Overview
    1. 1.1. Terraform architecture
    2. 1.2. Terraform Structure
      1. 1.2.1. Terraform Block
      2. 1.2.2. Provider Block
      3. 1.2.3. Resource Block
      4. 1.2.4. Data Block
      5. 1.2.5. Variables Block
      6. 1.2.6. Output Block
      7. 1.2.7. Modules Block
      8. 1.2.8. Locals Block
      9. 1.2.9. Backend Block
      10. 1.2.10. Provisioners Block
  2. 2. Providers in Terraform
  3. 3. References

Terraform is an infrastructure as code tool that enables you to safely and predictably provision and manage infrastructure in any cloud.

Terraform Overview

Terraform allows you to

  • automate and manage your infrastructure
  • your platform
  • and services that run on that platform

Terraform architecture

Terraform architecture mainly consists of the following components:

  1. Terraform Core
  2. Providers
  3. State file

Terraform Structure

Terraform Block

A Terraform block specifies the required providers that terraform needs in order to execute the script. This block also contains the source block that specifies from where terraform should download the provider and also the required version.

1
2
3
4
5
6
7
8
9
# https://developer.hashicorp.com/terraform/language/providers/requirements
terraform {
required_providers {
aws = {
version = ">= 2.7.0"
source = "hashicorp/aws"
}
}
}

Provider Block

A provider block specifies the cloud provider and the API credentials required to connect to the provider’s services. It includes the provider name, version, access key, and secret key.

1
2
3
4
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs
provider "aws" {
region = "us-east-1"
}

Resource Block

A resource block represents a particular resource in the cloud provider’s services. It includes the resource type, name, and configuration details. This is the main block that specifies the type of resource we are trying to deploy.

1
2
3
4
5
# https://developer.hashicorp.com/terraform/language/resources/syntax
resource "aws_instance" "web" {
ami = "ami-a1b2c3d4"
instance_type = "t2.micro"
}

Data Block

A data block is used to fetch data from the provider’s services, which can be used in resource blocks. It includes the data type and configuration details. This is used in scenarios where the resource is already deployed, and you would like to fetch the details of that resource.

1
2
3
4
5
6
7
8
9
10
# https://developer.hashicorp.com/terraform/language/data-sources
data "aws_ami" "example" {
most_recent = true

owners = ["self"]
tags = {
Name = "app-server"
Tested = "true"
}
}

Variables Block

A variable block is used to define input variables that are used in the Terraform configuration. It includes the variable name, type, and default value.

1
2
3
4
5
6
# https://developer.hashicorp.com/terraform/tutorials/aws-get-started/aws-variables
variable "instance_name" {
description = "Value of the Name tag for the EC2 instance"
type = string
default = "ExampleAppServerInstance"
}

Output Block

An output block is used to define output values that are generated by the Terraform configuration. It includes the output name and value.

1
2
3
4
# https://developer.hashicorp.com/terraform/language/values/outputs
output "instance_ip_addr" {
value = aws_instance.server.private_ip
}

Modules Block

Modules are containers for multiple resources that are used together. A module consists of .tf and/or .tf.json files stored in a directory. It is the primary way to package and reuse resources in Terraform.

Every Terraform configuration has at least one model (root module) which contains resources defined in the .tf files. Test configuration we created in the third part of these series is a module.

Modules are a great way to compartmentalize reusable collections of resources in multiple configurations.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.
├── README.md
├── modules/
│ ├── ec2_module/
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── vpc_module/
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ └── subnet_module/
└── main.tf
├── variables.tf
└── outputs.tf

Locals Block

Often called local variables block, this block is used to keep frequently referenced values or expressions to keep the code clean and tidy.

Locals block can hold many variables inside. Expressions in local values are not limited to literal constants. They can also reference other values in the module to transform or combine them. These variables can be accessed using local.var_name notation, note that it is called local. when used to access values inside.

1
2
3
4
5
6
7
8
9
10
11
12
13
# https://developer.hashicorp.com/terraform/language/values/locals
locals {
# Ids for multiple sets of EC2 instances, merged together
instance_ids = concat(aws_instance.blue.*.id, aws_instance.green.*.id)
}

locals {
# Common tags to be assigned to all resources
common_tags = {
Service = local.service_name
Owner = local.owner
}
}

Using Local Values

1
2
3
4
5
resource "aws_instance" "example" {
# ...

tags = local.common_tags
}

Backend Block

A backend defines where Terraform stores its state data files.

1
2
3
4
5
6
terraform {
backend "kubernetes" {
secret_suffix = "state"
config_path = "~/.kube/config"
}
}

Example Referencing

1
2
3
4
5
6
7
data "terraform_remote_state" "foo" {
backend = "kubernetes"
config = {
secret_suffix = "state"
load_config_file = true
}
}

Provisioners Block

Provisioners allows us to specify actions to be performed on local or remote machines to prepare resources for service. There are two types of Terraform provisioners:

  1. local-exec invokes local executable after a resource is created. It runs the process on the machine running Terraform, meaning the machine where you run terraform apply. This is most likely your own computer.
  2. remote-exec invokes remote executable, something like an EC2 instance on AWS.

This is an example of a provisioner for an EC2 instance. This example contains both local-exec and a remote-exec:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
resource "aws_instance" "web_server" {
# ...

provisioner "local-exec" {
command = "Get-Date > completed.txt"
interpreter = ["PowerShell", "-Command"]
}
provisioner "remote-exec" {
inline = [
"chmod +x /tmp/script.sh",
"/tmp/script.sh args",
]
}
}

Providers in Terraform

  • Expose resources for specific infrastructure platforms (e.g AWS, Azure, Google Cloud, etc.)
  • Responsible for understanding API of that platform
  • Just code that knows how to talk to specific technology or platform
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# AWS Provider
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs#authentication-and-configuration

terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}

# Configure the AWS Provider
provider "aws" {
region = "us-east-1"
}

References