Add GCP terraform standard templates

This commit is contained in:
shenlan 2025-11-20 21:37:34 +08:00
parent 5e838f76f1
commit 60e4e4a79c
31 changed files with 1127 additions and 0 deletions

View File

@ -0,0 +1,32 @@
# GCP Cloud Terraform Standard
该目录提供与 `aws-cloud` 模板一一对应的 GCP 版本,用于在 GCP 上快速引导基础设施。结构与 AWS 目录保持一致,包括引导阶段 (bootstrap)、环境示例 (envs) 与模块库 (modules)。
## 模板映射
- **bootstrap-dynamodb → Firestore**:使用 FirestoreDatastore 模式)作为无服务器键值存储。
- **bootstrap-iam → IAM**:创建基础服务账号与自定义角色,替代 AWS IAM 角色与策略。
- **bootstrap-s3 → Cloud Storage**:创建 GCS 存储桶并启用版本化,对应 AWS S3。
- **modules**保留原始模块命名alb、nlb、vpc 等),内部实现改为 GCP 资源:
- `alb`/`nlb`:使用 Google HTTP(S) / TCP 负载均衡。
- `ec2`:映射到 Compute Engine 实例或 MIG。
- `keypair`:生成 SSH 密钥并写入元数据。
- `msk`:映射到 Pub/Sub发布/订阅)。
- `rds`:映射到 Cloud SQL。
- `s3`:映射到 Cloud Storage。
- `vpc`:使用 VPC 网络与子网。
- `ami_lookup`映射到最新公共镜像查找debian/ubuntu
- `iam`:分配 IAM 角色与绑定。
- `landingzone`:创建基础网络、日志与审计配置。
- `redis`:映射到 Memorystore。
- `sg`:映射到 VPC 防火墙规则。
## 使用方式
1. 在 `config/backend.tf` 中配置远端状态GCS 存储桶)。
2. 在 `config/provider.tf` 中设置 `project`、`region`、`credentials` 等参数。
3. 按需修改 `envs` 下的环境示例,执行:
```bash
terraform -chdir=envs/dev init
terraform -chdir=envs/dev apply
```
本目录仅新增 GCP 代码,不改动现有 AWS 模板。

View File

@ -0,0 +1,42 @@
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 5.0"
}
}
}
variable "project_id" {
description = "GCP project id where Firestore will be enabled"
type = string
}
variable "location" {
description = "Firestore location"
type = string
default = "us-central"
}
resource "google_project_service" "firestore" {
service = "firestore.googleapis.com"
project = var.project_id
}
resource "google_project_service" "cloudresourcemanager" {
service = "cloudresourcemanager.googleapis.com"
project = var.project_id
}
resource "google_firestore_database" "default" {
name = "(default)"
location_id = var.location
project = var.project_id
type = "DATASTORE_MODE"
depends_on = [google_project_service.firestore, google_project_service.cloudresourcemanager]
}
output "firestore_database" {
description = "Firestore database ID"
value = google_firestore_database.default.name
}

View File

@ -0,0 +1,47 @@
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 5.0"
}
}
}
variable "project_id" {
description = "Target project for IAM bootstrap"
type = string
}
variable "service_account_id" {
description = "ID of the bootstrap service account"
type = string
default = "terraform-bootstrap"
}
variable "service_account_roles" {
description = "List of roles to attach to the bootstrap service account"
type = list(string)
default = [
"roles/resourcemanager.projectIamAdmin",
"roles/storage.admin",
"roles/compute.admin"
]
}
resource "google_service_account" "bootstrap" {
account_id = var.service_account_id
display_name = "Terraform Bootstrap"
project = var.project_id
}
resource "google_project_iam_member" "bootstrap" {
for_each = toset(var.service_account_roles)
project = var.project_id
role = each.value
member = "serviceAccount:${google_service_account.bootstrap.email}"
}
output "service_account_email" {
value = google_service_account.bootstrap.email
description = "Bootstrap service account email"
}

View File

@ -0,0 +1,47 @@
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 5.0"
}
}
}
variable "project_id" {
description = "Project id where the state bucket will be created"
type = string
}
variable "bucket_name" {
description = "Name of the GCS bucket"
type = string
}
variable "location" {
description = "Bucket location"
type = string
default = "US"
}
resource "google_storage_bucket" "state" {
name = var.bucket_name
location = var.location
project = var.project_id
uniform_bucket_level_access = true
versioning {
enabled = true
}
lifecycle_rule {
action {
type = "Delete"
}
condition {
age = 365
}
}
}
output "bucket" {
value = google_storage_bucket.state.name
description = "Created state bucket"
}

View File

@ -0,0 +1,9 @@
terraform {
required_version = ">= 1.5.0"
backend "gcs" {
bucket = var.state_bucket
prefix = var.state_prefix
project = var.project_id
}
}

View File

@ -0,0 +1,24 @@
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 5.0"
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 5.0"
}
}
}
provider "google" {
project = var.project_id
region = var.region
zone = var.zone
}
provider "google-beta" {
project = var.project_id
region = var.region
zone = var.zone
}

View File

@ -0,0 +1,27 @@
variable "project_id" {
description = "GCP project id"
type = string
}
variable "region" {
description = "Default region"
type = string
default = "us-central1"
}
variable "zone" {
description = "Default zone"
type = string
default = "us-central1-a"
}
variable "state_bucket" {
description = "GCS bucket used for Terraform remote state"
type = string
}
variable "state_prefix" {
description = "Prefix within the state bucket"
type = string
default = "terraform/state"
}

View File

@ -0,0 +1,27 @@
terraform {
required_version = ">= 1.5.0"
required_providers {
google = {
source = "hashicorp/google"
version = ">= 5.0"
}
}
}
variable "project_id" { type = string }
provider "google" {
project = var.project_id
region = "us-central1"
}
module "alb" {
source = "../../modules/alb"
project_id = var.project_id
bucket_name = "dev-alb-static-${var.project_id}"
name = "dev-alb"
}
output "forwarding_rule" {
value = module.alb.forwarding_rule
}

View File

@ -0,0 +1,48 @@
terraform {
required_version = ">= 1.5.0"
required_providers {
google = { source = "hashicorp/google" version = ">= 5.0" }
}
}
variable "project_id" { type = string }
variable "region" { type = string default = "us-central1" }
variable "zone" { type = string default = "us-central1-a" }
provider "google" {
project = var.project_id
region = var.region
zone = var.zone
}
module "vpc" {
source = "../../modules/vpc"
project_id = var.project_id
subnets = [{
name = "ec2-subnet"
ip_cidr_range = "10.40.0.0/24"
region = var.region
}]
}
data "google_client_config" "current" {}
module "ami" {
source = "../../modules/ami_lookup"
}
module "vm" {
source = "../../modules/ec2"
project_id = var.project_id
name = "dev-compute"
zone = var.zone
machine_type = "e2-medium"
network = module.vpc.network_self_link
subnet = module.vpc.subnet_self_links[0]
image = module.ami.image
ssh_keys = ["terraform:${data.google_client_config.current.access_token}"]
}
output "instance" {
value = module.vm.instance_self_link
}

View File

@ -0,0 +1,24 @@
terraform {
required_version = ">= 1.5.0"
required_providers {
google = { source = "hashicorp/google" version = ">= 5.0" }
}
}
variable "project_id" { type = string }
provider "google" {
project = var.project_id
region = "us-central1"
}
module "pubsub" {
source = "../../modules/msk"
project_id = var.project_id
topic = "dev-topic"
subscription = "dev-subscription"
}
output "topic" {
value = module.pubsub.topic
}

View File

@ -0,0 +1,28 @@
terraform {
required_version = ">= 1.5.0"
required_providers {
google = { source = "hashicorp/google" version = ">= 5.0" }
}
}
variable "project_id" { type = string }
provider "google" {
project = var.project_id
region = "us-central1"
}
module "landingzone" {
source = "../../modules/landingzone"
project_id = var.project_id
services = [
"compute.googleapis.com",
"pubsub.googleapis.com",
"sqladmin.googleapis.com",
"redis.googleapis.com"
]
}
output "services" {
value = module.landingzone.enabled_services
}

View File

@ -0,0 +1,43 @@
terraform {
required_version = ">= 1.5.0"
required_providers {
google = {
source = "hashicorp/google"
version = ">= 5.0"
}
}
}
variable "project_id" { type = string }
variable "region" { type = string default = "us-central1" }
variable "zone" { type = string default = "us-central1-a" }
provider "google" {
project = var.project_id
region = var.region
zone = var.zone
}
module "vpc" {
source = "../../modules/vpc"
project_id = var.project_id
subnets = [{
name = "nlb-subnet"
ip_cidr_range = "10.30.0.0/24"
region = var.region
}]
}
module "nlb" {
source = "../../modules/nlb"
project_id = var.project_id
network = module.vpc.network_self_link
subnet = module.vpc.subnet_self_links[0]
port = 8080
zone = var.zone
name = "dev-nlb"
}
output "forwarding_rule" {
value = module.nlb.forwarding_rule
}

View File

@ -0,0 +1,24 @@
terraform {
required_version = ">= 1.5.0"
required_providers {
google = { source = "hashicorp/google" version = ">= 5.0" }
}
}
variable "project_id" { type = string }
provider "google" {
project = var.project_id
region = "us-central1"
}
module "bucket" {
source = "../../modules/s3"
project_id = var.project_id
name = "dev-object-${var.project_id}"
location = "US"
}
output "bucket" {
value = module.bucket.bucket
}

View File

@ -0,0 +1,27 @@
terraform {
required_version = ">= 1.5.0"
required_providers {
google = { source = "hashicorp/google" version = ">= 5.0" }
}
}
variable "project_id" { type = string }
variable "region" { type = string default = "us-central1" }
provider "google" {
project = var.project_id
region = var.region
}
module "sql" {
source = "../../modules/rds"
project_id = var.project_id
name = "dev-postgres"
database_version = "POSTGRES_15"
region = var.region
tier = "db-custom-1-3840"
}
output "connection_name" {
value = module.sql.connection_name
}

View File

@ -0,0 +1,26 @@
terraform {
required_version = ">= 1.5.0"
required_providers {
google = { source = "hashicorp/google" version = ">= 5.0" }
}
}
variable "project_id" { type = string }
variable "region" { type = string default = "us-central1" }
provider "google" {
project = var.project_id
region = var.region
}
module "redis" {
source = "../../modules/redis"
project_id = var.project_id
name = "dev-redis"
region = var.region
memory_size_gb = 2
}
output "redis_host" {
value = module.redis.host
}

View File

@ -0,0 +1,25 @@
terraform {
required_version = ">= 1.5.0"
required_providers {
google = { source = "hashicorp/google" version = ">= 5.0" }
}
}
variable "project_id" { type = string }
provider "google" {
project = var.project_id
region = "us-central1"
}
module "iam" {
source = "../../modules/iam"
project_id = var.project_id
bindings = [
{ role = "roles/storage.objectViewer", member = "allAuthenticatedUsers" }
]
}
output "roles" {
value = module.iam.applied_bindings
}

View File

@ -0,0 +1,33 @@
terraform {
required_version = ">= 1.5.0"
required_providers {
google = {
source = "hashicorp/google"
version = ">= 5.0"
}
}
}
variable "project_id" { type = string }
variable "region" { type = string default = "us-central1" }
provider "google" {
project = var.project_id
region = var.region
}
module "vpc" {
source = "../../modules/vpc"
project_id = var.project_id
subnets = [
{
name = "dev-subnet"
ip_cidr_range = "10.20.0.0/24"
region = var.region
}
]
}
output "network" {
value = module.vpc.network_self_link
}

View File

@ -0,0 +1,34 @@
terraform {
required_version = ">= 1.5.0"
required_providers {
google = {
source = "hashicorp/google"
version = ">= 5.0"
}
}
}
variable "project_id" {
type = string
description = "Target project"
}
variable "region" {
type = string
default = "us-central1"
}
provider "google" {
project = var.project_id
region = var.region
}
module "landingzone" {
source = "../../modules/landingzone"
project_id = var.project_id
}
output "enabled_services" {
value = module.landingzone.enabled_services
description = "APIs enabled for the project"
}

View File

@ -0,0 +1,59 @@
variable "project_id" {
description = "Project id"
type = string
}
variable "name" {
description = "Load balancer name"
type = string
default = "http-lb"
}
variable "bucket_name" {
description = "Name for the backend bucket"
type = string
}
resource "google_storage_bucket" "static" {
name = var.bucket_name
location = "US"
project = var.project_id
uniform_bucket_level_access = true
website {
main_page_suffix = "index.html"
not_found_page = "404.html"
}
}
resource "google_compute_backend_bucket" "static" {
name = "${var.name}-backend"
bucket_name = google_storage_bucket.static.name
enable_cdn = true
}
resource "google_compute_url_map" "static" {
name = "${var.name}-url-map"
default_service = google_compute_backend_bucket.static.self_link
}
resource "google_compute_target_http_proxy" "static" {
name = "${var.name}-http-proxy"
url_map = google_compute_url_map.static.self_link
}
resource "google_compute_global_forwarding_rule" "static" {
name = "${var.name}-fwd"
port_range = "80"
target = google_compute_target_http_proxy.static.self_link
load_balancing_scheme = "EXTERNAL"
}
output "bucket" {
value = google_storage_bucket.static.name
description = "Static site bucket"
}
output "forwarding_rule" {
value = google_compute_global_forwarding_rule.static.name
description = "HTTP forwarding rule"
}

View File

@ -0,0 +1,21 @@
variable "family" {
description = "Image family to lookup"
type = string
default = "debian-12"
}
variable "project" {
description = "Project hosting the image"
type = string
default = "debian-cloud"
}
data "google_compute_image" "family" {
family = var.family
project = var.project
}
output "image" {
value = data.google_compute_image.family.self_link
description = "Self link of the resolved image"
}

View File

@ -0,0 +1,70 @@
variable "project_id" {
description = "Project id"
type = string
}
variable "name" {
description = "Instance name"
type = string
}
variable "zone" {
description = "Instance zone"
type = string
default = "us-central1-a"
}
variable "machine_type" {
description = "Machine type"
type = string
default = "e2-medium"
}
variable "network" {
description = "Network self link"
type = string
}
variable "subnet" {
description = "Subnetwork self link"
type = string
}
variable "image" {
description = "Source image"
type = string
}
variable "ssh_keys" {
description = "SSH key metadata entries"
type = list(string)
default = []
}
resource "google_compute_instance" "vm" {
name = var.name
project = var.project_id
zone = var.zone
machine_type = var.machine_type
boot_disk {
initialize_params {
image = var.image
}
}
network_interface {
network = var.network
subnetwork = var.subnet
access_config {}
}
metadata = length(var.ssh_keys) > 0 ? {
ssh-keys = join("\n", var.ssh_keys)
} : {}
}
output "instance_self_link" {
value = google_compute_instance.vm.self_link
description = "Instance self link"
}

View File

@ -0,0 +1,25 @@
variable "project_id" {
type = string
description = "Project id"
}
variable "bindings" {
type = list(object({
role = string
member = string
}))
description = "List of role/member bindings"
default = []
}
resource "google_project_iam_member" "bindings" {
for_each = { for idx, binding in var.bindings : idx => binding }
project = var.project_id
role = each.value.role
member = each.value.member
}
output "applied_bindings" {
value = [for binding in google_project_iam_member.bindings : binding.role]
description = "Roles applied to members"
}

View File

@ -0,0 +1,36 @@
terraform {
required_providers {
tls = {
source = "hashicorp/tls"
version = ">= 4.0"
}
}
}
variable "algorithm" {
type = string
description = "Algorithm for the SSH key"
default = "RSA"
}
variable "rsa_bits" {
type = number
description = "RSA key length when algorithm is RSA"
default = 4096
}
resource "tls_private_key" "ssh" {
algorithm = var.algorithm
rsa_bits = var.rsa_bits
}
output "public_key_openssh" {
value = tls_private_key.ssh.public_key_openssh
description = "Generated public key"
}
output "private_key_pem" {
value = tls_private_key.ssh.private_key_pem
sensitive = true
description = "Generated private key"
}

View File

@ -0,0 +1,26 @@
variable "project_id" {
description = "Project id"
type = string
}
variable "services" {
description = "APIs to enable"
type = list(string)
default = [
"compute.googleapis.com",
"iam.googleapis.com",
"cloudresourcemanager.googleapis.com",
"logging.googleapis.com"
]
}
resource "google_project_service" "enabled" {
for_each = toset(var.services)
project = var.project_id
service = each.key
}
output "enabled_services" {
value = [for s in google_project_service.enabled : s.service]
description = "List of enabled services"
}

View File

@ -0,0 +1,36 @@
variable "project_id" {
description = "Project id"
type = string
}
variable "topic" {
description = "Pub/Sub topic name"
type = string
default = "default-topic"
}
variable "subscription" {
description = "Subscription name"
type = string
default = "default-subscription"
}
resource "google_pubsub_topic" "this" {
name = var.topic
project = var.project_id
}
resource "google_pubsub_subscription" "this" {
name = var.subscription
topic = google_pubsub_topic.this.name
}
output "topic" {
value = google_pubsub_topic.this.name
description = "Pub/Sub topic name"
}
output "subscription" {
value = google_pubsub_subscription.this.name
description = "Pub/Sub subscription name"
}

View File

@ -0,0 +1,78 @@
variable "project_id" {
description = "Project id"
type = string
}
variable "name" {
description = "Load balancer name"
type = string
default = "tcp-lb"
}
variable "network" {
description = "Network self link"
type = string
}
variable "subnet" {
description = "Subnetwork self link"
type = string
}
variable "port" {
description = "Service port"
type = number
default = 80
}
variable "zone" {
description = "Zone for unmanaged instance group"
type = string
default = "us-central1-a"
}
resource "google_compute_instance_group" "placeholder" {
name = "${var.name}-ig"
project = var.project_id
zone = var.zone
network = var.network
named_port {
name = "service"
port = var.port
}
}
resource "google_compute_health_check" "tcp" {
name = "${var.name}-hc"
project = var.project_id
tcp_health_check {
port = var.port
}
}
resource "google_compute_backend_service" "tcp" {
name = "${var.name}-backend"
project = var.project_id
load_balancing_scheme = "EXTERNAL"
protocol = "TCP"
health_checks = [google_compute_health_check.tcp.self_link]
backend {
group = google_compute_instance_group.placeholder.self_link
}
}
resource "google_compute_forwarding_rule" "tcp" {
name = "${var.name}-fwd"
project = var.project_id
load_balancing_scheme = "EXTERNAL"
ip_protocol = "TCP"
port_range = tostring(var.port)
backend_service = google_compute_backend_service.tcp.self_link
network = var.network
subnetwork = var.subnet
}
output "forwarding_rule" {
value = google_compute_forwarding_rule.tcp.name
description = "TCP forwarding rule"
}

View File

@ -0,0 +1,44 @@
variable "project_id" {
description = "Project id"
type = string
}
variable "name" {
description = "Instance name"
type = string
default = "default-sql"
}
variable "database_version" {
description = "Cloud SQL engine"
type = string
default = "POSTGRES_15"
}
variable "tier" {
description = "Machine tier"
type = string
default = "db-f1-micro"
}
variable "region" {
description = "Instance region"
type = string
default = "us-central1"
}
resource "google_sql_database_instance" "this" {
name = var.name
project = var.project_id
region = var.region
database_version = var.database_version
settings {
tier = var.tier
}
}
output "connection_name" {
value = google_sql_database_instance.this.connection_name
description = "Instance connection string"
}

View File

@ -0,0 +1,41 @@
variable "project_id" {
description = "Project id"
type = string
}
variable "name" {
description = "Redis instance name"
type = string
default = "default-redis"
}
variable "region" {
description = "Region for the instance"
type = string
default = "us-central1"
}
variable "tier" {
description = "Service tier"
type = string
default = "STANDARD_HA"
}
variable "memory_size_gb" {
description = "Memory size"
type = number
default = 1
}
resource "google_redis_instance" "this" {
name = var.name
project = var.project_id
region = var.region
tier = var.tier
memory_size_gb = var.memory_size_gb
}
output "host" {
value = google_redis_instance.this.host
description = "Redis host"
}

View File

@ -0,0 +1,28 @@
variable "project_id" {
description = "Project id"
type = string
}
variable "name" {
description = "Bucket name"
type = string
}
variable "location" {
description = "Bucket location"
type = string
default = "US"
}
resource "google_storage_bucket" "this" {
name = var.name
project = var.project_id
location = var.location
uniform_bucket_level_access = true
versioning { enabled = true }
}
output "bucket" {
value = google_storage_bucket.this.name
description = "Storage bucket"
}

View File

@ -0,0 +1,45 @@
variable "project_id" {
description = "Project id"
type = string
}
variable "network" {
description = "Network self link"
type = string
}
variable "rules" {
description = "Firewall rules"
type = list(object({
name = string
direction = string
ranges = list(string)
protocols = map(list(number))
target_tags = list(string)
}))
default = []
}
resource "google_compute_firewall" "rules" {
for_each = { for rule in var.rules : rule.name => rule }
name = each.value.name
project = var.project_id
network = var.network
direction = upper(each.value.direction)
priority = 1000
allow = [for proto, ports in each.value.protocols : {
protocol = proto
ports = [for port in ports : tostring(port)]
}]
source_ranges = each.value.direction == "ingress" ? each.value.ranges : null
destination_ranges = each.value.direction == "egress" ? each.value.ranges : null
target_tags = each.value.target_tags
}
output "firewall_rules" {
value = [for rule in google_compute_firewall.rules : rule.name]
description = "Created firewall rules"
}

View File

@ -0,0 +1,51 @@
variable "project_id" {
description = "Project id"
type = string
}
variable "network_name" {
description = "Name of the VPC network"
type = string
default = "main-vpc"
}
variable "subnets" {
description = "List of subnet definitions"
type = list(object({
name = string
ip_cidr_range = string
region = string
}))
default = [
{
name = "default-subnet"
ip_cidr_range = "10.10.0.0/24"
region = "us-central1"
}
]
}
resource "google_compute_network" "this" {
name = var.network_name
project = var.project_id
auto_create_subnetworks = false
}
resource "google_compute_subnetwork" "this" {
for_each = { for subnet in var.subnets : subnet.name => subnet }
name = each.value.name
ip_cidr_range = each.value.ip_cidr_range
region = each.value.region
network = google_compute_network.this.id
private_ip_google_access = true
}
output "network_self_link" {
value = google_compute_network.this.self_link
description = "VPC network self link"
}
output "subnet_self_links" {
value = [for subnet in google_compute_subnetwork.this : subnet.self_link]
description = "Subnetwork self links"
}