🧨

TerraformでCloud SQLを消したくないのに消えそうになった

に公開

サマリ

  • プロジェクト終了に伴いインフラ停止した際の知見
  • リソース整理の過程で Cloud SQL のPrivate IP を外そうとしたら forces replacement が起きた
  • もしapply すると Cloud SQL が再作成(=削除)される
  • deletion_protection の設定は有効にしておくべき

なぜ Cloud SQL を消したくなかったのか

今回対象となった Cloud SQL は、本番環境で利用されていたデータベースでした。
プロダクト自体は終了フェーズに入っていましたが、データは削除してはいけないという前提がありました。

理由は、監査・証跡目的でのデータ保持が必要だったためです。
Cloud SQL を削除してしまうと、過去の状態を後から確認・説明する手段が失われてしまいます。

そのため今回の作業でやりたかったのは「削除」ではなく「停止」でした。

  • サービスは停止する
  • 不要なリソースは削除してコストを最小化する
  • データは残す
  • Cloud SQL は 停止(stop)まで にとどめる

この方針のもとで、Cloud SQL 自体は停止しつつ、付随する不要なリソースを整理することを考えていました。

やりたかったのは「プライベートIPを外す」だけ

Cloud SQL はコンソールから停止する予定でしたが、それに付随するネットワークリソースは不要になると判断していました。
アプリケーションリソースはすでに削除済みであり、外部からのアクセスも遮断した上で、可能な限りコストを下げたい状況だったので、

  • VPC や Service Networking などの不要なリソースを削除する
  • 可能であれば Cloud SQL の Private IP 接続も外す

Terraform 管理下ではip_configuration.private_network を削除すればよいだけに見え、
この時点では「設定を外すだけでインスタンス自体は残る」と考えていました。

resource "google_sql_database_instance" "xxxxx" {
  name             = "instance_name"
  database_version = "database_version"
  region           = "region"

  settings {
    availability_type = "REGIONAL"

.... 省略

    ip_configuration {
      ipv4_enabled = true
      # private_network を設定していた(今回ここを外そうとした)
    }
  }
}

Terraform plan から意図しない挙動に気づいた

terraform plan を確認したところ、次の差分が表示されました。

# module.common.google_sql_database_instance.postgres must be replaced
-/+ resource "google_sql_database_instance" "postgres" {
  name = "prod-db-instance"

  settings {
    ip_configuration {
      - private_network = "projects/***/global/networks/***" -> null
        # forces replacement
    }
  }
}

表示されていたのは、

  • must be replaced
  • # forces replacement

という内容で、「Private IP を外す変更が Cloud SQL インスタンスの再作成を前提にしている」という点に気づきました。
なので、作業を修正しPrivate IP を残して、Cloud SQL を停止することにしました。

誤って消してしまわないようにするには

通常のオペレーションで、planを確認せずにapplyすることはないと思います。
もし、今回の変更をそのまま terraform apply した場合、

  • Cloud SQL インスタンスを削除
  • 新しいインスタンスを再作成

という処理が実行される想定でした。そのような事故を防ぐためには、deletion_protection_enabledの設定が有効です。

resource "google_sql_database_instance" "xxxxx" {
  name             = "instance_name"
  database_version = "database_version"
  region           = "region"

  settings {
    availability_type = "REGIONAL"

.... 省略

    ip_configuration {
      ipv4_enabled = true
      # private_network を設定していた(今回ここを外そうとした)
    }

    # Cloud SQL インスタンス自体の削除を防ぐための設定
    deletion_protection_enabled = true
  }
}

この設定がされていれば、もしapplyを実行してしまってもCloud SQLの削除はできなくなるので、安心ですね。

Discussion