Search code examples
terraformterraform-provider-gcpterraform-modules

Reuse Terraform modules for different environments


I'm having a hard time to understand how to reuse modules like terraform-google-modules/terraform-google-kubernetes-engine for multiple environments like production, staging and development within one GCP project.

I was used to have a structure like this:

├── backend.tf
├── development
│   └── development.tfvars
├── firewall.tf
├── gcp-apis.tf
├── gke.tf
├── outputs.tf
├── production
│   └── production.tfvars
├── providers.tf
├── staging
│   └── staging.tfvars
├── variables.tf
├── versions.tf
└── vpc.tf

Where I just filled out the .tfvars files with values. Now I got somehow lost with the module structure. Looking at the terraform-google-modules/terraform-google-kubernetes-engine example I'm not sure how to define multiple node pools for i.e. with different types of machines/disks.

For me the example in README.md doesn't look like a clean separation of template and variables, it seem's to be some kind of mixup (please no offense, I guess I just don't understand it).

To be a little more specific: what do I need to define in my development.tfvars, staging.tfvars and production.tfvars if I want to have multiple node pools?

Hope you can help me out. Cheers


Solution

  • I'll explain better the terraform workspace usage.

    If you want to reuse a module or a resource across multiple environments, terraform workspace is the better solution. There are some steps that you need to follow.

    Let's create the dev and prod workspace:

    terraform workspace new prod
    terraform workspace new dev
    

    Let's check if they were created running terraform workspace list, you will see something like:

      default
    * dev
      prod
    

    Now we have two workspaces and we are on dev. Since we want to reuse the gke module, we need to pass everything we want to be changed, using the workspace name in a map.

    Let's create a file first like settings.tf, see the following examples, and feel free to customize everything you want.

    locals {
      env = terraform.workspace
    
      disk_size_gb = {
        dev  = 50
        prod = 100
      }
    
      machine_type = {
        dev  = "e2-standard-2"
        prod = "e2-medium"
      }
    ...
    }
    

    Now we need to use our custom configurations in the gke module, and all you need to do is:

    module "gke" {
       source = "terraform-google-modules/kubernetes-engine/google"
       project_id = "<PROJECT ID>"
       name = "${local.env}-gke-cluster" #your cluster name will be dev-gke-cluster"
      ...
       disk_size_gb = local.disk_size_gb #50 for dev
       machine_type = local.machine_type #e2-standard-2 for dev
      ...
    }
    

    When you are done, let's deploy by:

    terraform workspace select dev
    terraform apply
    terraform workspace select prod
    terraform apply
    

    As I said, you can use this approach on modules and resources.. You don't need to duplicate the terraform code, just put the values on the locals block as I did and use it where you want.