Engineering Scalable Infrastructure: A Comprehensive Guide to Terraform GCP Modules

Infrastructure as Code (IaC) has evolved from simple scripting to a sophisticated discipline of software engineering. In the ecosystem of Google Cloud Platform (GCP), Terraform serves as the primary engine for provisioning, but the raw application of Terraform resources often leads to "code sprawl"—the repetitive, error-prone practice of copy-pasting resource blocks across multiple environments. To combat this, professional cloud architects utilize Terraform modules to turn infrastructure into reusable, versioned, and scalable building blocks.

A Terraform module is fundamentally a collection of .tf files residing in a single folder. These files encapsulate the logic required to deploy a specific set of resources, exposing a clean interface through inputs and outputs. While a resource is a single object in GCP (like a google_compute_instance), a module is a logical abstraction of those resources. When these modules are bundled with specific policies and documentation to implement an opinionated solution, they transition into what are known as Blueprints.

The Architecture of a Reusable Module

To move beyond basic configurations, teams must adopt a standardized structure. A well-engineered module does not just wrap resources; it creates a contract between the infrastructure provider and the consumer. This contract is defined by three primary components:

  • Inputs (variables.tf): These define the parameters the module accepts, allowing the same code to be used for different environments (e.g., dev, staging, prod) by changing the input values.
  • Resources (main.tf): This is the core logic where the actual GCP resources are defined.
  • Outputs (outputs.tf): These expose specific attributes of the created resources (like a VPC ID or an IP address) so that other modules can consume them.

A professional directory layout separates the generic module logic from the environment-specific implementation. This ensures that the module remains agnostic of the environment it is deployed into.

Table 1: Recommended Directory Structure for GCP Terraform Projects

Directory Purpose Key Files
terraform/modules/vpc/ Reusable networking logic main.tf, variables.tf, outputs.tf, versions.tf, README.md
terraform/envs/dev/ Development environment instantiation main.tf, providers.tf, backend.tf, terraform.tfvars
terraform/envs/prod/ Production environment instantiation main.tf, providers.tf, backend.tf, terraform.tfvars

By keeping the modules generic and the environment folders "thin," organizations can ensure that a change to the module logic propagates across all environments consistently, provided the versioning strategy is sound.

Implementing a Production-Ready VPC Module

Networking is the foundation of any GCP organization. Rather than rewriting the same Virtual Private Cloud (VPC), subnets, and firewall rules repeatedly, a VPC module allows the architect to define the "how" once and the "what" per environment.

A robust VPC module should support the creation of a single VPC network, an arbitrary number of subnets defined via a list, and optional firewall rules. This flexibility is achieved by using Terraform's iteration capabilities.

The following code demonstrates the technical implementation of a reusable VPC module. It specifies the required provider versions to ensure stability across deployments.

```hcl
terraform {
requiredversion = ">= 1.5.0"
required
providers {
google = {
source = "hashicorp/google"
version = ">= 5.0.0"
}
}
}

variable "project_id" {
description = "GCP project ID where resources will be created."
type = string
}

variable "vpc_name" {
description = "Name of the VPC."
type = string
}

variable "routing_mode" {
description = "VPC routing mode: REGIONAL or GLOBAL"
type = string
default = "REGIONAL"
}

variable "subnets" {
description = "List of subnets to create"
type = list(object({
name = string
region = string
cidr = string
privategoogleaccess = bool
}))
}

variable "firewallrules" {
description = "Optional firewall rules"
type = list(object({
name = string
source
ranges = list(string)
target_tags = list(string)
protocol = string
ports = list(string)
}))
default = []
}

resource "googlecomputenetwork" "this" {
name = var.vpcname
project = var.project
id
autocreatesubnetworks = false
routingmode = var.routingmode
}

resource "googlecomputesubnetwork" "this" {
foreach = { for s in var.subnets : s.name => s }
name = each.value.name
ip
cidrrange = each.value.cidr
region = each.value.region
network = google
computenetwork.this.id
project = var.project
id
privategoogleaccess = each.value.privategoogleaccess
}

resource "googlecomputefirewall" "this" {
foreach = { for f in var.firewallrules : f.name => f }
name = each.value.name
network = googlecomputenetwork.this.name
project = var.project_id
direction = "INGRESS"

allow {
protocol = each.value.protocol
ports = each.value.ports
}

sourceranges = each.value.sourceranges
targettags = each.value.targettags
}

output "vpcid" {
value = google
compute_network.this.id
}

output "subnetids" {
value = { for k, s in google
compute_subnetwork.this : k => s.id }
}
```

To consume this module in a specific environment (e.g., envs/dev/main.tf), the developer simply calls the module and passes the required parameters.

```hcl
module "vpc" {
source = "../../modules/vpc"
projectid = var.projectid
vpc_name = "dev-vpc"

subnets = [
{
name = "dev-us-central1-public"
region = "us-central1"
cidr = "10.10.0.0/24"
privategoogleaccess = true
},
{
name = "dev-us-central1-private"
region = "us-central1"
cidr = "10.10.1.0/24"
privategoogleaccess = true
}
]

firewallrules = [
{
name = "dev-allow-ssh-from-office"
source
ranges = ["203.0.113.10/32"]
target_tags = ["ssh"]
protocol = "tcp"
ports = ["22"]
}
]
}
```

Google Cloud Foundation Fabric (Fabric FAST)

For enterprises, building modules from scratch can be a time-consuming process. Google provides the Cloud Foundation Fabric (Fabric FAST), an organization-wide landing zone toolkit designed to bootstrap real-world cloud foundations. Fabric FAST focuses on two primary goals: providing a design of a GCP organization that meets typical enterprise requirements and offering a reference implementation of that design via Terraform.

The Fabric repository is intended to be used as a complete toolkit. It can be cloned as a single unit and forked into separate owned repositories for production use, or used as-is for rapid prototyping. The suite of modules is designed for rapid composition and reuse, remaining simple and readable so they can be modified if third-party code is restricted.

All modules in the Fabric ecosystem share a consistent interface:
- They stay close to the underlying provider resources to avoid unnecessary abstraction.
- They support IAM (Identity and Access Management) together with resource creation and modification.
- They offer the ability to create multiple resources where logically appropriate.
- They are free of side-effects, meaning they do not execute external commands.

Table 2: Fabric FAST Module Categories and Capabilities

Category Key Modules / Components Purpose
Foundational Billing account, Folder, Organization, Project, Service Accounts, Logging Bucket Core GCP hierarchy and identity setup.
Process Factories Project Factory Automated creation and standardization of projects.
Networking VPC, DNS, NAT, VLAN Attachment, Firewall Policy, VPC Peering, VPN Dynamic, Load Balancers (App/Network/Regional) End-to-end connectivity and traffic management.

Terraform Blueprints: Implementing Opinionated Solutions

While modules provide the building blocks, Blueprints provide the architecture. A blueprint is a package of deployable, reusable modules and policies that implement a specific, opinionated solution. Blueprints move the conversation from "how do I create a database?" to "how do I deploy a secured data warehouse?"

Google Cloud offers a variety of blueprints tailored to specific business use cases. These are packaged as Terraform modules, allowing users to deploy complex environments with minimal configuration.

Table 3: Google Cloud Terraform Blueprints and Use Cases

Blueprint Name Category Description
ai-notebook Data Analytics / End-to-end Protects confidential data in Vertex AI Workbench notebooks.
crmint Data Analytics / End-to-end Deploys the CRMint marketing analytics application.
enterprise-application Operations / End-to-end Deploys an enterprise developer platform on Google Cloud.
example-foundation Operations / End-to-end Composes CFT modules to build a secure cloud foundation.
fabric End-to-end Advanced examples specifically designed for prototyping.
secure-cicd DevTools / Security / Identity Builds a secure CI/CD pipeline on Google Cloud.
secured-data-warehouse Data Analytics / End-to-end Deploys a secured BigQuery data warehouse.
secured-data-warehouse-onprem-ingest Data Analytics / Security Secured warehouse for ingesting encrypted on-prem data.
vertex-mlops End-to-end Creates the Vertex AI environment required for MLOps.
address Networking Manages Google Cloud IP addresses.
alloy-db Databases Creates AlloyDB for PostgreSQL instances.
analytics-lakehouse Data Analytics Deploys a Lakehouse Architecture Solution.
anthos-vm Compute Creates VMs on Google Distributed Cloud clusters.
apphub Developer tools Creates and manages App Hub.

Best Practices and Common Pitfalls

When designing and implementing Terraform modules for GCP, certain architectural pitfalls can lead to configuration drift or security vulnerabilities.

Avoiding Hardcoding

One of the most common mistakes in IaC is hardcoding values. Regions, CIDR blocks, environment names, and project IDs should never be hardcoded within a module. Instead, they should be passed as variables. This ensures the module can be moved from us-central1 to europe-west1 without changing the source code.

Modular Granularity

There is a temptation to create a "platform module"—a single, massive module that manages everything from the VPC to the GKE cluster. This approach leads to fragility and long execution times. The recommended approach is to create small, focused modules:
- modules/vpc
- modules/cloud_run
- modules/cloud_sql
- modules/iam

These granular modules are then composed in the environment folder (envs/dev/main.tf) to build the full stack.

Managing IAM and Authoritative Resources

IAM resources in Terraform can be dangerous if not handled correctly. Some IAM resources are "authoritative," meaning they overwrite the entire existing set of permissions. If a manual change is made in the GCP Console, an authoritative Terraform resource will remove that access during the next terraform apply. To avoid unexpected outages, it is safer to start with *_iam_member resources, which add a specific identity to a role without affecting other existing members.

Versioning and Pinning

To prevent breaking changes from flowing into production, modules should be versioned using Git tags. Instead of calling a module from a local path, production environments should pin the module to a specific version.

Example of pinning a module version:
hcl module "vpc" { source = "git::https://github.com/YOUR_ORG/YOUR_REPO.git//modules/vpc?ref=v1.0.0" }

Conclusion

The transition from writing flat Terraform files to utilizing a module-based architecture is a critical step in the maturity of any DevOps practice on Google Cloud. By abstracting recurring patterns into reusable modules, organizations can drastically reduce duplication, ensure consistent environments, and implement safer change management processes.

The combination of Google's Cloud Foundation Fabric and their suite of Blueprints provides a powerful shortcut for enterprises. Fabric FAST offers the foundational "plumbing" of a GCP organization—billing, folders, and core networking—while Blueprints provide the higher-level application architecture for AI, MLOps, and Data Analytics. By adhering to the principles of generic modules, thin environments, and strict version pinning, cloud engineers can build a scalable infrastructure that evolves with the business without collapsing under its own complexity.

Sources

  1. cloud-foundation-fabric
  2. terraform-blueprints
  3. terraform-modules-for-reusable-gcp-infrastructure-with-a-real-vpc-module-example-4b

Related Posts