Reflections on IaC using Terraform

Terraform has emerged as one of the top open source infrastructure as code (IaC) tools, since its initial release by Hashicorp back in 2014.

The design philosophy behind the tool is to have declarative, and stateful representation for the underlying IT infrastructure (whether it be on public, on-premise, or hybrid cloud), which in turns simplify the control, collaboration, and auditing of the cloud resources.

The classical example to show the main idea creating a VM:

provider "aws" { }

resource "aws_vpc" "vpc" {
  cidr_block = "10.0.0.0/16"
}

resource "aws_instance" "this" {
  ami = "ami-026b57f3c383c2eec"
  instance_type = "t2.micro"
  tags = {
    Name = "New example instance"
  }
}

This is not limited to only compute resources, many of AWS services are available as well.

Simplified Workflow

The main workflow is conventionally as follows:

The flow maps cleanly to CLI commands:

terraform init
terraform plan
terraform apply
terraform show

Additional linting commands available as well:

terraform fmt
terraform validate

Disposal of resources is simplified as well (without authoring .tf manifests):

terraform destroy

Structure

It is recommended to factorize input values across environments into variable blocks.
This enhances for security posture as well, like protecting sensitive data.

Moreover, output blocks provide a way to capture and log information after applying state changes.

The minimal structure of managed resources in terraform is shown below:

$ tree
├── main.tf
├── outputs.tf
├── terraform.tfstate
├── terraform.tfstate.backup
└── variables.tf

The variables and output files are separated to organize things up.

The state is tracked in .tfstate file, and managed internally by Terraform.

Providers

The mechanism behind provisioning the intended state of an infrastructure or platform, is performed on by “providers”. They are terraform extensions written in Go language exposing the resource types they implement, and interfacing with the target infrastructure / platform APIs.

provider "aws" {
  region = "us-east-1"
}

The major providers are available on the public terraform registry, along with many platform agnostic plugins, such as Helm and Kubernetes.

Here’s an example for a simple helm releasing technique:

provider "helm" {
  kubernetes { }
}

resource "helm_release" "redis" {
  name       = "redis-instance"

  repository = "https://charts.bitnami.com/bitnami"
  chart      = "redis"

  set {
    name  = "architecture"
    value = "replication"
  }
}

Terraform v.s. Ansible

Compared to Ansible as an orchestration tool on the infrastructure layer, I find that Terraform overall is more expressive and concise to enable building on modules in much elegant and feasible manner, with the excellent readability of HCL and dependency management of plugins.

The state is a major difference to consider here.

Ansible takes a stateless approach by always exchanging the desired state with the target resources in order to know the actual state then apply the delta, if needed. On the other hand, Terraform is stateful and manages the state in local or remote manner.

Summary

All in all, codifying infra and platform layers (e.g. using terraform) can bring key benefits to organizations in adopting the DevOps practices, leading to operational excellence, eventually.

Comments