The evolution of agile methodology has enabled software development teams to deliver high-quality software continually, but faster development alone can’t help the organizations to achieve a faster time-to-market. It also requires an infrastructure that is highly elastic, scalable, and easily reproducible. This is where the need for Infrastructure as a code/service (IAAC/IAAS) comes in.
IAAS allows you to write and execute code to define, deploy, or update your infrastructure. There are various public cloud providers in the market today, such as AWS, Google, AZURE, etc., and each one comes with an IAAS solution. As we speak about building or creating an infrastructure, we are referring to various components of the infrastructure, like Domain Name System (DNS), internet gateway, load balancers, subnets, security policies, IP ranges, instance type, capacity, and storage.
IAAS treats each component of the infrastructure as a code. It enables us to work at a required pace while building an infrastructure, which can be re-used, shared, updated, and modified. Terraform, hence, is basically a tool that fulfills an infrastructure’s reusable capabilities, automation, and utilizes IAAC.
Terraform is logically split into two main parts:
Public cloud providers usually assign a cloud-specific infrastructure management tool, such as CloudFormation by Amazon, Azure Resource Manager by Azure, Cloud Deployment Manager by Google, etc. These tools provide reusable templates and scripts in terms of IAAC that are only specific to their platform. Terraform, being a platform-independent tool, supports mostly all cloud providers.
Terraform provides segregation for the planning and execution phase of the infrastructure. Through this dry run, the user can reduce errors during the execution phase and can also inspect the result after the execution is done. Terraform plan generates a planning phase, while Terraform apply helps in the execution of the plan.
Terraform follows a declarative style of writing the code and figures out how to achieve the end-state by itself. Tools such as Chef and Ansible follows the procedural style, wherein a step-by-step plan is required to achieve an end state. To understand it better, let us first understand the difference between a declarative and procedural style of writing the code.
Let’s assume that you need to create 5 instances on the cloud, you can easily achieve those instances by using either Terraform or Ansible. In case the network traffic increases and you require 10 more instances, you have a choice of either using the Ansible template to update the remaining instances manually, or use Terraform to update only the end-state, following which the remaining instances are updated automatically.
Terraform has various components to create, manage, and update in an infrastructure. Below are a few important components of Terraform.
Terraform resolves dependencies for resources either implicitly or explicitly. When Terraform analysis interpolation expressions are used in the resource attribute, it can easily identify the resource’s dependency.
In the example above, the expression ${aws_instance.demoid} creates an implicit dependency on the AWS instance named demo. Terraform uses this dependency information to determine the correct order in which each resource needs to be created. In the example above, Terraform knows that an AWS instance must be created before the aws_eip.
Implicit dependencies via interpolation expressions are the primary way to inform Terraform about resource dependency. Even though the resources are sometimes not directly dependent on each other, but due to program logic or requirement of the application, other resources are required to gather the necessary information. Terraform is unable to resolve this type of dependency through interpolation, which is known as an explicit dependency (see the example below). Below is the example for the same. Here, aws_instance “datascience” has a dependency on S3 bucket “machinelearning”. Hence, the S3 bucket is the one that needs to be created first to create an aws_instance.