💂

Google Cloud Backup And DRとTerraformでCloud SQLのバックアップを不変にする

に公開

この記事は一休.com Advent Calendar 2025の4日目の記事です。

この記事では、このGoogle Cloud Backup and DRのひとつの特色であるBackup Vaultを使ってGoogle Cloud SQLのバックアップを取得する、ということをTerraformで実現してみます。

Google Cloud Backup and DR

https://cloud.google.com/solutions/backup-dr

その名の通り、バックアップと障害復旧のためのサービスです。
Google Cloud の各プロダクトやサービスは個別にデータ保護機能を持っています。Cloud SQLのバックアップやDiskのスナップショットなどです。
では、それらの個別のデータ保護機能と比べ、このBackup and DRの利点は、どこにあるのでしょうか。

Backup Vaultを使ってイミュータブルなバックアップを取得する

Backup and DRでは、誰も変更も削除もできない(=イミュータブルな)バックアップを取得することができます。
たとえば、悪意のある攻撃者がデータベースを改ざんされたとします。サービスを無事再開するために、バックアップからデータベースを復旧したいです。しかし、ここで、攻撃者がすべてのバックアップを削除していたとしたら、どうでしょうか。サービス再開が一気に難しくなります。

しかし、Backup and DRのBackup Vaultを使えば、バックアップをだれも(アカウントのオーナーでも)削除できないようにロックすることができます。
こうすることで、バックアップを保護し、万が一攻撃も受けても素早く復旧できるようにするのが、Backup Vaultの価値です。

では、順にTerraformの設定を見ていきましょう。

Cloud SQL向けのBackup VaultとBackup Planを作る

resource "google_backup_dr_backup_vault" "backup_vault" {
  project                                    = var.project
  location                                   = var.region
  backup_vault_id                            = "backup-vault"
  description                                = "backup vault"
  backup_minimum_enforced_retention_duration = "604800s"
  access_restriction                         = "WITHIN_PROJECT"
  backup_retention_inheritance               = "INHERIT_VAULT_RETENTION"
  ignore_inactive_datasources                = "true"
}

resource "google_backup_dr_backup_plan" "sql_backup_plan" {
  project        = var.project
  location       = var.region
  backup_plan_id = "sql-backup-plan"
  resource_type  = "sqladmin.googleapis.com/Instance"
  backup_vault   = google_backup_dr_backup_vault.backup_vault.id

  backup_rules {
    rule_id                = "rule-1"
    backup_retention_days  = 7

    standard_schedule {
      recurrence_type     = "DAILY"
      time_zone           = "Asia/Tokyo"

      backup_window {
        start_hour_of_day = 0
        end_hour_of_day = 6
      }
    }
  }
  log_retention_days = 6
}

イミュータブルなバックアップの設定は、Backup VaultとBackup Planによって実現します。
Vaultは英語で、金庫室や保管庫、といった意味です。つまり、Backup Vaultは文字通りバックアップの保管の仕方を設定します。
具体的な設定項目は、公式のドキュメントに詳しいです。大事なのは、backup_minimum_enforced_retention_duration です。これが、バックアップの最小保持期間を指定します。↑の設定では、7日になっています。
Backup Planは文字通り、バックアップの計画です。これにはバックアップ対象のリソースとバックアップのスケジュールを設定します。
↑の設定では、Cloud SQLが対象であることを設定しています。また、backup_rulesには、backup_retention_daysで7日分のバックアップを保持することを設定しています。この値は、vaultのbackup_minimum_enforced_retention_durationと同じか、より大きい値にする必要があります。
また、対象が、Cloud SQLの場合にのみ、 log_retention_daysが設定できます。これは、ポイントインタイム リカバリに必要なログの保持期間です。

まずは、この状態でapplyしてみます。

すると、https://console.cloud.google.com/backupdr/backup-vaults/list と、https://console.cloud.google.com/backupdr/backup-plans/list にそれぞれ、Vaultとプランができあがったのが確認できると思います。

Cloud SQLとBackup Planを紐づける。

resource "google_backup_dr_backup_plan_association" "sql_backup_plan_association" {
  project                    = var.project
  location                   = var.region
  resource_type              = "sqladmin.googleapis.com/Instance"
  backup_plan_association_id = "sql-backup"
  resource                   = "//sqladmin.googleapis.com/projects/${var.project}/instances/db"
  backup_plan                = google_backup_dr_backup_plan.rds_backup_plan.name
}

google_backup_dr_backup_plan_associationで、バックアップ対象のリソースとBackup Planを紐づけます。これは、非常にシンプルで単に紐づけているだけです。

ただし、注意点があります。これをapplyすると、対象のCloud SQLのバックアップ方式は、拡張バックアップになります。
この場合、Cloud SQL単体の機能としてのバックアップ(スタンダードバックアップ)は無効になります。
対象のCloud SQLをTerraformで管理しているなら、Cloud SQLのバックアップの設定はすべて削除する必要があります。 そうしないと、次のapplyで、無効になったスタンダードバックアップを有効にしようとしてしまい、エラーになります。

また、筆者が確認した限りでは、↑をapplyしたタイミングで初回のバックアップが実行されます。状況によっては負荷のかかり方などを確認しつつapplyしたほうが無難かもしれません。

さて、↑をapplyして、対象のCloud SQLのコンソールからバックアップを見てみます。
すると、以下の通り、「拡張バックアップ」ティアが選択されており、紐づけをしたbackup planが、設定されているのがわかります。

ロックを有効にして保持期間を短縮できなくする

ここまでで、すでに、バックアップそのものは直接的には削除できないようになっています。そして、さらに堅牢にするために、バックアップの最小保持期間を短縮できないようにします。
例えば、7日のバックアップ最小保持期間を1日にできてしまえば、事実上6日分のバックアップを消せる、ということになります。これでは厳密な意味ではイミュータブルではありません。そこで、vaultのロックを有効にして最小保持期間を短縮できないようにします。

resource "google_backup_dr_backup_vault" "backup_vault" {
  project                                    = var.project
  location                                   = var.region
  backup_vault_id                            = "backup-vault"
  description                                = "backup vault"
  backup_minimum_enforced_retention_duration = "604800s"
  access_restriction                         = "WITHIN_PROJECT"
  backup_retention_inheritance               = "INHERIT_VAULT_RETENTION"
  ignore_inactive_datasources                = "true"
  effective_time                             = "2025-12-04T00:00:00Z" ##これを追加
}

ロックをするにはeffective_timeに日時を設定します。この日時以後、ロックが発動し、最小保持期間(backup_minimum_enforced_retention_duration)が短縮できなくなります。
vaultの設定画面で確認してみます。
設定した日時の以前は、以下の通り、ロックされていない状態です。

設定された日時以後に見ると、以下の通り、ロックされた状態になりました。

終わりに

攻撃を受けてしまった後に適切な対応ができるかどうかが、ビジネスに大きな影響を与える、というのが、昨今のセキュリティインシデントの教訓です。
迅速にサービス再開をするためには、不変のバックアップがあるというのは強い味方です。積極的に活用していきたいですね。

参考

https://cloud.google.com/backup-disaster-recovery?hl=ja

https://cloud.google.com/blog/ja/products/storage-data-transfer/backup-and-dr-service-adds-immutable-indelible-backups

Discussion