Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 110 additions & 27 deletions envs/gcp/prod/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,41 @@ locals {
enable_apps = var.enable_apps

enable_private_networking = var.enable_private_networking
vpc_connector_name = var.vpc_connector_name != "" ? var.vpc_connector_name : "${var.name_prefix}-cr-conn"

# Strictly use app_name for resource naming (Convention over Configuration)
network_name = "${var.app_name}-vpc"
subnet_name = "${var.app_name}-subnet"
artifact_registry_repo = var.artifact_registry_repo != "" ? var.artifact_registry_repo : "${var.app_name}-repo"
gcs_bucket = "${var.app_name}-storage"
cloud_sql_instance_name = var.cloud_sql_instance_name != "" ? var.cloud_sql_instance_name : "${var.app_name}-db"
redis_instance_name = var.redis_instance_name != "" ? var.redis_instance_name : "${var.app_name}-redis"
filestore_instance_name = var.filestore_instance_name != "" ? var.filestore_instance_name : "${var.app_name}-fs"
app_service_name = "${var.app_name}-backend"
ui_service_name = "${var.app_name}-ui"
orion_service_name = "${var.app_name}-orion"
campsite_service_name = "${var.app_name}-campsite"
vpc_connector_name = "${var.app_name}-cr-conn"

enable_lb = var.enable_lb

lb_routing_plan = {
domain = var.base_domain
default_backend = (var.ui_service_name != "" ? "ui" : "backend")
default_backend = "ui"
backends = {
backend = {
cloud_run_service = var.app_service_name
cloud_run_service = local.app_service_name
region = var.region
}
ui = {
cloud_run_service = var.ui_service_name
cloud_run_service = local.ui_service_name
region = var.region
}
orion = {
cloud_run_service = local.orion_service_name
region = var.region
}
campsite = {
cloud_run_service = local.campsite_service_name
region = var.region
}
}
Expand All @@ -33,41 +54,44 @@ locals {
}
}

# GKE related modules disabled/removed, Cloud Run introduced for app service

# Artifact Registry module
module "artifact_registry" {
count = local.enable_build_env ? 1 : 0
source = "../../../modules/gcp/artifact_registry"

location = var.artifact_registry_location
repo_name = var.artifact_registry_repo
repo_name = local.artifact_registry_repo
}

# Network module
module "network" {
count = local.enable_private_networking ? 1 : 0
source = "../../../modules/gcp/network"

name_prefix = var.name_prefix
app_name = var.app_name
region = var.region
network_name = var.network_name
subnet_name = var.subnet_name
network_name = local.network_name
subnet_name = local.subnet_name
subnet_cidr = var.subnet_cidr
pods_secondary_range = var.pods_secondary_range
services_secondary_range = var.services_secondary_range
}

# IAM module
module "iam" {
source = "../../../modules/gcp/iam"

project_id = var.project_id
prefix = coalesce(var.app_suffix, var.name_prefix)
app_name = coalesce(var.app_suffix, var.app_name)
service_accounts = var.iam_service_accounts
}

# Monitoring module
module "monitoring" {
source = "../../../modules/gcp/monitoring"

project_id = var.project_id
app_name = var.app_name
enable_logging = var.enable_logging
enable_monitoring = var.enable_monitoring
enable_alerts = var.enable_alerts
Expand All @@ -76,21 +100,23 @@ module "monitoring" {
log_sink_destination = var.log_sink_destination
}

# GCS module
module "gcs" {
count = local.enable_gcs ? 1 : 0
source = "../../../modules/gcp/gcs"

name = var.gcs_bucket
name = local.gcs_bucket
location = var.region
force_destroy = var.gcs_force_destroy
uniform_bucket_level_access = var.gcs_uniform_bucket_level_access
}

# Cloud SQL module
module "cloud_sql" {
count = local.enable_cloud_sql ? 1 : 0
source = "../../../modules/gcp/cloud_sql"

name = var.cloud_sql_instance_name
name = local.cloud_sql_instance_name
database_version = var.cloud_sql_database_version
region = var.region
tier = var.cloud_sql_tier
Expand All @@ -108,32 +134,34 @@ module "cloud_sql" {
deletion_protection = var.cloud_sql_deletion_protection
}

# Redis module
module "redis" {
count = local.enable_redis ? 1 : 0
source = "../../../modules/gcp/redis"

name = var.redis_instance_name
name = local.redis_instance_name
region = var.region
tier = var.redis_tier
memory_size_gb = var.redis_memory_size_gb
network = local.enable_private_networking ? module.network[0].network_self_link : ""
transit_encryption_mode = var.redis_transit_encryption_mode
}

# Filestore module
module "filestore" {
count = local.enable_filestore ? 1 : 0
source = "../../../modules/gcp/filestore"

name = var.filestore_instance_name
name = local.filestore_instance_name
location = var.zone != "" ? var.zone : "${var.region}-b"
network = local.enable_private_networking ? module.network[0].network_self_link : ""
network = local.enable_private_networking ? module.network[0].network_id : ""
tier = var.filestore_tier
capacity_gb = var.filestore_capacity_gb
file_share_name = var.filestore_file_share_name
reserved_ip_range = var.filestore_reserved_ip_range
}

# Serverless VPC Access Connector for Cloud Run private egress
# Serverless VPC Access Connector
module "vpc_connector" {
count = local.enable_private_networking ? 1 : 0
source = "../../../modules/gcp/vpc_connector"
Expand All @@ -144,14 +172,14 @@ module "vpc_connector" {
ip_cidr_range = var.vpc_connector_cidr
}

# Cloud Run module for application service
# Cloud Run: Backend
module "app_cloud_run" {
count = local.enable_apps ? 1 : 0
source = "../../../modules/gcp/cloud_run"

project_id = var.project_id
region = var.region
service_name = var.app_service_name
service_name = local.app_service_name
image = var.app_image
env_vars = var.app_env

Expand All @@ -160,18 +188,20 @@ module "app_cloud_run" {
min_instances = var.app_min_instances
max_instances = var.app_max_instances
allow_unauth = var.app_allow_unauth
container_port = 8000

vpc_connector = local.enable_private_networking ? module.vpc_connector[0].name : null
vpc_egress = var.cloud_run_vpc_egress
}

# Cloud Run: UI
module "ui_cloud_run" {
count = local.enable_apps && var.ui_service_name != "" ? 1 : 0
count = local.enable_apps ? 1 : 0
source = "../../../modules/gcp/cloud_run"

project_id = var.project_id
region = var.region
service_name = var.ui_service_name
service_name = local.ui_service_name
image = var.ui_image
env_vars = var.ui_env_vars

Expand All @@ -180,26 +210,71 @@ module "ui_cloud_run" {
min_instances = var.ui_min_instances
max_instances = var.ui_max_instances
allow_unauth = var.ui_allow_unauth
container_port = 3000

vpc_connector = local.enable_private_networking ? module.vpc_connector[0].name : null
vpc_egress = var.cloud_run_vpc_egress
}

# Cloud Run: Orion Server
module "orion_cloud_run" {
count = local.enable_apps && var.orion_image != "" ? 1 : 0
source = "../../../modules/gcp/cloud_run"

project_id = var.project_id
region = var.region
service_name = local.orion_service_name
image = var.orion_image
env_vars = var.orion_env_vars

cpu = "1"
memory = "512Mi"
min_instances = 0
max_instances = 10
allow_unauth = true
container_port = 8000

vpc_connector = local.enable_private_networking ? module.vpc_connector[0].name : null
vpc_egress = var.cloud_run_vpc_egress
}

# Cloud Run: Campsite
module "campsite_cloud_run" {
count = local.enable_apps && var.campsite_image != "" ? 1 : 0
source = "../../../modules/gcp/cloud_run"

project_id = var.project_id
region = var.region
service_name = local.campsite_service_name
image = var.campsite_image
env_vars = var.campsite_env_vars

cpu = "1"
memory = "512Mi"
min_instances = 0
max_instances = 10
allow_unauth = true
container_port = 8000

vpc_connector = local.enable_private_networking ? module.vpc_connector[0].name : null
vpc_egress = var.cloud_run_vpc_egress
}

# Load Balancer module
module "lb_backends" {
count = var.enable_lb ? 1 : 0
source = "../../../modules/gcp/load_balancer"

project_id = var.project_id
region = var.region
name_prefix = var.name_prefix
backend_service_name = var.app_service_name
ui_service_name = var.ui_service_name
app_name = var.app_name
backend_service_name = local.app_service_name
ui_service_name = local.ui_service_name
lb_domain = var.base_domain
api_path_prefixes = var.lb_api_path_prefixes
}

# Outputs adjusted (removed GKE related ones)

# Outputs
output "artifact_registry_repo" {
value = local.enable_build_env ? module.artifact_registry[0].repository : null
}
Expand Down Expand Up @@ -241,7 +316,15 @@ output "app_cloud_run_url" {
}

output "ui_cloud_run_url" {
value = local.enable_apps && var.ui_service_name != "" ? module.ui_cloud_run[0].url : null
value = local.enable_apps ? module.ui_cloud_run[0].url : null
}

output "orion_cloud_run_url" {
value = local.enable_apps && var.orion_image != "" ? module.orion_cloud_run[0].url : null
}

output "campsite_cloud_run_url" {
value = local.enable_apps && var.campsite_image != "" ? module.campsite_cloud_run[0].url : null
}

output "lb_backend_backend_service" {
Expand Down
31 changes: 19 additions & 12 deletions envs/gcp/prod/terraform.tfvars.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,44 @@

# Required project and domain
project_id = "infra-20250121-20260121-0235"
base_domain = "buck2hub.com"
app_name = "mega"
base_domain = "buck2hub.com" # used for certificates / app config

# Region / zone (optional overrides)
# region = "us-central1"
# zone = "us-central1-b"

# GCS (object storage)
gcs_bucket = "mega-prod-storage"
gcs_force_destroy = false

# Artifact Registry (container images)
enable_build_env = true
artifact_registry_repo = "mega-prod"

# Cloud Run backend application
app_service_name = "mega-backend"
# Image path format: [LOCATION]-docker.pkg.dev/[PROJECT_ID]/[REPOSITORY_ID]/[IMAGE_NAME]:[TAG]
app_image = "us-central1-docker.pkg.dev/your-gcp-project-id/mega-prod/mega-backend:mono-0.1.0-pre-release"
# Cloud Run Images
# Note: GitHub Actions will push images directly to ${app_name}-repo.
app_image = "us-central1-docker.pkg.dev/your-gcp-project-id/mega-prod/mega:mono-0.1.0-pre-release"
ui_image = "us-central1-docker.pkg.dev/your-gcp-project-id/mega-prod/mega:mega-ui-staging-0.1.0-pre-release"
orion_image = "us-central1-docker.pkg.dev/your-gcp-project-id/mega-prod/mega:orion-server-0.1.0-pre-release"
campsite_image = "us-central1-docker.pkg.dev/your-gcp-project-id/mega-prod/mega:campsite-0.1.0-pre-release"

app_env = {
RAILS_ENV = "production"
RACK_ENV = "production"
# Optimized for SQLite on Cloud Run to avoid PoolTimedOut panic
MEGA_DATABASE__DB_TYPE = "sqlite"
MEGA_DATABASE__DB_PATH = "/tmp/mega.db"
MEGA_DATABASE__MIN_CONNECTION = "1"
MEGA_DATABASE__MAX_CONNECTION = "1"
MEGA_DATABASE__ACQUIRE_TIMEOUT = "30"
}

# Cloud Run UI (Next.js SSR)
ui_service_name = "mega-ui"
# Image path format: [LOCATION]-docker.pkg.dev/[PROJECT_ID]/[REPOSITORY_ID]/[IMAGE_NAME]:[TAG]
ui_image = "us-central1-docker.pkg.dev/your-gcp-project-id/mega-prod/mega-ui:mega-ui-staging-0.1.0-pre-release"
ui_env_vars = {
APP_ENV = "staging"
}

# Database (Cloud SQL)
cloud_sql_instance_name = "mega-prod-db"
cloud_sql_instance_name = "mega-db"
Comment on lines -39 to +43
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

应该不需要这个配置,直接用app_name 拼接 db 就行

cloud_sql_db_name = "mega"
db_username = "mega_user"
db_password = "your-prod-db-password"
Expand All @@ -49,9 +53,12 @@ cloud_sql_enable_public_ip = true
vpc_connector_cidr = "10.8.0.0/28"

# Redis (Memorystore)
redis_instance_name = "mega-prod-redis"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

同理,用app_name 拼接 redis

redis_instance_name = "mega-redis"
redis_tier = "BASIC" # no HA
redis_memory_size_gb = 1

# Filestore
filestore_instance_name = "mega-fs"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

同理,用app_name 拼接 fs


# Rails secrets (sensitive)
rails_master_key = "your-prod-rails-master-key"
Loading
Loading