Beginners Guide to Terraform

Shanmuganathan Raju
9 min readMay 17, 2022

Terraform is an open source infrastructure as code (IaC) software developed by Hashicorp. It is used by engineers to codify their infrastructure — write code to create their infrastructure. Terraform is used to manage on-prem servers, cloud resources and software by writing configuration files.

Summary of topics:

  • How Terraform works
  • Benefits of using Terraform
  • Basic Terraform concepts
  • Installing Terraform
  • Creating an EC2 instance from Terraform

Hashicorp Configuration Language (HCL) is used to write code for Terraform to create and manage infrastructure. HCL is designed to be easy to read and write by humans and provides a declarative interface to define infrastructure.

Terraform is based on a plugin architecture. It consists of two components: Terraform Core and Terraform plugins. The Terraform CLI makes up the core, whiles providers are downloaded as plugins when required. This ensures Terraform (core) is lightweight and other features (plugins) are downloaded only when required.

The Terraform CLI (core) :

  • reads and interprets HCL
  • builds dependency graphs for resources to be managed
  • plans execution of IaC code and communicates with plugins via RPC.

The plugins (providers and provisioners) extend the functionality of Terraform. They interact with providers(cloud services, SaaS applications etc.) via APIs to manage resources on behalf of the developer.

Source: Terraform Documentation

Terraform uses a declarative approach to managing infrastructure. This means you describe the desired end-state of your infrastructure and Terraform ensures your infrastructure is always in the state defined. This is contrary to the imperative approach, where you enter commands or interact with UI to perform one task at a time.

At the time of writing this post, Terraform has 1990 providers. This means, you can codify infrastructure resources for 1990 different cloud providers, SaaS, local utilities and other services with APIs. If there is an infrastructure service with no Terraform provider yet, you can write your own provider and use the Terraform to manage it.

2. Simplify multi-cloud deployments

Terraform simplifies multi-cloud deployments. It provides engineers the same workflow for interacting with all cloud providers. Every cloud provider has their own interfaces and tools for deploying workloads on their cloud. Instead of using different tools to provision and manage different cloud services, you can use Terraform to manage them all.

When you use Terraform, you follow the same workflow for all your deployments because Terraform now communicates with all these providers on your behalf.

3. Write once, deploy multiple times

It is a known fact that IaC saves you a lot of time with deployments (in the long run). You spend time writing your templates and you can reuse it many times to deploy the same workloads even in different environments.

You could also use the same template to provision different kinds of the same infrastructure. For example, you could use the same template to provision either a t2.micro EC2 instance or a m5.large EC2 instance. You may specify the instance type as a variable.

Modules in Terraform can be reused across projects and organizations. Modules allows you to package multiple resources that are frequently used together and re-use them in your configuration.

4. Collaboration

Terraform fosters collaboration. Teams practicing devops may work on the same configuration using the same version control workflows they use in writing applications. Team members can make updates to configurations and track changes.

Terraform Cloud and Terraform Enterprise allows teams to use Terraform together. It runs Terraform in a secure remote environment other than an individual’s computer. Team members can view the state of their resources and share secrets and configuration. Teams may also publish modules and providers to their own private registry. Lastly, infrastructure policies can be written as code and enforced.

Providers

Terraform interact with cloud providers and SaaS applications using providers. Providers are plugins that are downloaded when referenced in a Terraform configuration. Providers are hosted in Terraform’s public registry or private registries in Terraform Cloud/Enterprise.

Every Terraform configuration has at least one provider. To use a provider, you need to provide the local name, source and version of the provider.

Resources

Resources are used in Terraform to describe infrastructure objects like EC2 instances or persistent disks in Google Cloud. Terraform uses providers to provision and manage resources.

Every resource has a type and a name. The type tells Terraform which provider to use and the provider what resource to create. The name is used to refer to the resource in other parts of the configuration. Arguments are used to configure resources. Examples of resource arguments are instance type, availability zone and key pair name for AWS EC2 instances.

State

Terraform stores the state of the configuration and managed infrastructure (remote resources) in the state file locally or remotely. State is used to map configuration to the deployed resources from that configuration and keep track of resource metadata.

Before any Terraform operation, Terraform checks the current state of managed resources and updates the state file to match it. The state file is used when changes are made to infrastructure and it is updated after any change.

MacOS

From your terminal, install the Hashicorp tap

brew tap hashicorp/tap

Install Terraform

brew install hashicorp/tap/terraform

Verify your installation

terraform -help

Windows

  1. Download the Terraform binaries from here . Choose 386 for-32 bit computers and amd64 for 64-bit computers
  2. Extract the binaries (zip archive) to a desired location and copy the path to directory containing the Terraform executable eg. C:\Users\ekoomson\Downloads\terraform_1.1.7_windows_amd64
  3. Add the directory Terraform executable is located to your PATH. Using command prompt enter the below commands to add to your system’s path
setx /M path "%path%;C:\your\path\here\"

or the below command to add to your current user’s path

setx path "%path%;C:\your\path\here\"

4. Check the Terraform version to confirm the installation. Open command prompt and enter the below commands

terraform version

Linux (Ubuntu)

Download public key and add to your system

curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/terraform-archive-keyring.gpg

Add Terraform repository to Apt sources

echo deb [signed-by=/usr/share/keyrings/terraform-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main | sudo tee /etc/apt/sources.list.d/terraform-stable-debian.list

Update package lists and their dependencies

sudo apt-get update

Install Terraform

sudo apt-get install terraform -y

Check if Terraform is installed

terraform version

Prerequisites

You will need the following to be able to create your first EC2 instance using Terraform:

  • AWS Account
  • AWS Credentials — Learn how to create an IAM user from here
  • Terraform CLI which we just installed

Configure your AWS CLI

Run the aws configure command on your terminal and provide your credentials as seen below.

Write your code

We now know a little something about Terraform. In this section, we apply the concepts we have learnt by writing a Terraform configuration to create an EC2 instance.

The basic Terraform workflow starts with writing our infrastructure code, initializing Terraform and creating the infrastructure using Terraform CLI. In our case, we would validate the code as well as previewing the infrastructure resource to be created.

Below diagram shows a Terraform workflow.

Source: Hashicorp Learn

Now, let us write our code.

Create a file, name it main.tf and copy and paste below code into it.

Understanding the code

Terraform configuration is written in HCL. It organizes different components into modules(blocks) making it easy to read. Our code consists of three blocks: Terraform block, provider block and resource block.

The Terraform block contains information about the providers to be used this configuration. Provided to be used in a configuration are listed in the required_providers block.

A local name is given to each provider, the local name can be referenced in any part of the configuration. Note that you may give a provider any name of your choice, but providers have preferred local names. The preferred local name of our provider is aws .

For every provider declared in the Terraform block, a source and version must be provided. The source for our provider is hashicorp/aws. The source address consists of hostname, workspace and type, all delimited by slashes.

Providers hosted on Terraform’s public registry can omit the hostname portion of the source address. Our provider only has the workspace and type portions, hence Terraform downloads it from the public registry. From the source address, we can infer that, the provider is hosted in the hashicorp workspace (written by Hashicorp) and the provider type is aws (the preferred local name).

We also notice a version is defined for our provider. The version tells Terraform which version of the provider to install when Terraform is initialized. The version constraint = ~> 4.5.0 ensures that only new patch releases for version 4.5 will be installed anytime Terraform is initialized for this Terraform code.

The required_version setting specifies which versions of Terraform CLI can run this configuration.

Some providers required additional configuration. The configuration information are declared in the provider block. For our provider, we stated the AWS named profile (configured with AWS CLI)to be used for interacting with AWS APIs and the default AWS regions to create resources.

This section defines the AWS resource to create. The first parameter aws_instance tells Terraform to provision an AWS EC2 instance. The second parameter first_server is the local name of the resource, like a variable name. It may be referenced in other parts of the configuration.

We provided an AMI ID — which is specific to the region we want to create the resource and the instance type. We also provided two tags: Name and Purpose.

You may define as many resources in a Terraform configuration, as far as the provider has been defined.

Using Terraform commands

Before deploying our resource, we can use the terraform fmt command to rewrite our Terraform configuration into a canonical style and format.

The first step to deploy managed resources in Terraform is to initialize Terraform in our working directory. In our case, the folder containing our main.tf file.

We initialize Terraform by running below command.

terraform init

When we initialize Terraform, it looks for the provider plugins from the Terraform registry hostname specified in the source address and downloads it into the .terraform directory in the working directory. Alternatively, Terraform can be configured to search for providers locally.

After installing the provider plugins, Terraform writes the location of installed providers and other metadata in the .terraform.lock.hcl lock file. Subsequent initializations update the lock file.

After initializing Terraform, its a good practice to check whether the configuration is syntactically correct. We use the below command.

terraform validate

To preview the changes we want to make with our code, we run the below command. When terraform plan is run, Terraform checks the state file against the remote resources it represents (if any) to make sure it is up to date. Terraform also checks it against the prior state and proposes changes or new resources to be created.

terraform plan

Finally, we can create our EC2 instance. When terraform apply is run, Terraform informs us of changes to made( or new resources to be created) and prompts for an approval. Terraform also provides updates on resource creation and outputs values if you configured any.

terraform apply

We can now view the instance we created from Terraform with the below command. Replace the <instance-id> with the instance id from your output. Also replace the <aws-region> placeholder with the region specified in the Terraform configuration.

aws ec2 describe-instances --instance-ids<instance-id> --query "Reservations[*].Instances[*].{PublicIP:PublicIpAddress,Type:InstanceType,Name:Tags[?Key=='Name']|[0].Value,Purpose:Tags[?Key=='Purpose']|[0].Value,Status:State.Name}" --region <aws-region>

We can also view the same information and more from the Terraform state of the managed resource using the terraform show command.

Human readable Terraform state

Clean up

To remove all resources created from a Terraform configuration, use the below command and Enter yes when prompted to approve the action.

terraform destroy

You can read more on how to destroy resources in Terraform from here.

Originally published at https://medium.com on May 17, 2022.

--

--

Shanmuganathan Raju

A Multicloud Architect, with more than 16 years in the information technology industry with experiences in architecting, solution designing and Cloud Migration.