Advanced Tips & Tricks to Optimize your Terraform Code
Deployment and management infrastructure day-to-day isn’t an easy task. In this post, I’ll discuss how we can accomplish this using Terraform in AWS and my hope is that this post will bring in more confidence in using Terraform and open up possible approaches and solutions. I will demonstrate how to build complex infrastructures and how to avoid duplication in code using loops. My example will be focused on Amazon Web Services (AWS), but all the information should apply to other clouds as well.
Terraform is a tool created by HashiCorp that allows you to:
- describe your infrastructure as code
- outline exactly what will happen when you run your code
- builds a graph of your resources
- create and change your infrastructure with minimal human interaction.
Terraform is platform-agnostic and you can use it to manage bare metal or cloud servers — like AWS, GCP, OpenStack, Azure, etc...
Terraform uses a declarative language, called HashiCorp Configuration Language (HCL), to define an infrastructure. This allows for a cleaner, more authentic view of what is being deployed.
Specific types of tasks, like loops and if-statements, could become extra painful since declarative languages usually don’t have loops. With that in mind, defining multiple resources that are similar could end up looking like this.
The loop is used to eliminate the workload in terms of programming and for faster execution without consuming extra time coding.
Is there a better way?
Almost every Terraform resource has a metadata parameter. “count” is one of the parameters which simplifies configurations to scale your resources by simply incrementing a number. In the example below, I am using the function “length()” to calculate the number of values in my list.
What if you wanted to give each resource a unique name?
To accomplish this, you can simply use “count.index”.
I will show you how to optimize code with multiple examples of count and splat expression for the diagram below and provide you with the code.
For the code to work, minimum pre-requirements must be met:
- Terraform version >= 0.11.7
- AWS Account with the right level of permission
- Visual Studio Code or Sublime
The following layout is typical of what you find in many data centers with DMZ (Public) & Internal (Application and Database)networks. This diagram is a cloud agnostic 3-tiered solution which has public, application, and database subnets in multi availability zones. I will also show how I used splat expressions to configure Auto Scaling for Bastion host.
The Network topology above display of what will be implemented:
- VPC
- Subnets
- Availability Zone
- NAT Gateway
- Route Tables
- Security Group
- Internet Gateway
- Auto Scaling Bastion host
Code Review
Global variables
- Self-explanatory
Input Variables
- I am declaring input variables. Please note that “availability zones” is a list variable containing three values.
Subnets & Zones
- I am using the meta parameter “count”. The meta parameter is available for all resources in Terraform. In this case, I am using the “length()” function combined with the availability zone list, which equals three.
- The built-in “element()” function is also being used to have to subnets in use a different availability zone.
- Furthermore, I am using the “cidrsubnet()” function to calculate a CIDR block for each subnet.
NAT Gateway
- I am creating NAT Gateways in each public zone using the function “count”, “count.index”, “element()” and splat expression to reference public subnets & EIP.
Route Tables
- While creating route tables, I am using splat expression to reference subnet created previously by Terraform.
- Also, you will find an example of how “count.index” can be used for tagging resources.
Autoscaling Group
- In the autoscaling group configuration, I am using splat expression to reference public availability zones.
Output
- Once again, I am using splat expression to output variables as a way to organize data to be easily queried and shown back to the Terraform user.
This video demonstrates how I deploy Terraform code. Provisioning Network Infrastructure:
To see how I just as easily destroy these resources created by Terraform:
Outcome
In this post, we saw how we could use some built-in functions in Terraform to easily make and flexibly create and scale our infrastructure, with many more tricks to help us achieve this. It is important for maintainability, infrastructure as code cleanliness, and flexibility. For the code I have demonstrated here, you can find in my GitHub repository.