Convert AWS CloudFormation Template For a Highly Available Web Server To Terraform Script

Convert AWS CloudFormation Template For a Highly Available Web Server To Terraform Script

I tried out Terraform for the first time in one of my previous posts and since nothing beats learning by continuously doing, I decided to convert a CloudFormation script I wrote to "deploy infrastructure for highly available applications" to its Terraform version.

Remember this post? Yeah, the CloudFormation script from this project.

The project was mainly to understand (and practice) what to consider when deciding between high availability of applications vs. optimising costs, and how that translates to the architecture.

Prerequisites: Have Terraform Open Source installed.

Steps to Convert CloudFormation templates to Terraform scripts

There are three main steps after creating and writing the configurations but I'll be highlighting every other step as well.

  • Structure the folder

The project uses the modules/folder structure because real-world projects will typically be structured that way. I created sub-folders like setup, security, etc to create separate files with the configurations for each section.

As highlighted above, each folder had at least its main.tf, outputs.tf and variables.tf files.

  • Convert each resource declaration to terraform syntax

This is where I spent the most time; there are several resources provided by the Terraform team to learn about different aspects of the tool; language syntax, CLI commands, providers' documentation, etc. I also encountered several errors and got some clarifications from reading the documentation.

The final configuration files can be found in this repo.

Link to the CF template

And now to the "main" steps:

  • Initialise the working directory

The directory that contains the configuration files defined above must be "initialised" before Terraform commands can be used to perform any operation. This is done with terraform init and this pretty much sets up the folder with all the necessary configurations Terraform needs.

  • terraform plan and terraform apply

The plan command generates a preview of the updates to be made (this can be saved in .tfplan file.

P.S it can be saved in files other than the default tfplan but those require extra configurations that may be unnecessary.

One of the issues I encountered during this step was associating route tables with subnets. Unlike AWS CloudFormation where I had to create each subnet individually (hence having direct access to the individual subnet_id), Terraform provides meta-arguments like for_each that can be used to create similar subnets with just one configuration.

However, it becomes difficult to directly retrieve the subnet_ids and use them in another for_each for creating the matching route-table associations.

As suggested, a workaround would be to use the -target option to apply just the setup module before proceeding. This is not recommended as highlighted in the docs so I created the resources individually instead since the values I needed could not be defined statically beforehand. That did not seem efficient so there would most likely be another way.

Workaround #1:

terraform plan -out=tfplan -target=module.setup
terraform apply tfplan -target=module.setup

Workaround #2:

Let me know if you have another way of doing it!

Afterwards, run the commands as normal, and test:

terraform plan -out=tfplan
terraform apply tfplan

Don't forget to delete your resources after you are done!

The command terraform destroy is the equivalent of deleting CloudFormation stacks.


The deployment can also be automated using a CI/CD tool so that's what I'd be trying out next!