「GCP 基础设施实战」

用 Terraform 在 Google Cloud 落地基础设施:GCE/GKE/CloudSQL 组合编排、服务账户与最小权限、VPC 网络与负载均衡,以及成本优化与标签治理。

1. Google Provider 配置与认证

一句话总结: google Provider 通过 project 与凭证链完成初始化,生产推荐用服务账户(SA)的 JSON 密钥或 Workload Identity,避免在代码中硬编码密钥。

Google Cloud 以 Project 为资源边界。动手前先把 Project ID、区域(region)与可用区(zone)固定下来,Provider 用 google 与 google-beta 两个版本覆盖 GA 与预览 API。

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
}

1.1 凭证方式的取舍

方式配置途径适用场景
环境变量GOOGLE_APPLICATION_CREDENTIALS 指向 JSONCI 注入、本地开发
gcloud 登录gcloud auth application-default login单机日常开发
服务账户credentials 字段或 SA 密钥文件团队统一身份
Workload Identity运行在 GKE 上的负载自动获取云端 Runner、Pod 内运行

生产环境最推荐 服务账户 + Workload Identity 的组合:代码里不出现任何长期密钥,权限由 IAM 统一治理。

export GOOGLE_APPLICATION_CREDENTIALS="$HOME/.config/gcp/platform-sa.json"
gcloud config set project my-project
terraform plan

一句话:Provider 是「配置模板」,Project 是「资源归属」,凭证决定「谁在操作」,三者先行定好再谈资源。

2. 服务账户与权限

一句话总结: 服务账户是 GCP 的身份实体,用 google_service_account 声明、google_project_iam_member 赋权,遵循「一角色一职责」的最小权限原则。

GCP 权限体系以服务账户(Service Account)与 IAM 角色为核心。先建 SA,再按资源作用域绑定角色。

resource "google_service_account" "app" {
  account_id   = "app-runner"
  display_name = "应用运行服务账户"
}

resource "google_project_iam_member" "app_logging" {
  project = var.project_id
  role    = "roles/logging.logWriter"
  member  = "serviceAccount:${google_service_account.app.email}"
}

resource "google_storage_bucket_iam_member" "app_assets" {
  bucket = google_storage_bucket.assets.name
  role   = "roles/storage.objectViewer"
  member = "serviceAccount:${google_service_account.app.email}"
}

一句话:SA 是身份,IAM 绑定是权限,作用域限定到 Project、Bucket、Topic 等具体资源,权限泛滥的根子就在「给了过大的角色」。

3. VPC 网络与负载均衡

一句话总结: GCP 的 VPC 是全局网络,子网按区域划分,防火墙规则按标签放行,负载均衡由转发规则 + 后端服务组合,跨区域可用 Global LB。

GCP VPC 的一个特点是「全局网络 + 区域子网」:VPC 覆盖整个 Project,子网才绑定区域。防火墙规则用网络标签(network tag)精确控制目标实例。

resource "google_compute_network" "main" {
  name                    = "vpc-${var.environment}"
  auto_create_subnetworks = false
}

resource "google_compute_subnetwork" "web" {
  name          = "subnet-web-${var.region}"
  network       = google_compute_network.main.id
  region        = var.region
  ip_cidr_range = "10.10.1.0/24"
}

resource "google_compute_firewall" "allow_web" {
  name    = "fw-allow-web"
  network = google_compute_network.main.name

  allow {
    protocol = "tcp"
    ports    = ["80", "443"]
  }
  source_ranges = ["0.0.0.0/0"]
  target_tags   = ["web"]
}

3.1 全球负载均衡

对外服务用 google_compute_global_forwarding_rule + google_compute_backend_service,把多区域实例组聚合成一个公网入口。

resource "google_compute_backend_service" "web" {
  name          = "backend-web"
  port_name     = "http"
  protocol      = "HTTP"
  load_balancing_scheme = "EXTERNAL"

  backend {
    group = google_compute_instance_group.web.id
  }

  health_checks = [google_compute_health_check.web.id]
}

resource "google_compute_health_check" "web" {
  name               = "hc-web"
  check_interval_sec = 10

  http_health_check {
    port = 80
    path = "/healthz"
  }
}

resource "google_compute_global_forwarding_rule" "web" {
  name       = "fw-global-web"
  target     = google_compute_target_http_proxy.web.id
  port_range = "80"
}

一句话:GCP 网络以「全局 VPC + 区域子网 + 防火墙标签」组织,负载均衡把后端实例组抽象成一个稳定入口,跨区域容灾交给 Global LB。

4. GCE 计算实例

一句话总结: GCE 用 google_compute_instance 声明,启动脚本走 metadata 的 startup-script,实例模板 + 实例组是横向伸缩的标准姿势。

单台 VM 用 google_compute_instance,生产建议用实例模板(instance template)+ 托管实例组(MIG)承接自动伸缩与滚动更新。

resource "google_compute_instance" "web" {
  name         = "web-${var.environment}"
  machine_type = "e2-small"
  zone         = var.zone

  boot_disk {
    initialize_params {
      image = "ubuntu-os-cloud/ubuntu-2204-lts"
      size  = 20
    }
  }

  network_interface {
    network    = google_compute_network.main.name
    subnetwork = google_compute_subnetwork.web.name
    access_config {} # 分配临时公网 IP
  }

  metadata_startup_script = <<-EOT
    #!/bin/bash
    apt-get update -y
    apt-get install -y nginx
    systemctl enable nginx
  EOT

  service_account {
    email  = google_service_account.app.email
    scopes = ["cloud-platform"]
  }

  tags = ["web"]
}

4.1 实例模板与托管实例组

把启动逻辑与磁盘配置写进模板,MIG 按 min/max 自动扩缩,健康检查失败自动重建。

resource "google_compute_instance_template" "web" {
  name         = "tmpl-web"
  machine_type = "e2-small"

  disk {
    source_image = "ubuntu-os-cloud/ubuntu-2204-lts"
    auto_delete  = true
  }

  network_interface {
    network = google_compute_network.main.name
  }

  metadata_startup_script = "systemctl start nginx"
}

resource "google_compute_region_instance_group_manager" "web" {
  name = "mig-web"

  base_instance_name = "web"
  region             = var.region
  target_size        = 3

  version {
    instance_template = google_compute_instance_template.web.id
  }

  named_port {
    name = "http"
    port = 80
  }
}

一句话:模板定义「长什么样」,MIG 定义「多少个、怎么伸缩」,滚动更新只需换模板版本。

5. GKE 集群编排

一句话总结: GKE 用 google_container_cluster 声明控制面与默认节点池,业务负载放独立 NodePool,身份走 Workload Identity,kubeconfig 用 gcloud 安全获取。

GKE 是 GCP 的托管 Kubernetes。集群声明在 google_container_cluster,额外节点池用 google_container_node_pool。

resource "google_container_cluster" "gke" {
  name     = "gke-${var.environment}"
  location = var.region

  remove_default_node_pool = true
  initial_node_count       = 1

  network    = google_compute_network.main.name
  subnetwork = google_compute_subnetwork.web.name

  workload_identity_config {
    workload_pool = "${var.project_id}.svc.id.goog"
  }
}

resource "google_container_node_pool" "primary" {
  name       = "primary"
  location   = var.region
  cluster    = google_container_cluster.gke.name
  node_count = 3

  node_config {
    machine_type = "e2-standard-2"
    oauth_scopes = [
      "https://www.googleapis.com/auth/cloud-platform",
    ]
  }
}

5.1 Workload Identity

把 GKE 上的 Pod 身份映射到服务账户,避免把 SA 密钥烧进镜像。

resource "google_project_iam_member" "gke_app" {
  project = var.project_id
  role    = "roles/cloudsql.client"
  member  = "serviceAccount:${var.project_id}.svc.id.goog[default/app]"
}

一句话:GKE 托管控制面、自管节点池,Workload Identity 让 Pod 以服务账户身份访问 GCP API,是容器上云的安全基线。

6. CloudSQL 数据库

一句话总结: CloudSQL 用 google_sql_database_instance 声明,私有 IP 走 VPC、只对应用网段开放授权,开启备份、高可用与维护窗口。

数据库实例建议用私有 IP 接入 VPC,应用从内网访问;公网访问通过 authorized_networks 限定来源。

resource "google_sql_database_instance" "postgres" {
  name             = "pg-${var.environment}"
  database_version = "POSTGRES_15"
  region           = var.region

  settings {
    tier              = "db-f1-micro"
    disk_size         = 50
    disk_type         = "PD_SSD"
    availability_type = "ZONAL"

    backup_configuration {
      enabled                        = true
      start_time                     = "02:00"
      point_in_time_recovery_enabled = true
    }

    ip_configuration {
      ipv4_enabled    = false
      private_network = google_compute_network.main.id
    }
  }
}

resource "google_sql_database" "appdb" {
  name     = "appdb"
  instance = google_sql_database_instance.postgres.name
}

一句话:CloudSQL 的核心是「私有网络 + 备份 + 高可用」三件套,密码永远走密钥系统而非 IaC 仓库。

7. 成本优化与标签治理

一句话总结: GCP 成本治理靠「统一标签 + committed use discount + 自动停止」三件套,标签让账单可归属,折扣降单价,调度省空闲。

成本优化的第一步是让每笔费用可归属。用 labels 标记环境、成本中心,再用预算告警盯住异常。

resource "google_billing_budget" "monthly" {
  billing_account = var.billing_account
  display_name    = "月度预算-${var.environment}"

  budget_filter {
    projects = ["projects/${var.project_id}"]
    labels = {
      environment = var.environment
    }
  }

  amount {
    specified_amount {
      currency_code = "CNY"
      units         = 10000
    }
  }

  threshold_rules {
    threshold_percent = 0.8
  }
}

7.1 标签与调度

所有资源统一补 environment 与 cost_center 标签,开发机用 google_compute_resource_policy 定时停止。

resource "google_compute_resource_policy" "nightly_stop" {
  name   = "nightly-stop-dev"
  region = var.region

  instance_schedule_policy {
    time_zone = "Asia/Shanghai"
    schedule  = "0 22 * * *"

    vm_start_schedule {
      schedule = "0 9 * * 1-5"
    }
    vm_stop_schedule {
      schedule = "0 22 * * *"
    }
  }
}

一句话:GCP 的账单按标签聚合,打标是成本归属的前提;长期运行的服务用 Committed Use Discount,开发环境用调度停止。

8. 总结

一套真实可用的 GCP 基础设施,核心是把 Project、身份、网络、计算、容器、数据库、成本七类资源按「引用组合」的方式组织起来:

环节要点
Providerproject/region/zone + 凭证链 + google/google-beta
身份SA + IAM 绑定,作用域限定到具体资源
网络全局 VPC + 区域子网 + 防火墙标签 + Global LB
计算实例模板 + MIG 自动伸缩
容器GKE + 独立 NodePool + Workload Identity
数据库CloudSQL 私有 IP + 备份 + 高可用
成本标签 + 预算告警 + 调度停止固化成代码

一句话收尾:GCP 实战与 AWS 的最大差异在「全局 VPC」与「Project 级隔离」。把 Project 规划、SA 最小权限、标签成本治理这三件事做对,这套模板就能在 dev/staging/prod 之间稳定复制。下一篇「AWS 网络进阶」将深入 AWS 特有的 VPC 互联与多账户网络隔离。

延伸阅读

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「terraform」更多文章

  1. Helm Provider 与应用发布:值注入与回滚
  2. 模块注册表与分发:版本、文档与测试
  3. DNS 与证书编排:托管区域与自动验证