Before the advent of cloud and DevOps, most companies managed and deployed their infrastructure manually. This used to be risky because not only was it error-prone, it also slowed down the entire infrastructure cycle. The good news is that now, most companies are not deploying infrastructure manually but instead using tools like Terraform. In this blog, we are going to cover Terraform and the use of terraform modules.
Introduction to Infrastructure as Code(IaC)
The key idea behind Infrastructure as Code(IaC) is to manage almost âeverythingâ as code, where everything involves your servers, network devices, databases, application configuration, automated tests, deployment process, etc. This consists of every stage of your infrastructure lifecycle, starting from defining, deploying, updating, and destroying. The advantage of defining every resource as IaC is you can now version control it, reuse it, validate it and build a self-service model in your organization.
Intro to Terraform and how it fits into IaC space
Terraform is an open-source tool written in Go language, created by HashiCorp and is used to provision or manage infrastructure as code. It supports multiple providers like AWS, Google Cloud, Azure, Openstack, etc. To know about the complete list of providers, check this link:https://www.terraform.io/docs/language/providers/index.html
Now that you have a brief idea about Terraform, let's understand how Terraform fits into IaC space and how it's different from other tools(Chef, Puppet, Ansible, CloudFormation) in its space. Some of the key differences are:
- Ansible, Chef, and Puppet are configuration management tools(used to push/pull configuration changes), whereas Terraform is used to provision infrastructure. Conversely, you can use configuration management to build infrastructure and Terraform to run configuration scripts, but that is not ideal. The better approach is to use them in conjunction, for example, Terraform to build infrastructure and then run Puppet on the newly built infrastructure to configure it.
- The next significant difference is mutable vs. immutable infrastructure. Terraform creates immutable infrastructure, which means every time you push changes via Terraform, it builds an entirely new resource. On the other hand, if changes are pushed via Puppet, it will update the existing software version, leading to configuration drift in the long run.
- Another difference is open source vs. proprietary; Terraform is an open-source tool and works with almost all the major providers, as we discussed above, whereas tools like CloudFormation are specific to AWS and are proprietary.
Terraform Installation
Installing Terraform is pretty straightforward as it comes with a single binary and you need to choose the binary depending upon your platform using this link: https://www.terraform.io/downloads.html
- Download the binary(in case of Mac)
wget https://releases.hashicorp.com/terraform/1.0.6/terraform_1.0.6_darwin_amd64.zip
- Unzip the package
unzip terraform_1.0.6_darwin_amd64.zip
- Copy the binary on your Operating system path
echo $PATH
/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
sudo cp terraform /opt/homebrew/bin - Logout and login from the terminal and verify the terraform installation
terraform version
Terraform v1.0.6
How Terraform Works
Terraform works by making an API call on your behalf to the provider(AWS, GCP, Azure, etc.) you defined. Now to make an API call, it first needs to be authenticated, and that is done with the help of API keys(AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY). To create an IAM user and its corresponding keys, please check this doc: https://docs.aws.amazon.com/IAM/latest/UserGuide/getting-started_create-admin-group.html
Now how much permission users have will be defined with the help of an IAM policy. To attach an existing policy to the user, check this doc: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_manage-attach-detach.html#add-policies-console
Now in order to use these keys, you can export these as environment variables
$ export AWS_ACCESS_KEY_ID="abcxxx"
$ export AWS_SECRET_ACCESS_KEY="xyzasdd"
There are other ways to configure these credentials; check this doc for more info: https://registry.terraform.io/providers/hashicorp/aws/latest/docs#authentication
Now the next question, how does Terraform know which API to call? This is where you need to define the code in a Terraform configuration file(ends typically with .tf). These configuration files are the code in Infrastructure as Code(IaC).
How Terraform helps in creating immutable infrastructure using state files
Every time you run Terraform, it records the information about your infrastructure in a terraform state file(terraform.tfstate). This file stores information in json format and contains a mapping of your terraform resource in your configuration file vs. the real world in AWS cloud. Now when you run the terraform command, it fetches the resource's latest status, compares it with the tfstate file, and determines what changes need to be applied. If Terraform sees a drift, it will re-create or modify the resource.
Note: As you can see, this file is critically important. It is always good to store this file in some remote storage, for example, S3. In this way, your team member should have access to the same state file. Also, to avoid race conditions, i.e., two team members running terraform simultaneously and updating the state file, it's a good idea to apply locking, for example, via DynamoDB. For more information on how to do that, please check this doc: https://www.terraform.io/docs/language/settings/backends/s3.html
Introduction to Terraform module
Terraform module is a set of Terraform configuration files (*.tf) in a directory. The advantage of using modules is reusability. You can use the terraform module available in the terraform registry or share the module you created with your team members.
Writing your first terraform code
With all the prerequisites in place(configuring aws credentials access and secret keys), itâs time to write the first terraform code. Before we start writing our first terraform code, let's see how we are going to organize the files:
- main.tf: This is our main configuration file where we are going to define our resource definition.
- variables.tf: This is the file where we are going to define our variables.
- outputs.tf: This file contains output definitions for our resources.
NOTE: Filename doesnât have any special meaning for terraform as long as it ends with .tf extension, but this is a standard naming convention followed in terraform community.
Let first start with main.tf