michelangelus - Fotolia


Implement these best practices to run Terraform with AWS

Infrastructure as code on AWS can introduce a learning curve, but tools, such as Terraform, can help enterprises meet their IaC goals.

Infrastructure as code -- if appropriately implemented -- dramatically changes the way automation engineers, system administrators and software developers provision infrastructure resources. Once organizations start to dig into the concept, one of the first tools they'll come across is Terraform by HashiCorp.

Terraform is an IaC tool designed around a domain-specific language that can define one or more infrastructure components in a set of plain-text configuration files. Terraform reads these configuration files, compares them against an environment and either reports the necessary changes to sync configurations or performs the actual changes.

There's no one right way to perform tasks in Terraform with AWS, but users should be mindful of some best practices.

Terraform and AWS

Terraform uses what are called providers to interact with resources and translate configuration files into a specific system's API language. In this case, provider shouldn't be confused with vendor, though there is overlap. It generally refers to the code that connects Terraform to a particular cloud-based or on-premises service.

The AWS provider is one of the most popular Terraform providers. It translates Terraform configurations into the various API calls for the supported AWS products. DevOps teams use the AWS provider to designate various options in the Terraform configuration files, which can then define the look of one or more AWS infrastructure components.

Use an AWS credential profile

To set up Terraform with AWS, users provide credentials to Terraform via an Identity and Access Management key and secret key. The easiest way to do this is to hardcode the access key and secret key in plain text inside of the configuration file, but for security reasons, it's best to separate configuration information from the execution code.

Use the AWS credentials file to handle credentials. The default location is $HOME/.aws/credentials on Linux and OS X or %USERPROFILE%.aws for Windows. Terraform will look for this credential file and use these encrypted values when it accesses the AWS provider.

Users can either depend on Terraform to automatically look for the credentials file or specify it with the shared_credentials_File attribute:

provider "aws" {
  region                  = "us-west-2"
  shared_credentials_file = "/Users/tf_user/.aws/creds"
  profile                 = "customprofile"

Break up AWS configurations

Teams likely provision more than one service -- an EC2 instance, security boundary, Elastic Container Service cluster, etc. -- when they use Terraform with AWS. They could define all of these services in a single configuration file, but this would eventually become difficult to manage. Instead, break up configuration files into microservices to piece them all together at runtime.

In addition to the configuration files, Terraform also provides modules to reuse code among multiple teams' configurations. Teams would typically use this feature to create a custom EC2 module that sets the default configuration needed for their company. Constantly look for patterns, and continually evaluate if a separate module or configuration file is necessary. If you repeatedly create the same configurations or copy and paste the same code to complete the same tasks in different configurations, consider the shared module.

Use variables

Users can also build and modularize Terraform configurations with variables. First, they must determine what could change in their AWS configurations, such as their AWS region. For example, one day, you may need to be in US-East-1 but need to change to US-East-2 the next. Rather than hardcode the region inside of a configuration like this:

provider "aws" {
  access_key = "<ACCESS KEY HERE>"
  secret_key = "<SECRET KEY HERE>"
  region     = "us-east-1"

Instead, define a variable in the main.tf file called region:

variable "region" {
  default = "us-east-1"

Plan changes before they're applied

A task that fails due to a manual error only does so once, but it's exponentially worse when that failure is repeated hundreds or thousands of times. Luckily, Terraform has a plan action to confirm what will happen before any changes.

Always use the plan action with the terraform plan command before applying any changes. This example shows what Terraform wants to change based on a user's configuration values:

+ aws_instance.web
      id:                           <computed>
      ami:                          "ami-xxxxxxx"
      associate_public_ip_address:  <computed>
      availability_zone:            <computed>
      ebs_block_device.#:           <computed>
      ephemeral_block_device.#:     <computed>
      get_password_data:            "false"
      instance_state:               <computed>

Users can run the terraform apply command to actually implement those changes once they're OK with the proposed changes.

Next Steps

How to launch an EC2 instance using Terraform

How to deploy an EKS cluster using Terraform

Dig Deeper on AWS infrastructure

App Architecture
Cloud Computing
Software Quality