The Trinity; IaC with Terraform.

The Trinity; IaC with Terraform.

Imagine the synergy of AWS Cloud Formation, Azure Resource Manager, Google Cloud Deployment Manager and more, wicked right?

Definition

IaC stands for Infrastructure as Code. It's a key concept in modern software development and IT operations. IaC involves managing and provisioning cloud infrastructure via code, rather than through physical hardware configuration or interactive UI configuration tools. AWS Cloud Formation, Azure Resource Manager and Google Cloud Deployment Manager are all IaC tools for their respective Cloud Providers.


Terraform is an Industry as Code (IaC) tool for Cloud Provisioning, it was developed by Hashicorp and makes use of a JSON-like language called HCL which stands for Hashicorp Configuration Language and not the acid :). Terraform is used to provision Cloud services via code and CLI. It goes the extra mile to support Cloud Configuration tools such as Ansible, Chef, Puppet, etc. As earlier stated, Terraform is a multiplatform tool which means it can be used with several Cloud Providers, Terraform does this through the use of Application Programming Interfaces (APIs).

Syntax

Like every other programming language, the Hashicorp Configuration Language that Terraform uses has its syntax. It is a Domain Specific Language (DSL) that makes use of variables, loops, functions and conditionals to efficiently manage and provision IaC.

Variables in Terraform are type-sensitive similar to Typescript and Swift, it will throw an error if the types aren't declared and followed properly. There are 3 types of variables in terraform, each with its uniqueness;

  • Input variables: Generally for customization and parameterization, they add an extra layer of abstraction which leaves sensitive parameters to be added only at runtime.

  • Local variables: Are used to create intermediate values within a module to improve readability and maintainability and finally,

  • The Output variables: Utilized for exposing certain values or results from a module so that they can be easily consumed by other parts of the configuration. These values can be the returns of Instance IP addresses, Amazon Resource Numbers and the like.

For simplicity purposes, we will be applying Terraform with AWS in this piece.

Terraform State Files are an essential piece of its functionality. It stores useful information about the infrastructure that Terraform manages, allowing Terraform to understand the current state of the infrastructure and track any changes in the long run. The file is preconfigured to the name terraform.tfstate. The state file is created when Terraform is initialized and can be referenced using the terraform state command. However, they mostly contain sensitive data and will likely be encrypted.

The Terraform IPAD

The Terraform IPAD is an acronym I like to use to describe the usage sequence of Terraform. After writing terraform code and describing the resources you wish to provision, some commands are used to kick off your terraform configuration from the terminal, the same way you'd use a node app.js command to start your node server or a flutter run to run your app, the IPAD is used to sequentially deploy your resources to the cloud.

I initialaize --terraform init
P plan        --terraform plan
A apply       --terraform apply
D destroy     --terraform destroy

Each command executes a critical function in the Terraform process;

  • The terraform init command initiates a backend and prepares the state for the commands that will follow.

  • The second command; terraform plan queries your chosen Cloud Provider and checks for the current state of deployed resources, then compares it to the state about to be deployed in your terraform code.

  • terraform apply launches the resources into your Cloud Provider.

  • Lastly the terraform destroy command is available to tear down the resources you just provisioned, leaving your state clean as a whistle.


Meta-Arguments

Meta-arguments in Terraform are special arguments that are used to control the behaviour of the provisioning process. They are used within a module or resource to provide additional configuration options beyond the regular resource-specific arguments. A few popular Terrafoem meta-arguments are:

  • Depends_on: Specifies dependencies between resources. It ensures that one resource is created or updated before another resource. A good use case would be defining a policy for an Instance to use an S3 bucket.

  • Count: Controls resource instantiation by setting the number of instances created based on a given condition or variable.

  • For_each: Allows the creation of multiple instances of a resource from a single block. It is similar to the count meta-argument but offers more control and customization to be able to iterate over resources and perform desired actions.

  • Lifecycle: Defines the flow of the operations of specific resources. It can specify an immutable sequence of actions to a resource, inferring an order and placing required verifications on some actions such as but not limited to terraform destroy.

Adding these arguments to the resource code helps developers control the behaviours and flow of the provisioning protocol.

Modules

In Terraform, modules are a way to structure and envelop Terraform configurations into reusable and shareable components, you can think of it as a Docker Image. Modules allow you to abstract, customize, and segment your infrastructure code, promoting code reuse and maintainability. Terraform supports several types of module platforms including Github, the official Terraform Registry and Bitbucket amongst a few. The Terraform Registry is a centralized repository where developers can publish and share their modules. Modules play a crucial role in Terraform's infrastructure, and I highly suggest delving deeper into their functionality.

Formatting and Tests

Yes, Terraform incorporates testing and formatting in its structure. It covers a variety of lint, tests and checks for both built-in and external libraries.

Terraform supports the renowned Go testing library; Terratest and allows you to write tests to validate and verify your infrastructure code and configurations.

The terraform fmt command, for instance, is a built-in command used to run lint on code and structure our code to properly align with the HCL style format.

terraform validate checks to see if the configuration has correctly defined variables and dependencies.

It also entertains mocking, CI/CD testing and the like of it.

Hands-On

So far we've had a basic overview of Terraform, now let's proceed to implement a simple hello world example by launching an AWS EC2 instance with Terraform.

The prerequisites for this exercise are to have already installed Terraform on your local system and initiate it with your AWS IAM public and secret keys. I'll leave the link to a video with a detailed description of how this is done.

Meanwhile, in my main.tf file:

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

provider "aws" {
  region = "eu-north-1"
}

The code sets up Terraform with AWS as the Cloud Provider. It then declares the Terraform version that will be in use as well as the AWS region we will be launching into. Our next code block will declare the resource we wish to provision.

resource "aws_instance" "testTerraform" {
    ami = "ami-0416c18e75bd69567"
    instance_type = "t3.micro"
}

After specifying the entertains, we give a name to our instance; "testTerraform" and then move on to add the Amazon Machine Image (AMI) which is a Machine Image of the underlying Server’s Operating System. In this example, the AMI is a Linux Image that is set to provision a virtual Linux Server, you can reference the AWS Management Console to get the AMI for different Operating Systems.

Next, we set the instance type to a t3.micro which is more or less a general-purpose Instance type that AWS offers. Now we are all set to initialize Terraform and deploy our resources, to do so we will use the Terraform IPAD sequence;

  • Running the terraform init command in my VS code terminal will initialize the backend and leave the following output

  • The terraform plan command will review the resources I wish to provision.

  • terraform apply prompts me to verify the actions that are about to be executed, then deploys my code to AWS and launches our new instance.

    A snapshot from my AWS Management Console shows that the instance spun up nicely in just a few seconds.

  • Finally, terraform destroy tears down this instance but by default, you'll be required to verify this action as it cannot be reverted. It is advisable to remember this command, especially in development environments so as not to leave resources running and accumulate an unwanted bill.

As you can see, our Instance state changes from "Running" to "Terminated".

DISCLAIMER: Terraform isn't restricted to just Google Cloud, AWS and Microsoft Azure but covers a wide variety of other Cloud Providers such as Alibaba Cloud, IBM, Oracle Cloud Infrastructure and others.

This video contains an overall guide for using Terraform, from installation to initialization, deployment and more. It gets into the nitty-gritty of Terraform so I recommend you follow through with it if you're looking to get some real hands-on experience with Terraform as well as to further explore the use of modules in its infrastructure. And that’s a wrap for The Trinity; IaC with Terraform.