Skip to main content

Terraform

1. Overview

All GCP infrastructure is provisioned via Terraform. The configuration follows a module-based approach with per-environment variable files for staging and production. State is managed remotely via Terraform Cloud.


2. Directory Structure

terraform/
├── variables.tf # Common variable definitions
├── outputs.tf # Root outputs
├── main.tf # Module orchestration and backend config
├── environments/
│ ├── staging/
│ │ └── terraform.tfvars
│ └── production/
│ └── terraform.tfvars
└── modules/
├── apphub/ # Application Hub registration
├── artifact-registry/ # Docker image registry
├── cloud-run/ # Cloud Run services
├── firebase/ # Firebase project enablement
├── iam/ # IAM roles, service accounts, and WIF
├── identity-platform/ # Identity Platform tenants and providers
├── kms/ # Cloud KMS keys for encryption
├── load-balancer/ # Cloud Load Balancer (HTTPS)
├── monitoring/ # Cloud Monitoring services and SLOs
├── networking/ # VPC, subnets, connector, and DNS
├── project/ # Placeholder for project-level resources
├── pubsub/ # Pub/Sub topics and subscriptions
├── secrets/ # Secret Manager secrets
├── security/ # Cloud Armor WAF and SSL policies
├── spanner/ # Cloud Spanner instance, database, and backups
└── storage/ # Cloud Storage buckets

3. Backend Configuration

# main.tf
terraform {
required_version = ">= 1.7.0"

required_providers {
google = {
source = "hashicorp/google"
version = "~> 7.0"
}
google-beta = {
source = "hashicorp/google-beta"
version = "~> 7.0"
}
}

backend "remote" {
hostname = "app.terraform.io"
organization = "peaksystems"
workspaces {
name = "gateway"
}
}
}

4. Module Specifications

4.1 Project Module

The project module is currently a placeholder as API enablement and core project configurations are handled in the root main.tf file to ensure proper ordering.

# main.tf (API enablement)
resource "google_project_service" "apis" {
for_each = toset([
"run.googleapis.com",
"spanner.googleapis.com",
"pubsub.googleapis.com",
"secretmanager.googleapis.com",
"artifactregistry.googleapis.com",
"compute.googleapis.com",
"vpcaccess.googleapis.com",
"cloudresourcemanager.googleapis.com",
"firebase.googleapis.com",
"identitytoolkit.googleapis.com",
"monitoring.googleapis.com",
"logging.googleapis.com",
"cloudtrace.googleapis.com",
"cloudkms.googleapis.com",
"iam.googleapis.com",
"apphub.googleapis.com",
"dns.googleapis.com",
"storage.googleapis.com",
])

project = var.project_id
service = each.value
disable_on_destroy = false
}

4.2 Networking Module

Implements the VPC, subnets, serverless VPC access connector, and firewall rules. It also configures Private Google Access via Cloud DNS.

# modules/networking/main.tf
resource "google_compute_network" "vpc" {
name = "gateway-vpc"
auto_create_subnetworks = false
project = var.project_id
}

resource "google_compute_subnetwork" "subnet" {
name = "gateway-subnet"
ip_cidr_range = "10.0.0.0/24"
region = var.region
network = google_compute_network.vpc.id
project = var.project_id
}

resource "google_vpc_access_connector" "connector" {
name = "gateway-vpc-connector"
region = var.region
network = google_compute_network.vpc.name
ip_cidr_range = "10.8.0.0/28"
project = var.project_id
}

# Private Google Access DNS and routes are also configured here

4.3 Cloud Run Module

Deploys microservices using for_each. Services are internal-only by default (accessible via Load Balancer or internal VPC). Includes probes and IAM bindings.

# modules/cloud-run/main.tf
resource "google_cloud_run_v2_service" "service" {
for_each = var.services

name = "gateway-${each.key}"
location = var.region
project = var.project_id
ingress = "INGRESS_TRAFFIC_INTERNAL_LOAD_BALANCER"

template {
service_account = var.service_accounts[each.key]

vpc_access {
network_interfaces {
network = var.vpc_network_id
subnetwork = var.vpc_subnet_id
tags = ["cloud-run"]
}
egress = "PRIVATE_RANGES_ONLY"
}

containers {
image = each.value.image

startup_probe {
http_get { path = "/health" }
}

liveness_probe {
http_get { path = "/health" }
}

# Environment variables and secrets mapped dynamically
}
}
}

4.4 Spanner Module

Configures the Cloud Spanner instance and database with CMEK encryption and a daily backup schedule.

# modules/spanner/main.tf
resource "google_spanner_instance" "instance" {
name = "gateway-spanner"
config = "regional-${var.region}"
processing_units = var.spanner_processing_units
project = var.project_id
}

resource "google_spanner_database" "database" {
instance = google_spanner_instance.instance.name
name = "gateway-db"
project = var.project_id
database_dialect = "POSTGRESQL"

encryption_config {
kms_key_name = var.kms_key_id
}
}

resource "google_spanner_backup_schedule" "daily" {
instance = google_spanner_instance.instance.name
database = google_spanner_database.database.name
name = "daily-backup"
spec {
cron_spec { text = "0 2 * * *" }
}
}

5. Environment Variables

Staging (terraform.tfvars)

environment = "staging"
project_id = "peak-gateway-staging"
project_number = "" # Set after project creation
region = "us-central1"
spanner_processing_units = 100

cloud_run_deletion_protection = false

microservice_min_instances = 0
microservice_max_instances = 5
microservice_warm_services = []

identity_saml_callback_uris = ["https://peak-gateway-staging.firebaseapp.com/__/auth/handler"]

Production (terraform.tfvars)

environment = "production"
project_id = "peak-gateway-prod"
project_number = "" # Set after project creation
region = "us-central1"
spanner_processing_units = 1000

cloud_run_deletion_protection = true

microservice_min_instances = 1
microservice_max_instances = 20
microservice_warm_services = ["processing", "online-txn"]

identity_saml_callback_uris = ["https://peak-gateway-prod.firebaseapp.com/__/auth/handler"]

6. Deployment Commands

# Initialize with Terraform Cloud
cd terraform
terraform init

# Select workspace/environment is handled via Terraform Cloud or local workspace selection
# To plan/apply for a specific environment using local files:

# Staging
terraform plan -var-file=environments/staging/terraform.tfvars
terraform apply -var-file=environments/staging/terraform.tfvars

# Production
terraform plan -var-file=environments/production/terraform.tfvars
terraform apply -var-file=environments/production/terraform.tfvars