Terraform multiple environments gitlab ci - deployment strategy

Hey,

i have written a terraform code to roll out Openstack instances with different configuration. Now I have wrapped it in a module and want to roll out a multi environment and need help with the right strategy. The code is hosted in gitlab.

Each enviroment has it’s own remote State File in gitlab.

My folder structure:

- ROOT /
- enviroments /
--- infra /
    |- versions.tf, backend.tf, main.tf, output.tf
--- dev /
--- test /
--- prod /
--- global /
    |- cloud-init.yml
- modules/ openstack-instances
    |- versions.tf, output.tf, veriables.tf, data-sources.tf, maint.tf, README.MD
- README.MD

Now I have heard that you could manage the environments using gitlab branches. Instead of a module, would it be possible to simply manage the code through different tfvars files or through large gitlab-ci.yaml and the directory structure?
I am not yet good enough to write a ci pipeline to work with the different folders. At the moment I am using the gitlab-terraform template. I have also heard about Terragrunt…

The module should also be further developed later and hosted in the gitlab registry.

Could you help me find a solution and strategy?

Example from enviroments/dev/main.tf:

module "openstack-instances" {
  source = "../../modules/openstack-instances"

  instance_name_prefix        = "it-d"
  instance_delete_with_disk   = true
  instance_disk_resize_online = true
  instance_tag_keys           = ["Environment", "ApplicationClass", "SystemType"]
  linux_cloudinit_config      = "../../global/linux-cloud-init.yaml"

  instances = [
    {
      name             = "websrv01"
      image            = "Ubuntu 22.04"
      flavor           = "SCS-2V-4-20s"
      volume_size      = 8
      network          = "test-intern"
      security_groups  = ["default"]
      keypair_name     = "ssh_key"
      floating_ip_pool = "public"
      tags             = ["dev", "e-commerce", "webserver"]
    },
    {
      name             = "websrv02"
      image            = "Ubuntu 22.04"
      flavor           = "SCS-2V-4-20s"
      volume_size      = 8
      network          = "test-intern"
      security_groups  = ["default"]
      keypair_name     = "ssh_key"
      floating_ip_pool = "public"
      tags             = ["dev", "e-commerce", "webserver"]
    },
    {
      name            = "dbsrv"
      image           = "Ubuntu 22.04"
      flavor          = "SCS-2V-4-20s"
      volume_size     = 8
      network         = "test-intern"
      security_groups = ["default"]
      keypair_name    = "ssh_key"
      tags            = ["dev", "e-commerce", "dbserver"]
      additional_disks = [
        { disk_name = "db-data", disk_size = 5 },
        { disk_name = "db-log", disk_size = 3 }
      ]
    }
  ]
}

gitlab-ci.yaml:

# This file is a template, and might need editing before it works on your project.
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml

include:
  - template: Terraform/Base.latest.gitlab-ci.yml  # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml
  - template: Jobs/SAST-IaC.gitlab-ci.yml   # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/SAST-IaC.gitlab-ci.yml

stages:
  - validate
  - test
  - build
  - deploy
  - cleanup

fmt:
  extends: .terraform:fmt
  needs: []

validate:
  extends: .terraform:validate
  needs: []

build:
  extends: .terraform:build
  environment:
    name: $TF_STATE_NAME
    action: prepare

deploy:
  extends: .terraform:deploy
  dependencies:
    - build
  environment:
    name: $TF_STATE_NAME
    action: start

cleanup:
 extends: .terraform:destroy
 dependencies:
   - deploy
 environment:
   name: $TF_STATE_NAME
   action: start