GCP for DevOps — Terraform Modules
Terraform Modules
Modules are reusable Terraform packages. They encapsulate a set of resources behind a clean interface of variables and outputs, promoting DRY (Don’t Repeat Yourself) infrastructure.
Module Structure
modules/
├── gke-cluster/
│ ├── main.tf
│ ├── variables.tf
│ ├── outputs.tf
│ └── README.md
├── vpc/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── cloud-run-service/
├── main.tf
├── variables.tf
└── outputs.tf
Create a VPC Module
# modules/vpc/variables.tf
variable "project_id" {
type = string
}
variable "environment" {
type = string
}
variable "region" {
type = string
default = "us-central1"
}
variable "subnet_cidr" {
type = string
default = "10.0.0.0/20"
}
# modules/vpc/main.tf
resource "google_compute_network" "vpc" {
name = "${var.environment}-vpc"
project = var.project_id
auto_create_subnetworks = false
}
resource "google_compute_subnetwork" "subnet" {
name = "${var.environment}-subnet"
project = var.project_id
ip_cidr_range = var.subnet_cidr
region = var.region
network = google_compute_network.vpc.id
secondary_ip_range {
range_name = "pods"
ip_cidr_range = "10.4.0.0/14"
}
secondary_ip_range {
range_name = "services"
ip_cidr_range = "10.8.0.0/20"
}
private_ip_google_access = true
}
resource "google_compute_router" "router" {
name = "${var.environment}-router"
project = var.project_id
region = var.region
network = google_compute_network.vpc.id
}
resource "google_compute_router_nat" "nat" {
name = "${var.environment}-nat"
project = var.project_id
router = google_compute_router.router.name
region = var.region
nat_ip_allocate_option = "AUTO_ONLY"
source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES"
}
# modules/vpc/outputs.tf
output "network_name" {
value = google_compute_network.vpc.name
}
output "network_id" {
value = google_compute_network.vpc.id
}
output "subnet_name" {
value = google_compute_subnetwork.subnet.name
}
output "subnet_id" {
value = google_compute_subnetwork.subnet.id
}
Use the Module
# environments/dev/main.tf
module "vpc" {
source = "../../modules/vpc"
project_id = var.project_id
environment = "dev"
region = "us-central1"
subnet_cidr = "10.0.0.0/20"
}
module "gke" {
source = "../../modules/gke-cluster"
project_id = var.project_id
environment = "dev"
region = "us-central1"
network_name = module.vpc.network_name
subnet_name = module.vpc.subnet_name
}
Terraform Registry Modules
Use pre-built modules from the Terraform Registry.
# Google Cloud VPC module from registry
module "vpc" {
source = "terraform-google-modules/network/google"
version = "~> 9.0"
project_id = var.project_id
network_name = "${var.environment}-vpc"
routing_mode = "GLOBAL"
subnets = [
{
subnet_name = "${var.environment}-subnet"
subnet_ip = "10.0.0.0/20"
subnet_region = var.region
}
]
secondary_ranges = {
"${var.environment}-subnet" = [
{ range_name = "pods", ip_cidr_range = "10.4.0.0/14" },
{ range_name = "services", ip_cidr_range = "10.8.0.0/20" },
]
}
}
# GKE module from registry
module "gke" {
source = "terraform-google-modules/kubernetes-engine/google//modules/autopilot"
version = "~> 30.0"
project_id = var.project_id
name = "${var.environment}-cluster"
region = var.region
network = module.vpc.network_name
subnetwork = "${var.environment}-subnet"
ip_range_pods = "pods"
ip_range_services = "services"
}
Module Versioning
# Pin to a specific version (recommended)
module "vpc" {
source = "terraform-google-modules/network/google"
version = "9.1.0"
# ...
}
# Pin to a Git tag
module "custom_module" {
source = "git::https://github.com/myorg/terraform-modules.git//vpc?ref=v1.2.0"
}
Common Mistakes
| Mistake | Why It’s Wrong | Fix |
|---|---|---|
| No module versioning | Breaking changes | Pin module versions |
| Monolithic modules | Too rigid, hard to compose | Keep modules focused and small |
| Hardcoding values in modules | Not reusable | Use variables for all configurable values |
| No outputs | Can’t compose modules | Export all IDs, names, and URLs |
| Copy-pasting instead of modules | Drift between environments | Extract into modules |
Quick Reference
| Concept | Example |
|---|---|
| Local module | source = "../../modules/vpc" |
| Registry module | source = "terraform-google-modules/network/google" |
| Git module | source = "git::https://github.com/org/repo.git//path?ref=v1.0" |
| Version pin | version = "~> 9.0" |
| Module output | module.vpc.network_id |
Next → Cloud Foundation Toolkit