How to leverage Infrastructure as Code with AWS and Terraform

As more organisations continue their evolving cloud journey in 2019, many will begin to learn the concept and benefits of "infrastructure as code", or IaC for short.

IaC is a method to define, build and deploy vast environments within a few minutes. IaC files are easily readable, extremely portable and often serve as a documentation tool for IT administrators. Each cloud platform provides a separate IaC tool: Azure uses ARM templates, AWS uses CloudFormation and Google Cloud uses Deployment Manager.

Infrastructure as Code effectively manages your business environment through machine-readable scripts or definition files, rather than through manual processes. IaC models uses code and automation to deliver the desired state of environment consistently and securely at scale, eliminating traditional security risks from human error.

So, why should you care about IaC? For starters, Infrastructure as code tools have multiple advantages for almost all cloud management and IT efforts:

  • Deployment becomes repeatable and consistent, making it easier to redeploy your cloud environment in any scenario
  • IaC is self documenting, meaning if you can read a template, you can understand what should be in your cloud environment
  • Faster deployment timelines as engineers can share templates for specific resources, saving huge amounts of build time
  • You can delete resources with confidence and bring them back the moment they are needed
  • You can version control your environment, using a source control service like Git which enables you to rollback to an older environment fast

While all three IaC tools for each cloud platform have similarities and huge advantages, each product is specific to a respective platform. You can't deploy a CloudFormation template to Azure and you need to know the differences between the two to convert them. For many admins, understanding multiple languages is time consuming.

Thankfully, there is a new solution which simplifies this process and makes unlocking IaC's benefits more accessible.

 

What is AWS Terraform?

To solve IT administrators nightmares, Hashicorp has been kind enough to develop Terraform - a multi-cloud, multi-platform IaC tool.

In a similar manner to the other IaC tools, Terraform uses configuration files to define, deploy and destroy cloud infrastructure. To make the product even more juicy for admins, Terraform supports multiple cloud and on premise services. Your IaC files can easily be converted for on premise deployment and expanded to support different platforms - AWS, Google Cloud, Microsoft Azure, and more. 

Terraform files are written using Hashicorp Configuration Language (HCL). You might have just groaned at the thought of learning a new language, but you don't need to stress - it's pretty similar YAML markdown. Terraform files can be broken down into three main components; Providers, Variables and Resources.

  • Providers are utilised to detail what environment types you need (eg AWS/Azure/GCP)
  • Variables are used to set a value once and use it throughout a file
  • Resources are what will be deployed into your environments

Once a Terraform file is deployed, a state file is created detailing the current configuration and you can provide a tfvar variable file for variable input into a template. 

 

How to I setup Terraform?

One of my favourite features of Terraform is the ease with which you can get started.

Simply download the product and then add the binary to your environment path. If you want to test it out first, download the files and open a command prompt at the download location. Once ready to go, type Terraform in your command line to test.

 


There is a fair few options shown above and available to run with Terraform - we will only cover a few in this blog.

 

Writing Terraform Files?

Now that we have setup Terraform for use its time to write some code.

First, declare the provider you require - We're going to start with AWS, and use this public cloud provider to deploy some networking infrastructure and an EC2 instance. 

provider "aws" {
  access_key = "YOURAWSACCESSKEY"
  secret_key = "YOURAWSSECRETKEY"
  region     = "us-east-1"
}

Should you need to configure a new AWS access and secret key you can find documentation on this process here. You can probably already tell that Terraform configuration can be a lot less wordy than its platform-specific counterpart. Next, we will deploy some resources: I want a VPC, some subnets and an EC2 instance. 

resource "aws_vpc" "myVPC" {
 cidr_block = "10.1.1.0/24"
}
 
resource "aws_subnet" "VPCSubnetOne" {
 vpc_id = "${aws_vpc.myVPC.id}"
 cidr_block = "10.1.1.0/25"
}
 
resource "aws_subnet" "VPCSubnetTwo" {
 vpc_id = "${aws_vpc.myVPC.id}"
 cidr_block = "10.1.1.128/25"
}
 
data "aws_ami" "ubuntuAMI" {
 most_recent = true
 filter {
 name = "name"
 values = ["ubuntu/images/hvm-ssd/ubuntu-trusty-14.04-amd64-server-*"]
}
filter {
  name = "virtualization-type"
  values = ["hvm"]
}
 owners = ["099720109477"] # Canonical
}
 
resource "aws_instance" "MyVM" {
 ami = "${data.aws_ami.ubuntuAMI.id}"
 instance_type = "t2.micro"
 subnet_id = "${aws_subnet.VPCSubnetOne.id}"
}

You should notice each resource does have a list of available options and this changes depending on what you're deploying.

I normally keep the Terraform providers reference open when writing files, as it's a helpful tool to check what settings are available. 

If you're interested in seeing the similarity between Azure & AWS deployment on Terraform, I've published some example templates to Github. 

Checking your deployment code & Terraform state

Once you have completed your Terraform code, you can complete a test of the files using Terraform plan.

This command will allow you to see in advance what actions Terraform will take. 

There is a fair bit of output produced, so I've removed some from the provided screenshots just to show the functionality at a high level.

<Redacted for brevity>

 

Whenever discussing Terraform deployments or plans, its extremely important to understand Terraform state. This is a reference file for anything you have deployed using Terraform. If you begin to work on a Terraform project, all your plans and deployment actions will be influenced by this data. State can be a tricky thing to manage when working in teams, requiring storage in a central location.

If you have a look at the following plan, you will notice that there is no changes to be deployed. This is because my current state file matches the resources I've deployed within AWS. I personally find this extremely useful when writing Terraform files, as I can test as often as I like and only see the changes that I'm actually writing in my files

 

Making your changes

Now that you have validated your files using Terraform plan, it's time to deploy. Again, this is super simple:

Terraform apply

You should get an up to date plan with the changes to be applied and be prompted to confirm your actions.

<Redacted for brevity>

<Redacted for brevity>

 

A quick look at my AWS dashboard confirms a newly created EC2 instance!

 

 

Introduction to Terraform: Next steps

Hopefully you now have a high level understanding of how Terraform works and how you can use it within your environment.

There are also a couple of simple files using the providers for AWS, Azure and a combined file to demonstrate ways to deploy across cloud. Like all good engineers, my secrets have now been stripped out - and you will need to reference the documentation for setting up your own environment.. 

Stay tuned for the my next blog where I cover the basics of Azure Monitor and building custom dashboards within your environment.