Hugo Future Imperfect Slim

Shashi Shetty

Opinions Are My Own.

Infrastructure as code using Terraform - Part 1

Series of blog posts on Terraform.

Shashi Shetty

6-Minute Read

Terraform Introduction

Infrastructure as code, popularly known as IaC, adopted by industry through DevOps, the key reason being source code would always generate the same result. Infrastructure as code evolved to solve the problem of environment drift in the release pipelines. Inconsistency among environments leads to issues during deployments. Without IaC, administration and infrastructure maintenance involves manual processes that are hard to track and contributed to errors.

The most popular tools used for Iac are Azure ARM and Terraform. As the name suggests, Azure ARM is intended for Azure Cloud infra; however, Terraform supports multi cloud Infrastructure, VMware, and on-prem Infrastructure. Both the tools have their advantage and disadvantages. In both cases, administrators needs to spend some time to understand the syntax and nuances.

Terraform is a preferred tool for IaC as most organizations use more than one cloud to host their resources. Some of the advantages of Terraform are

  • Ease of understanding
  • Multi-cloud support
  • Code versioning
  • Statefile
  • Workspace to separate different stacks
  • Inbuilt dependency calculation
  • Parallel execution capability
  • One-click or auto deployments and decommissions

A typical Terraform code has the following components

  • Variables
  • Data
  • Providers
  • Resources
  • Output

Let us go through a simple example of creating a resource group. What do we need first? Before you start coding, you need a valid Azure account and authorization to create the required resources. You can use either PowerShell, azure cloud shell. You can directly start coding in the local system or using the Azure cloud shell. In this post, I am using the visual studio editor.

You can follow the installation instructions at link

Under the variable section, define the Resource Group Name and location. {} indicate the actual value of the variables are in the VAR file. The point to remember here is the file name needs to be terraform.tfvars

#############################################################################
# VARIABLES
#############################################################################
variable "RGname" {}
variable "location" {}

Example of Var File

RGname = "test-group"
location = "eastus"

Provider is nothing but the plugin the Terraform needs to import before executing the code; in our case, it’s Azure. ~> indicated the azurerm version needs to be greater than 1.0

#############################################################################
# PROVIDERS
#############################################################################
 
#Import Azure provider/plugin 

provider azurerm {

 version = ~> 1.0.
}

Resources is the section you would create the actual resource . Here we are stating resource group “Rname " with the resource type as “azurerm_resource_group,” . Name and the location are the two mandatory properties to create a resource group. Name is populated using the value of declared variable RGname, which is of type string with allowed special characters. Lets say your company has a mandatory rule to have all the resource names in lower case , this is where you use inbuilt terraform functions . The code would look like – “name = lower(var.RGname)”

#############################################################################
# RESOURCES
#############################################################################
resource "azurerm_resource_group" "Rname" {
  name = var.RGname
  location = var.location
  tags = {
    "BusinessUnit" = "Test"
  }
  }

Output : this is where you display the resource group name and location

#############################################################################
# OUTPUTS
#############################################################################
output "ResourceGroupname" {
  value = azurerm_resource_group.Rname.name
}

output "ResourceGrouplocation" {
  value = azurerm_resource_group.Rname.location
}

How to run your first azure terraform code

  • Create a folder “Terraform.”
  • Navigate to the newly created folder “blab”
  • Save the code as main.tf
  • Save your variable file as terraform.tfvar

First step to execute your code is - Run terraform init , which will load the plugins defined under providers section of the code

PS D:\Terraform\blab> terraform init

Initializing the backend...

Initializing provider plugins...
- Using previously-installed hashicorp/azurerm v1.44.0

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,    
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
PS D:\Terraform\blab> 

The next step is to run Terraform plan, which will draw out an execution plan. Terraform performs a refresh, and then determines what actions are necessary to achieve the desired state specified in the configuration files. This step will not modify or create any resources.

PS D:\Terraform\blab> terraform plan  -out .\plan.tfplan      
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


------------------------------------------------------------------------

An execution plan has been generated and is shown below.  
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # azurerm_resource_group.Rname will be created
  + resource "azurerm_resource_group" "Rname" {
      + id       = (known after apply)
      + location = "eastus"
      + name     = "test-group"
      + tags     = {
          + "BusinessUnit" = "Test"
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + ResourceGrouplocation = "eastus"
  + ResourceGroupname     = "test-group"

------------------------------------------------------------------------

This plan was saved to: .\plan.tfplan

To perform exactly these actions, run the following command to apply:
    terraform apply ".\\plan.tfplan"

The final step is to run Terraform apply to execute the plan which was drawn in the previous step.

PS D:\Terraform\blab>     terraform apply ".\\plan.tfplan"
azurerm_resource_group.Rname: Creating...
azurerm_resource_group.Rname: Creation complete after 2s [id=/subscriptions/XXXXX/resourceGroups/test-group]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your      
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.

State path: terraform.tfstate

Outputs:

ResourceGrouplocation = eastus
ResourceGroupname = test-group

Validate if your script has created the required resource group

PS D:\Terraform\blab> Get-AzResourceGroup test*  | select ResourceGroupName                 

ResourceGroupName
-----------------
test-group

Now , lets explore the option to delete the resources created by terraform. Terraform uses state file to destroy all the resource’s in the current stack

PS D:\Terraform\blab> ls        

    Directory: D:\Terraform\blab

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----          08-03-2021    15:06                .terraform
-a---          08-03-2021    14:54           1293 main.tf
-a---          15-03-2021    17:31           1330 plan.tfplan
-a---          15-03-2021    17:34            899 terraform.tfstate       
-a---          15-03-2021    17:34            156 terraform.tfstate.backup
-a---          08-03-2021    15:05             42 terraform.tfvars        

PS D:\Terraform\blab> terraform destroy
azurerm_resource_group.Rname: Refreshing state... [id=/subscriptions/XXXX/resourceGroups/test-group]

An execution plan has been generated and is shown below.  
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  # azurerm_resource_group.Rname will be destroyed
  - resource "azurerm_resource_group" "Rname" {
      - id       = "/subscriptions/XXXX/resourceGroups/test-group" -> null
      - location = "eastus" -> null
      - name     = "test-group" -> null
      - tags     = {
          - "BusinessUnit" = "Test"
        } -> null
    }

Plan: 0 to add, 0 to change, 1 to destroy.

Changes to Outputs:
  - ResourceGrouplocation = "eastus" -> null
  - ResourceGroupname     = "test-group" -> null

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes 

azurerm_resource_group.Rname: Destroying... [id=/subscriptions/XXXX/resourceGroups/test-group]
azurerm_resource_group.Rname: Still destroying... [id=/subscriptions/XXXX/resourceGroups/test-group, 10s elapsed]azurerm_resource_group.Rname: Still destroying... [id=/subscriptions/XXXX/resourceGroups/test-group, 20s elapsed]azurerm_resource_group.Rname: Still destroying... [id=/subscriptions/XXXX/resourceGroups/test-group, 30s elapsed]azurerm_resource_group.Rname: Still destroying... [id=/subscriptions/XXXX/resourceGroups/test-group, 40s elapsed]azurerm_resource_group.Rname: Still destroying... [id=/subscriptions/XXXX/resourceGroups/test-group, 50s elapsed]azurerm_resource_group.Rname: Destruction complete after 51s

Destroy complete! Resources: 1 destroyed.

PS D:\Terraform\blab> Get-AzResourceGroup test*  | select ResourceGroupName
PS D:\Terraform\blab> 

Say Something

Comments

Nothing yet.

Recent Posts

Categories

About

Dependable and goal-oriented IT infrastructure engineer with 12 years of experience in designing and delivering infrastructure projects.