Terraform – Quick Reference

  • by

Infrastructure as code (IAC) has revolutionized the way we provision infrastructure. It enabled programmers to build, change and even version control the infrastructure. In my opinion, Terraform is the best IAC tool available that understands multiple clouds. This post covers coding and designing terraform modules.

Q) How do you set up Terraform on your local machine?

Step 1) Install Terraform:

Installation of terraform is very simple and easy. You can use any popular package manager to install it, you can follow the link below

Reference: https://learn.hashicorp.com/tutorials/terraform/install-cli.

Step 2) Install AWS CLI

Step 3) Set aws credentials.

  • environment variables. AWS_ACCESS_KEY_ID & AWS_SECRET_ACCESS_KEY
  • aws configure

Q) What are providers?

Terraform relies on plugins called “providers” to interact with remote systems. Terraform configurations must declare which providers they require, so that Terraform can install and use them

Terraform 0.13 and later:

terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 3.0" } } } # Configure the AWS Provider provider "aws" { region = "us-east-1" } # Create a VPC resource "aws_vpc" "example" { cidr_block = "10.0.0.0/16" }

Terraform 0.12 and earlier:

# Configure the AWS Provider provider "aws" { version = "~> 3.0" region = "us-east-1" } # Create a VPC resource "aws_vpc" "example" { cidr_block = "10.0.0.0/16" }

Q) How do you deploy resources across multiple regions in AWS?

Configure multiple providers

# The default provider configuration; resources that begin with `aws_` will use # it as the default, and it can be referenced as `aws`. provider "aws" { region = "us-east-1" } # Additional provider configuration for west coast region; resources can # reference this as `aws.west`. provider "aws" { alias = "west" region = "us-west-2" }

Specify provider at resource or module level

resource “aws_instance” “foo” {
provider = aws.west

# …
}

module “aws_vpc” {
source = “./aws_vpc”
providers = {
aws = aws.west
}
}

Q) What are the most used Terraform commands?

  • terraform init : terraform scans the code and
    • Downloads modules
    • Downloads the plugins for providers to .terraform folder.
    • Configures backend to store tfstate file
  • terraform plan: shows what terraform will do before actual changes
  • terraform apply: changes the infrastructure (adds, deletes & modifies resources)
  • terraform destroy: destroys the infrastructure

Q) List me more terraform commands that are used in development?

  • terraform output
  • terraform state
  • terraform import

Q) What files are excluded from version control / go into .gitignore?

.terraform

.tfstate

.tfstate.backup

Q) What is user_data resource?

Q) How does terraform refer to another resource?

Q) What is a dependency graph?

Q) What is the input variable format?

Q) What are terraform supported types?

  • String
  • Number
  • Bool
  • List
  • Map
  • Set
  • Object
  • Touple
  • Any (default)

Q) What are type constraints?

  • list(number), list(string)
  • map(string)

Q) How do you pass values to variables?

  • -var
  • –var-file
  • Environment variable
  • Default value

Q) What is string interpolation?

Q) What are lifecycle settings?

  • create_before_destroy: creates new resource before deleting the existing resource
  • prevent_destroy: Any attempt to destroy the resource will cause terraform to error out and exit

Q) How do you add a lifecycle setting to resources?

lifecycle{
create_before_destroy = true
}

Q) What is data_source resource?

It queries the provider for data and the data is available for other resources to refer.

It can also query terraform_remote_state (.tfstate)

Q) What is terraform state?

.tfstate file contains a mapping of real resources to the ones specified in code.

Q) Where do you store state files?

Supported backends

  • S3
  • Azure Storage
  • Google Cloud Storage
  • Terraform Cloud
  • Terraform Enterprise

terraform {
backend “s3” {
# bucket = “
# key = “/terraform.tfstate”
# region = “us-east-2”
# dynamodb_table = “
# encrypt = true
}
}

Q) How do you lock tfstate using dynamodb?

  • Create a Dynamodb table for storing locks. The table must have a primary key named LockID with type of string. If not configured, state locking will be disabled.
  • Specify table in terraform backend “s3” block

The value of LockID is made up of /-md5 with bucket and key being from the backend “s3” stanza of the terraform backend config.

Q) Why should state files not be stored in version control?

  • Locking: No locking mechanism available
  • Secrets: All data in tf state file is stored in plain text

Q) Can we parameterize the backend resource? Does it allow variables?

Q) What are terraform workspaces?

Workspaces allow you to store terraform state in multiple, separate, named workspaces

  • terraform workspace new wspace1: creates new workspace wspace1
  • terraform workspace list
  • terraform workspace select wspace1
  • terraform workspace shows; shows selected workspace

Q) How does the .tfstate path change when workspaces are used?

S3 bucket: env:/{workspace name}/{keypath specified in backend}

Q) How do you change instance type based on the workspace?

instance_type = terraform.workspace == “default” ? “t2.medium” : “t2.micro”

Q) How do you query remote .tfstate?

data “terraform_remote_state” “db”{
backend = “s3”
config = {
bucket = “mybucket01”
key = “stage/mydb/terraform.tfstate”
region = “us-east-1”
}
}

Q) How do you store secrets for resources provisioned by Terraform, example db passwords?

Q) What is template_file resource?

Q) What is the difference between user_data and template_file resource?

Q) What is a terraform module?

A folder containing terraform configuration files is called a module.

The concept of modules allows us to break large code bases into small manageable chunks. It enables code reuse.

Q) How do you pass inputs to module and consume its outputs

Q)What are locals?

Locals are temporary variables. Their scope is within the module.

They are helpful to avoid repeating the same values or expressions multiple times in a configuration

A set of related local values can be declared together in a single locals block:

locals {
service_name = “forum”
owner = “Community Team”
}

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
}
}

Locals can be referred as local.

Q) How do you iterate or create loops in terraform?

The below constructs can be used

  • Count: To create multiple resources
  • For_each
  • For

Q) How do you do conditionals in terraform?

  • Count
  • Combination of for_each and for
  • If string directive

Q) What is the use of a count parameter?

The count parameter on a resource defines how many copies of the resource to create.

Example 1:

resource “aws_instance” “web” {
instance_type = “t2.small”
ami = data.aws_ami.ubuntu.id

# This will create 4 instances
count = 4
}

Example 2: use count.index

variable “user_names” {
type = list(string)
default = [“alpha”, “beta”, “gamma”]
}

resource “aws_iam_user” “seteam” {
count = length(var.user_names)
name = var.user_names[count.index]
}

Example 3: set count using ternary syntax

variable “environment” {
type = “string”
default = “Dev”
}

resource “aws_instance” “web” {
instance_type = “t2.small”
ami = data.aws_ami.ubuntu.id

# This will create 4 instances
count = “${var.environment == “Prod” ? 4 : 2}”
}

Q) How do you use for_each expression?

The for_each expression is used to

1) create multiple copies of a resource

2) create multiple copies of an inline block within a resource

Example 1: create multiple copies of a resource

variable “user_names” {
type = list(string)
default = [“alpha”, “beta”, “gamma”]
}

resource “aws_iam_user” “seteam” {
#for_each supports sets and maps only
for_each = toset(var.user_names)
name = each.value
}

Example 2: create multiple inline blocks in a resource

variable “common_tags” {
type = map(string)
default = {
“maintained_by” = “SE Team”
“cost_center” = “c1001”
}
}

resource “aws_autoscaling_group” “example” {
launch_configuration = aws_launch_configuration.example.id
availability_zones = data.aws_availability_zones.all.names
min_size = 2
max_size = 2

# Use for_each to loop over var.common_tags
dynamic “tag” {
for_each = var.common_tags
content {
key = tag.key
value = tag.value
propagate_at_launch = true
}
}
}

Q) How do you use a for expression?

For expression is used

  • To generate a single value. It is similar to list comprehension / dictionary comprehension in python.
  • To loop in string directive

Example 1:

variable “user_names” {
type = list(string)
default = [“alpha”, “beta”, “gamma”]
}

output “upper_user_names” {
value = [for name in var.user_names: upper(name)]
}

Example 2:

variable “user_names” {
type = map(string)
default = {
alpha = “Engineer”
beta = “Sr.Engineer”
gamma = “Manager”
}
}

output “roles” {
value = { for name, role in var.user_names:
name => role
}
}

Example 3: for in string directive

variable “user_names” {
type = list(string)
default = [“alpha”, “beta”, “gamma”]
}

output “string_directive_example” {
value = <for name in var.user_names}
${name}
%{ endfor }
EOF
}

Q) How do you combine for_each and for to create conditionals?

The number of resources or inline blocks created by for_each expression depends on the collection passed to it. If you pass an empty collection, it creates 0 resources or 0 inline blocks. If you pass an non-empty collection, it creates 1 or more resources or inline blocks.

dynamic “tag”{
for_each = {
for key, value in var.custom_tags:
key => upper(value)
if key != “Name”
}

content {
key = tag.key
value = tag.value
}
}

Q) What are string directives?

variable “environment” {
type = string
default = “dev”
}

output “string_directive_example” {
value = “Hello, %{ if var.environment == “prod”}
${environment}
%{ endif }”
}

Don’t delete this line

variable “user_names” {

type = list(string)

default = [“alpha”, “beta”, “gamma”]

}

output “string_directive_example” {

value = <

%{ for name in var.user_names}

${name}

%{ endfor }

EOF

}

Dont’ delete this line too

Design and Implementation

How do you secure state files?

How can we run terraform across multiple accounts?

How do you run terraform?

Atalntis:

Links:

Terraform Issues

Atlantis

How Atlantis works?

Atlantis commands?

#default
atlantis plan -w {workspacename}
#custom options
atlantis plan -w {workspacename} -var-file=.env/{workspacename}.tfvars

atlantis apply -w {workspacename}
atlantis plan -w {workspacename} -var-file=.env/{workspacename}.tfvars

Note: For Atlantis to be able to plan automatically with .tfvars files, you need to create an atlantis.yaml file to tell it to use -var-file={YOUR_FILE}.

How do you create infrastructure using atlantis?

  • Git repo: Create a new file in the folder that holds tfvars for each workspace; that creates a pull request as well
  • Git repo: Type atlantis plan command in the comment section for the pull request
  • Git repo: Check the output from atlantis and if output is good
  • Git repo: Type atlantis apply command in the comment section for the pull request
  • Git repo: merge pull request.

How Atlantis executes terraform commands?

  • clones repo
  • intializes terraform
  • creates a workspace and selects the workspace
  • plans using the {workspace}.vars file

What is atlantis.yaml?

Terraform deployment workflow atlantis vs jenkins?

Atlantis locking?

Issues with Atlantis locking?

How can we run Atlantis across multiple accounts?

How is Atlantis integrated with git repo?

Leave a Reply

Your email address will not be published. Required fields are marked *