brikis98 / terraform-up-and-running-code

Code samples for the book "Terraform: Up & Running" by Yevgeniy Brikman
http://www.terraformupandrunning.com/
MIT License
2.87k stars 1.92k forks source link

Backend Config in Chapter 4: Modules #62

Closed muhannad0 closed 3 years ago

muhannad0 commented 4 years ago

Hey there!

I have a question regarding the backend configuration in Chapter 4: Modules.

As I was following the webserver-cluster example in the book, I noticed that you didn't mention about the remote backend S3 config. The backend config was hardcoded (as shown below in modules/services/webserver-cluster/main.tf), which works fine. But I was thinking of making it more reusable and flexible to accommodate different environments.

# modules/services/webserver-cluster/main.tf

terraform {
    backend "s3" {
        bucket = "bucket-for-tf"
        key = "stage/services/webserver-cluster/terraform.tfstate"
        region = "us-east-1"

        dynamodb_table = "tf-dev-locks"
        encrypt = true
    }
}

In your opinion, which option is the best approach to maintain remote state this scenario (best practice wise)?

Option 1:

Example:

# modules/services/webserver-cluster/variables.tf

variable "backend_env" {
  description = "The remote state folder for deploy environment"
  type = string
}
# modules/services/webserver-cluster/main.tf

terraform {
    backend "s3" {
        bucket = "bucket-for-tf"
        key = "${var.backend_env}/services/webserver-cluster/terraform.tfstate"
        region = "us-east-1"

        dynamodb_table = "tf-dev-locks"
        encrypt = true
    }
}

And we can pass the environment value in stage/services/webserver-cluster/main.tf

# stage/services/webserver-cluster/main.tf

module "webserver_cluster" {
    source = "../../../modules/services/webserver-cluster"

    backend_env = "stage"
}

OPTION 2:

Example:

# stage/services/webserver-cluster/main.tf

terraform {
    backend "s3" {
        bucket = "bucket-for-tf"
        key = "stage/services/webserver-cluster/terraform.tfstate"
        region = "us-east-1"

        dynamodb_table = "tf-dev-locks"
        encrypt = true
    }
}

Let me know your thoughts. Thanks so much for your help!

brikis98 commented 3 years ago

One of the limitations of Terraform is that the backend config blocks do not support ANY variables or interpolation. That's why they are hard-coded and copy/pasted in most places in the book.

Terraform does not natively offer any way to keep the backend config DRY. You can extra some of the pieces into reusable files using partial configuration, but the key parameter must be specified manually for every single module, which is a very tedious and error-prone process. Another option is to use a tool like Terragrunt, which has first-class features for keeping your backend configuration DRY. Both options are covered in the book and code examples in this repo!

muhannad0 commented 3 years ago

Ah, alright. That explains it nicely. (Guess I got a bit ahead of myself there.)

Also, just wanted to mention that I'm enjoying the book plenty. It's helped me understand a lot about Terraform and its usage patterns. Thank you for that.

brikis98 commented 3 years ago

Thanks! That's great to hear 😄