Terraform First Impressions

Hello dear readers!

It’s been a while since I wrote some stuff over here. So it’s about time.

This time I’ll write about AWS and Terraform!


Terraform offers a modularized way to deploy your infrastructure. It offers a lot of providers that you can leverage in order to deploy on AWS, Azure, Google Cloud and other Cloud providers.

It offers a zero-installation approach composed of 1 single executable file that you can run wherever you need it. I copied that to a location that is already in my PATH so that I could call it from anywhere in my workstation.

The so-called modules are basically the building blocks for our infrastructure. You can have them as decoupled as you want or as big as a full stack. Both approaches have pros and cons you’ll have to consider when making a decision on how to code your infrastructure.

The Terraform Mythos

Myth #1. “Terraform is platform agnostic”

False! While it allows you to use a ton of different providers, if you want the same infrastructure on different providers you’ll need different code for each provider. So, there’s no such thing as a high level Infrastructure Code that can be “translated” by Terraform depending on the provider.

Let’s go over the simpler example.

Let’s create a VPC on AWS, Azure and Google Cloud

For each Cloud provider, resource “types” are absolutely tied to the provider, making terraform only a “common” language to describe cloud objects, but always using the provider’s names for those objects.

Google Cloud

# --- Google Cloud ---
resource "google_compute_network" "example" {
  name = "example_network"
  auto_create_subnetworks = "true"

AWS requires stuff ike a cidr_block, and if you fail to provide  it, Terraform will faill and tell you that you need to give it a cidr_block.

# --- AWS VPC ---
resource "aws_vpc" "example_vpc" {
  cidr_block = ""
  instance_tenancy = "dedicated"
  tags {
    Name = "example_vpc_name"

AWS has it’s own resource for subnets. See below that Azure requires the subnets added in the same resource which is not even close to the AWS “version” of the code

# --- AzureRM VNresource "azurerm_virtual_network" "network" {
  name = "production-network"
  address_space = [""]
  location = "${azurerm_resource_group.network.location}"
  resource_group_name = "${azurerm_resource_group.network.name}"

  subnet {
    name = "subnet1"
    address_prefix = ""

  subnet {
    name = "subnet2"
    address_prefix = ""

  subnet {
    name = "subnet3"
    address_prefix = ""

Myth #2 Terraform can track changes

True! Terraform indeed can track changes as long as it has a special file with the .tfstate extension where it is run.

Myth #3 Terraform is open source

True and False! To some extent, yes, it is open source. Nevertheless it has it’s “Enterprise Edition” which features are not generally available.

The real deal

Once we have a full overview of what we can do and what we can’t, let’s talk about it.

Terraform will allow you to manage your Infrastructure as Code in an easy way provided that you maintain your code organized. For this, I would highly recommend reading some documentation over in https://www.terraform.io before engaging in any coding at all.

Terraform has some great advantages like: it won’t make any changes unless you say “YES” literally.

I would also recommend to have a folder structure that allows you to simplify identifying your deployers and modules easily.

-- <provider>
-- -- <environment>
-- -- -- <deployer>
-- -- -- -- <deployer>_main.tf
-- -- -- -- <deployer>_outputs.tf
-- -- -- -- <deployer>_provider.tf
-- -- -- -- <deployer>_variables.tf
-- -- -- -- terraform.tfvars
-- -- -- modules
-- -- -- -- <module name>
-- -- -- -- -- <module name>_data.tf
-- -- -- -- -- <module name>_main.tf
-- -- -- -- -- <module name>_outputs.tf
-- -- -- -- -- <module name>_variables.tf

Where the <> stand for:

  • <provider>: The actual provider to use
    • {aws | azurerm | alicloud | google | … }
  • <environment>: In the case you manage more than a production environment
    • { development | uat | stress-test | qa | … }
  • <deployer>: The module orchestrator for deploying your infrastructure fully or partially complete
    • { network | security | database | ec2_instance | … }
  • <module name>: The module name which is somewhat tied to the provider
    • { vpc | security_groups | ec2-instance | autoscaling_group | … }

And the files have the following contents:

  • *_data.tf: Here you query your provider to give you information on existing infrastructure
  • *_main.tf: Here are the infrastructure resources to be created/updated
  • *_outputs.tf: Here, the output “variables” are defined, so that the <deployer> can pass them as variables to other modules.
  • *_variables.tf: Here, the variables are defined, and even default values can be passed to avoid missing important information.
  • terraform.tfvars: This file contains hardcoded data. It shoulden’t be sensitive information as it’s in plain text. Also is highly recommended to avoid putting this file in git or any other version control system.

How does it work?

Simple. Download aws-cli and terraform. Configure aws-cli and then terraform init after you have a very small “infrastructure” to test.

Then the steps will be:

  1. terraform init: Get the provider plugins and check the code
  2. terraform plan: connect to the provider and check what the state of the infrastructure and what has to be done
  3. terraform apply: make the changes happen.

Last words

My advice is that you give it a try. You already have more knowledge than I when I first started testing it.

I will post some more about mixing Terraform with other tools for automation in the future.

Go and have fun! Happy Terraforming!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s