★★ 中級

07. Cloud SQL / Firestore

GCP の主要 DB は Cloud SQL(MySQL / PostgreSQL / SQL Server)と Firestore(NoSQL)。さらに大規模分散用に SpannerBigtable が用意されています。

どれを使うか

Cloud SQLFirestoreSpanner
モデルRDBNoSQL ドキュメント分散 RDB
スケール単一インスタンス自動・無限分散・無限
料金常時稼働コスト従量制(読み書き)高い(最小 $700/月〜)
用途標準 Web/業務アプリモバイル・リアルタイム金融・大規模グローバル

Cloud SQL (PostgreSQL)

resource "google_sql_database_instance" "main" {
  name             = "pg-myapp-prd"
  database_version = "POSTGRES_16"
  region           = "asia-northeast1"

  deletion_protection = true   # 本番では必須

  settings {
    tier              = "db-custom-2-7680"   # vCPU 2 / RAM 7.5GB
    availability_type = "REGIONAL"             # ZONAL or REGIONAL (HA)
    disk_type         = "PD_SSD"
    disk_size         = 100
    disk_autoresize   = true

    backup_configuration {
      enabled                        = true
      point_in_time_recovery_enabled = true
      start_time                     = "16:00"   # UTC = JST 01:00
      backup_retention_settings {
        retained_backups = 30
      }
    }

    maintenance_window {
      day  = 7      # 日曜
      hour = 17     # UTC 17:00 = JST 02:00
    }

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

    insights_config {
      query_insights_enabled  = true
      record_application_tags = true
    }

    database_flags {
      name  = "log_min_duration_statement"
      value = "1000"
    }
  }
}

resource "google_sql_database" "myapp" {
  name     = "myapp"
  instance = google_sql_database_instance.main.name
}

resource "random_password" "db" {
  length  = 32
  special = true
}

resource "google_sql_user" "app" {
  name     = "myapp"
  instance = google_sql_database_instance.main.name
  password = random_password.db.result
}

本番向け設定

VPC との接続(Private Services Access)

# VPC に GCP サービス用の予約 IP 範囲を確保
resource "google_compute_global_address" "private_ip" {
  name          = "private-ip-cloud-sql"
  purpose       = "VPC_PEERING"
  address_type  = "INTERNAL"
  prefix_length = 16
  network       = google_compute_network.main.id
}

# その範囲を Cloud SQL に peering で接続
resource "google_service_networking_connection" "main" {
  network                 = google_compute_network.main.id
  service                 = "servicenetworking.googleapis.com"
  reserved_peering_ranges = [google_compute_global_address.private_ip.name]
}

Firestore

Firestore は project あたり 1 つの「Native モード」DB を持つ仕組み。ドキュメント/コレクション構造。

resource "google_firestore_database" "main" {
  project     = "myapp-prd"
  name        = "(default)"   # デフォルト DB
  location_id = "asia-northeast1"
  type        = "FIRESTORE_NATIVE"

  point_in_time_recovery_enablement = "POINT_IN_TIME_RECOVERY_ENABLED"
  delete_protection_state           = "DELETE_PROTECTION_ENABLED"
}

# 追加 DB(複数 DB 対応)
resource "google_firestore_database" "analytics" {
  project     = "myapp-prd"
  name        = "analytics"
  location_id = "asia-northeast1"
  type        = "FIRESTORE_NATIVE"
}

# インデックス
resource "google_firestore_index" "users_by_email_status" {
  database   = google_firestore_database.main.name
  collection = "users"

  fields {
    field_path = "email"
    order      = "ASCENDING"
  }
  fields {
    field_path = "status"
    order      = "ASCENDING"
  }
  fields {
    field_path = "created_at"
    order      = "DESCENDING"
  }
}

Cloud Spanner(概要)

「水平スケールする SQL DB」。料金の最小ラインが高い(処理単位 1 PU で月 ~$65、運用には 100 PU 程度推奨で月 $6500〜)ので、規模が小さいなら Cloud SQL の方が圧倒的に安い。

resource "google_spanner_instance" "main" {
  config           = "regional-asia-northeast1"
  display_name     = "myapp-spanner"
  name             = "myapp-spanner"
  processing_units = 100   # 1 ノード = 1000 PU
}

resource "google_spanner_database" "main" {
  instance = google_spanner_instance.main.name
  name     = "myapp"

  ddl = [
    "CREATE TABLE users (id STRING(36) NOT NULL, email STRING(255), created TIMESTAMP) PRIMARY KEY(id)",
  ]

  deletion_protection = true
}
tip 新規アプリは Cloud SQL(PostgreSQL)から 始めるのが無難。NoSQL が本当に必要なら Firestore、グローバル分散が必要になった時に Spanner を検討。