Software Development

Terraform 1.8 Module Composition: Advanced Techniques for Multi-Cloud Infra

As infrastructure becomes increasingly multi-cloud, managing complexity in Terraform is critical. Terraform 1.8 enhances module composition and provides powerful constructs like for_each, dynamic blocks, and workspaces to enable reusable, DRY (Don’t Repeat Yourself) infrastructure code.

In this guide, you’ll learn advanced techniques for composing Terraform modules in a multi-cloud environment, how to manage per-environment configurations, and apply reusable logic across AWS, Azure, and GCP.

🚀 What’s New in Terraform 1.8?

Terraform 1.8 brings enhancements to:

  • Module metadata and validation
  • Improved for_each in module blocks
  • Scoped outputs and input schema validation
  • Cleaner workspace-aware designs

🔗 Terraform 1.8 Release Notes

🧱 Organizing a Multi-Cloud Structure

Let’s start with a folder structure for a multi-cloud setup:

infra/
├── modules/
│   ├── aws/
│   ├── azure/
│   └── gcp/
├── environments/
│   ├── dev/
│   ├── staging/
│   └── prod/
├── main.tf
├── variables.tf
└── terraform.tfvars

This approach separates provider-specific modules and allows per-environment customization using workspaces.

🔄 Using for_each to Instantiate Modules per Environment or Region

Terraform 1.8 allows for_each over module blocks — ideal for deploying similar infra in multiple regions or clouds.

variable "regions" {
  type = list(string)
  default = ["us-east-1", "us-west-2"]
}

module "aws_vpc" {
  for_each = toset(var.regions)
  source   = "../modules/aws"
  
  region   = each.key
  cidr     = "10.${index(var.regions, each.key)}.0.0/16"
}

This deploys a VPC module in each region without duplicating code.

🧬 Dynamic Blocks for Reusable Nested Configurations

Use dynamic blocks for optional or conditional nested resources. Here’s an example with security group rules:

resource "aws_security_group" "web" {
  name        = "web-sg"
  description = "Security group for web servers"
  vpc_id      = var.vpc_id

  dynamic "ingress" {
    for_each = var.allow_ssh ? [22] : []
    content {
      from_port   = ingress.value
      to_port     = ingress.value
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
    }
  }
}

This will only add an SSH rule if allow_ssh is true.

🗂️ Workspaces for Environment Separation

Workspaces enable isolated state per environment (dev, staging, prod):

terraform workspace new dev
terraform workspace select dev

In your code:

variable "env" {
  default = terraform.workspace
}

Use this env variable to dynamically name resources or load env-specific variables.

Example:

resource "aws_s3_bucket" "logs" {
  bucket = "my-logs-${var.env}"
}

📦 Writing a Cloud-Agnostic Module Interface

Design modules to accept a provider alias and other generic inputs:

provider "aws" {
  alias  = "east"
  region = "us-east-1"
}

module "network" {
  source          = "./modules/aws"
  providers       = { aws = aws.east }
  vpc_cidr        = "10.0.0.0/16"
  availability_zones = ["us-east-1a", "us-east-1b"]
}

You can use similar interfaces for Azure and GCP modules, allowing multi-cloud abstraction with shared inputs.

🛡️ Validating Module Inputs (Terraform 1.8+ Feature)

Define strict validation rules:

variable "vpc_cidr" {
  description = "CIDR block for the VPC"
  type        = string

  validation {
    condition     = can(cidrsubnet(var.vpc_cidr, 8, 0))
    error_message = "The vpc_cidr must be a valid CIDR block."
  }
}

This prevents runtime failures by enforcing configuration rules early.

📊 Visualizing Multi-Cloud Composition

Use Terraform Graph or third-party tools like:

📁 Example Use Case: AWS + GCP VPC Deployment

module "aws_network" {
  source    = "../modules/aws"
  region    = "us-east-1"
  cidr      = "10.0.0.0/16"
}

module "gcp_network" {
  source    = "../modules/gcp"
  region    = "us-central1"
  cidr      = "10.1.0.0/16"
}

Both modules implement a unified interface and are deployed independently with shared logic.

🧠 Best Practices Recap

✅ Use for_each and dynamic for scalable resource generation
✅ Leverage workspaces for isolated environments
✅ Validate module inputs early
✅ Abstract provider-specific logic in modules
✅ Keep modules small, composable, and testable

📚 Further Reading

Eleftheria Drosopoulou

Eleftheria is an Experienced Business Analyst with a robust background in the computer software industry. Proficient in Computer Software Training, Digital Marketing, HTML Scripting, and Microsoft Office, they bring a wealth of technical skills to the table. Additionally, she has a love for writing articles on various tech subjects, showcasing a talent for translating complex concepts into accessible content.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Back to top button