Terraform: Using Variables And Count

Cleaning up my AWS Three-Tier Architecture Deployment part 1

In a previous post, Terraform: Deploy A Three-Tier Architecture in AWS, I used Terraform to create AWS infrastructure, however I did not use Terraform recommended best practices. I used a single main.tf file and hard-coded everything. As I’m just beginning my journey with Terraform, hopefully this can be forgiven. In an attempt to make up for my past sins, I plan to convert my original project using the best practices that I neglected the first time around. I plan to do this in stages and for this post I’ll be adding variables and count.

Please refer to my previous post for some basics on Terraform and a more detailed walk through of my original Terraform file. In this post I plan to go over a few examples of the changes I’ve made, but I won’t be going over each individually. Generally the examples I’m going over are applied throughout the file. As I said earlier, I plan to modify my original project in stages so this will not incorporate all the best practices that I want to add and I’m sure there are things I could improve on. If you’d like to skip this and go straight to the code please scroll to the sections below or visit my GitHub.

Please note that I have chosen to not have the ports use variables. At this time I feel that the port numbers should not be changed and because of that see no reason to turn them into variables. As I dive deeper into Terraform this may change, but for now that is my reasoning.

Input Variables

The Count Parameter

VPC Code Block

The following will be added to a variables.tf file. Notice that we are setting a description so developers know what the variable is for, a type so developers know what type of input is used, and a default of “10.0.0.0/16”.

Now we go back to main.tf and update the cidr_block from hard-coding 10.0.0.0/16 to var.vpc_cidr. When this resource is referenced when applied, it will look for the variable vpc_cidr which we created in the previous step.

Web Subnet Code Block

Once again we are going to update the variables.tf file. Rather than making a variable for each Availability Zone and a variable for each Web Subnet CIDR, giving us a total of four variable blocks, we will create two variable blocks with lists for their defaults.

When we add our variables we can reference the variable list index numbers to get our desired variable. For example our var.availability_zone_names[0] will return the first list item in the variable “availability_zone_names” block, which is “us-east-1a”. Remember that indexes start with 0, so the first item in a list has an index of 0 and the second has an index of 1 and so on.

Adding variables helps clean up our code a little but we can still do more. We are still using two resources that are very similar except for the CIDR and Availability Zone. That’s where count comes in. When we add a count, it will basically loop through the number of times specified. Here we added a count of 2. When it loops through the first time the count.index will be 0 pulling the first item in each of the variable lists. For the tags we use ${ } because they are needed when using count.index in a string. Here we want the tag name to be Web-1 and Web-2. Since indexes start with 0, we add 1 to the count.index to return 1 & 2 instead of 0 & 1.

I’ve applied similar changes to the rest of the file and won’t go into detail for those.

RDS Code Block

To change everything over to variables we use a map(any) type. This will allow us to quickly create all the needed parameters rather than making a variable block for each. If you notice I set up two variable blocks. One for rds_instance and another for user_information. This is because the user_information contains our username and password for the RDS instance which has been marked as sensitive. This will prevent the information from being displayed in the output. To ensure these sensitive values are not uploaded to a public repo, you may want to move them to a terraform.tvars file.

To access the mappings from the rds_instance and user_information variables we will use the following configuration: var.<variable name>.<map key value>.

Full Code

provider.tf

outputs.tf

variables.tf

main.tf

DevOps Engineer | AWS Certified Solutions Architect - Associate | Terraform Associate | Python | Linux