Search code examples
terraformterraform-provider-kubernetes

Terraform Multi-providers VS explicit passing within Module


I have seen similar questions but the answers there rather addressed the formatting or workarounds which weren't that "clean". I will try to summarize my issue and hopefully can get some lean/clean solution. Thank you in advance guys!

I am creating AKS namespaces via Kubernetes provider in Terraform. Since I have 3 clusters, I want to be able to control which provider should be used to create the namespace. e.g. dev / prod

Folder structure

.terraform
    ├───modules
        └───namespace.tf
        └───module_providers.tf
    └───main-deploy
        └───main.tf
        └───main_provider.tf

My Module // namespace.tf

# Create Namespace
resource "kubernetes_namespace" "namespace-appteam" {
  metadata {
    annotations = {
      name = var.application_name
    }
    labels = {
      appname = var.application_name
    }
    name = var.application_name
  }
}

My main.tf file

module "appteam-test" {
  source            = "../modules/aks-module"
  application_name  = "dev-app"
  providers         = {
    kubernetes.dev  = kubernetes.dev
    kubernetes.prod  = kubernetes.prod
  }
}

Now since I have passed 2 providers in the main.tf module block! How do I control that the resource I am creating in namespace.tf file should use Dev or Prod provider? In short, how does the module know which resource to create with what provider if several are passed.

Note: I have required_providers defined in the module_providers.tf and providers in main_provider.tf folder.

module_provider.tf

terraform {
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
      version = "3.20.0"
    }
    azuread = {
      source = "hashicorp/azuread"
      version = "2.27.0"
      
    }

    kubernetes = {
      source = "hashicorp/kubernetes"
      version = "2.12.1"
    }
  
  }
}

Main_provider.tf

provider "azuread" {
  alias = "AD"
}
  
provider "azurerm" {
  alias = "default"
  features {}
}

provider "kubernetes" {
  alias = "dev"
}

provider "kubernetes" {
  alias = "prod"
}

Solution

  • You need to add alias to all your providers.

    provider "kubernetes" {
      alias = "dev"
    }
    provider "kubernetes" {
          alias = "stage"
        }
    

    In your main.tf file. Pass providers in module like following:

     providers             = {
        
        kubernetes.dev      = kubernetes.dev
        kubernetes.stage    = kubernetes.stage
        
      }
    

    Now in the module_provider.tf file. You need to pass configuration_aliases

    kubernetes = {
          source = "hashicorp/kubernetes"
          version = "2.12.1"
          configuration_aliases = [ kubernetes.dev, kubernetes.stage ]
        }
    

    Once all the configurations are in place. You can specify the provider explicitly for resources you want. Your namespace.tf file will look like

    resource "kubernetes_namespace" "namespace-appteam-1" {
      provider = kubernetes.dev
      metadata {
        annotations = {
          name = var.application_name
        }
        labels = {
          appname = var.application_name
        }
        name = var.application_name
      }
    }
    
    resource "kubernetes_namespace" "namespace-appteam-2" {
      provider = kubernetes.stage
      metadata {
        annotations = {
          name = var.application_name
        }
        labels = {
          appname = var.application_name
        }
        name = var.application_name
      }
    }