Terraform Backends
In this post, we discuss backends that can be used with Terraform. Working with backends is essential when a larger team works on developing Terraform code. This is mainly because Terraform relies heavily on states for its operations and there is a huge scope of states getting “corrupted” if we “just use Github” to maintain the same.
We would not go into the details of those complexities in this post. It is indeed a topic for another post as we would go through the process of how teams can collaborate on Terraform IaC. However, to discuss this point, knowledge about backends is essential.
Terraform supports 2 types of backends - local
and remote
. All the code examples we have dealt with in this series use a local
backend by default. Local backends simply mean your local computer on which Terraform code and state files reside and the execution happens. It is safe to assume that we are already very familiar with the same.
Remote backends - as the name suggests - store and/or execute Terraform states and code respectively, remotely. This enables cross-team collaboration. Usually, these remote backends also provide us with state locking functionality to avoid race conditions.
Essentially, there are types of backends based on what they are used for. Some backends are used only to store Terraform state while there are others where Terraform API operations take place. Of course, there are backends where both can be done.
Remote backends help manage Terraform state so that multiple developers working on the same infrastructure configuration can access it from their local development systems. In the cases where remote backends are used, if we run terraform plan
command, Terraform evaluates by accessing the remotely stored state and currently deployed infrastructure.
Most of the frequently used commands in Terraform CLI are related to Terraform state. Whether it is querying, modifying, importing, tainting, or anything that has to do with states - happens remotely. However, there are a couple of commands like apply
and destroy
, which perform the planned operations.
Remote backends also support these operations where Terraform performs API calls remotely and streams the output to the local terminal. Certain backends also support workspaces
.
There are several backends available to be used and the list can be found here. My favorites are Terraform Cloud and AWS S3.
Let us consider our example, and try to manage our states remotely. We would attempt to use Terraform Cloud to store our state and execute Terraform operations (apply
and destroy
) our backend. If you choose Terraform Cloud as a backend
, then workspaces
are not managed locally. They are directly managed on the cloud. In such cases, the “prefix” attribute is used while configuring remote workspaces in the backend configuration.
We have used a single workspace in our example to keep it simple. To use remote backends, let us navigate to provider.tf
file and add the backend
configuration block within terraform settings block as shown below.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.0"
}
}
backend "remote" {
hostname = "app.terraform.io"
organization = "letsdotech"
//token = “xxxxxxxx”
workspaces {
name = "tf-blog-workspace"
}
}
}
In the above configuration, we have asked Terraform to use a remote backend and have set certain properties like hostname, organization, and workspace name. We have commented on the token attribute. This token is used by Terraform for authentication purposes to perform all the remote operations.
However, since this is sensitive information it is recommended to set the token using Terraform CLI using terraform login command. After all, we would need this even before we reinitialize the Terraform configuration directory.
Running terraform login would open Terraform Cloud in a browser window, after login, the window would provide us with a token. We are expected to copy the token and paste it in the next step in Terraform CLI input. Hit Enter, and Terraform soon confirms that the login to Terraform Cloud was successful. Log in to your Terraform Cloud portal using a web browser and you would already see a workspace listed with a name that you provided in your remote backend configuration.
Reinitialize the directory by running terraform init
. Terraform installs the plugins required to manage the desired backends. Try running terraform plan
command and observe the output.
Running plan in the remote backend. The output will stream here. Pressing Ctrl-C
will stop streaming the logs, but will not stop the plan running remotely.
Preparing the remote plan...
. . .
. . .
Error: error configuring Terraform AWS Provider: no valid credential sources for Terraform AWS Provider found.
Please see https://registry.terraform.io/providers/hashicorp/aws
for more information about providing credentials.
Error: NoCredentialProviders: no valid providers in chain. Deprecated.
For verbose messaging see aws.Config.CredentialsChainVerboseErrors
The very first statement in the output indicates that the remote backend is being used to run the terraform plan
command. Which is good and as per what we want - nothing runs locally anymore. The output is a result of what is happening on Terraform Cloud.
However, it has failed to run the command completely. It has not generated any plan. The error tells us that there are no credentials provided. This is good as well as bad news. Good because it confirms the fact that the AWS API is now being consumed from Terraform Cloud. Bad because Terraform Cloud is unaware of AWS Access and Secret Access keys.
Thus to make this work, we need to set these Environment Variables into the workspace created on Terraform Cloud. This is a one-time activity and can be done by clicking on our workspace and adding 2 environment variables - AWS_ACCESS_KEY_ID
and AWS_SECRET_ACCESS_KEY
.
Run terraform plan
after saving these environment variables - it should give you a generated plan output. If it does, we have successfully configured a remote backend for our Terraform Configuration!