What is terraform state?

What are the best practices?

Introduction

Terraform is an open-source infrastructure as code (IAC) tool used to build, manage, and version infrastructure. It uses a declarative approach to define infrastructure as code, enabling teams to automate the deployment and management of infrastructure across multiple clouds and on-premises environments. Terraform allows infrastructure to be defined in a simple language called Hashicorp Configuration Language (HCL).

One of the most critical components of Terraform is its state management. The state is a snapshot of the current infrastructure resources that Terraform is managing. In this article, we will dive into Terraform state and its best practices.

What is Terraform State?

Terraform state is a crucial component of Terraform. It is a file that stores the current state of the resources managed by Terraform. The state file keeps track of the resources' metadata and their attributes, such as resource IDs, attributes, dependencies, and the relationship between them. Terraform uses the state file to compare the desired state with the current state of the infrastructure, and then it makes the necessary changes to move the infrastructure to the desired state.

When Terraform applies a configuration, it reads the desired state from the configuration files and compares them with the current state. If there are any differences between the desired state and the current state, Terraform applies the necessary changes to move the infrastructure to the desired state. Terraform state helps Terraform to know what changes are necessary to bring the infrastructure in sync with the desired state.

Terraform state is stored in a file called terraform.tfstate. By default, Terraform stores the state file locally in the root directory where the Terraform configuration files are located. However, Terraform can also store the state remotely, for example, in a backend like Amazon S3, Azure Blob Storage, or Hashicorp's own Terraform Cloud.

Best Practices for Terraform State Management

Terraform state is a critical component of Terraform, and managing it properly is essential for successful infrastructure automation. Here are some best practices for Terraform state management.

Use a remote backend for storing Terraform state:

By default, Terraform stores the state file locally in the root directory of the Terraform configuration files. However, using a remote backend like Terraform Cloud or Amazon S3 has several benefits.

Firstly, a remote backend ensures that the state file is stored securely and is accessible to all members of the team working on the infrastructure. Secondly, a remote backend provides version control for the state file, which makes it easier to roll back changes if necessary. Finally, using a remote backend eliminates the risk of accidentally deleting the state file, which can cause irreversible damage to the infrastructure and is very hard to recover.

Use a locking mechanism:

When multiple team members are working on the same infrastructure, there is a risk of multiple Terraform processes attempting to modify the state file simultaneously. This can cause race conditions and potentially corrupt the state file. To prevent this, Terraform provides a locking mechanism that prevents multiple processes from modifying the state file simultaneously.

When using a remote backend, Terraform can automatically manage locking. However, if you are using a local state file, you should implement a locking mechanism manually. There are several tools available to manage Terraform state locking, including Consul, DynamoDB, and etcd.

Keep the state file small:

The state file can grow very large if it contains many resources or complex data structures. A large state file can slow down Terraform operations, increasing the time it takes to apply changes or plan updates. To keep the state file small, avoid storing unnecessary data in the state file.

For example, do not include sensitive data like passwords or access keys in the state file. Instead, use Terraform's input variables to pass sensitive data to the configuration. Also, consider using data sources instead of creating new resources for data that do not need to be managed by Terraform. This can improve performance if you have a very large environment.

Use Terraform workspaces:

Terraform workspaces allow you to manage multiple instances of the same infrastructure in a single Terraform configuration. Workspaces can be used to manage different environments, such as development, staging, and production, or to manage multiple instances of the same infrastructure for different teams or customers.

Each workspace has its separate state file, allowing you to manage each instance of the infrastructure independently. When you switch between workspaces, Terraform automatically switches to the appropriate state file.

Regularly back up the state file:

The state file is critical to the success of Terraform, and losing the state file can cause significant problems. To prevent this, it is essential to regularly back up the state file. When using a remote backend, the backend provider may automatically back up the state file. However, if you are using a local state file, you should back up the file regularly to a secure location. State recovery sucks, dont lose the state file. Here is a basic GO script to back up a state file to a versioned S3 bucket. I enabled versioning so that it is harder to delete (I have seen this happen and would highly suggest removing empty bucket privileges in IAM). :

package main

import (
    "fmt"
    "os"
    "path/filepath"

    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/s3"
)

func main() {
    // Define the path to the Terraform state file to backup
    stateFilePath := "/path/to/terraform.tfstate"

    // Define the name of the S3 bucket to upload the backup to
    s3Bucket := "my-terraform-state-backups"

    // Define the name of the backup file to create in S3
    backupFileName := filepath.Base(stateFilePath) + ".bak"

    // Create an AWS session
    awsSession := session.Must(session.NewSession())

    // Create an S3 service client with versioning enabled
    s3Client := s3.New(awsSession, aws.NewConfig().WithS3DisableContentMD5Validation(true).WithS3ForcePathStyle(true))
    _, err := s3Client.PutBucketVersioning(&s3.PutBucketVersioningInput{
        Bucket: aws.String(s3Bucket),
        VersioningConfiguration: &s3.VersioningConfiguration{
            Status: aws.String("Enabled"),
        },
    })
    if err != nil {
        panic(fmt.Errorf("Failed to enable versioning on S3 bucket: %s", err))
    }

    // Open the Terraform state file for reading
    stateFile, err := os.Open(stateFilePath)
    if err != nil {
        panic(fmt.Errorf("Failed to open Terraform state file: %s", err))
    }
    defer stateFile.Close()

    // Upload the state file backup to S3
    _, err = s3Client.PutObject(&s3.PutObjectInput{
        Bucket: aws.String(s3Bucket),
        Key:    aws.String(backupFileName),
        Body:   stateFile,
    })
    if err != nil {
        panic(fmt.Errorf("Failed to upload Terraform state file backup to S3: %s", err))
    }

    fmt.Printf("Successfully backed up Terraform state file to S3 bucket %s with backup file name %s\n", s3Bucket, backupFileName)
}

Conclusion

Terraform state is a crucial component of Terraform, and managing it properly is essential for successful infrastructure automation. Terraform state provides a snapshot of the current infrastructure resources that Terraform is managing, allowing Terraform to compare the desired state with the current state of the infrastructure and make the necessary changes to move the infrastructure to the desired state.

In this article, we discussed the best practices for Terraform state management, including using a remote backend for storing Terraform state, using a locking mechanism, keeping the state file small, using Terraform workspaces, and regularly backing up the state file. By following these best practices, you can ensure the smooth operation of your infrastructure automation using Terraform.

Why did the JavaScript developer wear glasses?

Because he couldn't C#!

Did you find this article valuable?

Support Kyle Shelton by becoming a sponsor. Any amount is appreciated!