VISASQ Dev Blog

ビザスク開発ブログ

Cloud SQL のデータを定期的に GCS へバックアップする仕組みを整えました

はじめに

こんにちは!基盤チームの高畑です。

最近シロカのコーヒーメーカーを買ってからというもの、1 日に 5 杯くらいコーヒーを飲み続けてしまっておりちょっと飲み過ぎなのではないかと危機感を覚えています。 手軽にコーヒーが淹れられてしまうのも考えものですが、美味しいので仕方がないと自分に言い聞かせながら今もコーヒーを淹れています。

みなさん、Cloud SQL のバックアップを定期的に行うといえば、まず思い浮かぶのは自動バックアップ機能を利用することだと思います。

しかし、この自動バックアップはあくまで「インスタンスが存在していること」が前提で、仮に Cloud SQLインスタンスが削除されてしまった場合にバックアップもろとも削除されてしまい復元ができないといった状態に陥ってしまいます。

AWS の RDS であればスナップショットを定期的に取っておくことでインスタンスが削除されてしまっても復元することが可能ですが、Cloud SQL にはそのような機能はありません。

そこで、Cloud SQL のデータを定期的に GCS へバックアップできる仕組みを整えて、万が一の際に復元ができるようにする方法をご紹介します。

バックアップ手法について

Cloud SQL のバックアップデータを GCS へ保存するためには、Cloud SQL のエクスポート機能を利用するしか現状方法がありません(自分が知らないだけかもしれませんが)。

Cloud SQL のエクスポートは定期的に実行するための機能がないため、独自で仕組みを整える必要があります。

そこで、ビザスクでは GCP の Workflow を利用して Cloud SQL のエクスポート API をキックし、Cloud Scheduler で定期実行するという方法を選択しました。

バックアップの構成図

Workflow + Cloud Scheduler のリソースを作成する

バックアップを行うために必要なサービスアカウントや Workflow 本体、Workflow をキックするための Cloud Scheduler を作成します。

Cloud SQL のエクスポートはそれなりに CPU リソースを消費するため、サービス影響が出ないリードレプリカからエクスポートを実施しました。

また、エクスポートの対象とするのはシステムデータベースを除いたアプリケーションに関係するデータベースのみを対象としています。

resource "google_service_account" "cloudsql_exporter" {
  project     = var.project
  account_id  = "cloudsql-exporter"
  description = "Execute CloudSQL Export"
}

resource "google_project_iam_member" "cloudsql_exporter_workflow_invoker" {
  project = var.project
  role    = "roles/workflows.invoker"
  member  = "serviceAccount:${google_service_account.cloudsql_exporter.email}"
}

resource "google_project_iam_member" "cloudsql_exporter_cloudsql_editor" {
  project = var.project
  role    = "roles/cloudsql.editor"
  member  = "serviceAccount:${google_service_account.cloudsql_exporter.email}"
}

data "google_sql_databases" "databases" {
  project  = var.project
  instance = google_sql_database_instance.read_replica.name
}

resource "google_workflows_workflow" "cloudsql_export" {
  project = var.project

  name        = "cloudsql-export"
  region      = local.region
  description = "CloudSQL Export to GCS"

  service_account = google_service_account.cloudsql_exporter.id

  source_contents = <<-EOF
    main:
      steps:
      - init:
          assign:
            - now: $${time.format(sys.now(), "Asia/Tokyo")}

      - export:
          call: googleapis.sqladmin.v1.instances.export
          args:
            project: ${var.project}
            instance: ${google_sql_database_instance.read_replica.name}
            body:
              exportContext:
                fileType: "SQL"
                databases: ["${join("\", \"", [for name in data.google_sql_databases.databases.databases[*].name : name if !(contains(["mysql", "sys", "information_schema", "performance_schema"], name))])}"]
                uri: '$${"gs://xxxxxxxx/Cloud_SQL_Export_" + now + ".sql"}'
                offload: false
EOF
}

resource "google_cloud_scheduler_job" "exec_cloudsql_export_workflow" {
  project = var.project
  name    = "exec-cloudsql-export-workflow"

  region      = local.region
  description = "Execute CloudSQL Export Workflow"

  time_zone = "Asia/Tokyo"
  schedule  = "0 2 * * *"

  attempt_deadline = "600s"

  retry_config {
    retry_count          = 0
    min_backoff_duration = "10s"
    max_backoff_duration = "300s"
    max_doublings        = 3
    max_retry_duration   = "0s"
  }

  http_target {
    http_method = "POST"
    uri         = "https://workflowexecutions.googleapis.com/v1/${google_workflows_workflow.cloudsql_export.id}/executions"
    body        = base64encode("{\"argument\":\"\"}")

    oauth_token {
      service_account_email = google_service_account.cloudsql_exporter.email
    }
  }
}

terraform apply を実施しリソースの作成が完了すると、毎日 2:00 に自動で Cloud SQL のエクスポートが実施されるようになります。

(Workflow のタイムアウト制御をしていないので失敗扱いとなってしまっていますが、実際にはちゃんとエクスポートされています。いずれ直す。)

Workflow 実行履歴

エクスポートされたデータ

おわりに

いかがでしたでしょうか。

Cloud SQL の自動バックアップ機能と併用することにより、従来のポイントインタイムリカバリなどからの復元に加え有事の際に GCS に保存されているバックアップデータから復元することも可能となります。

インスタンスの削除保護をすることは当然として、自然災害等でデータが復旧できなくなったというリスクがちょっとでも減らせたのではないでしょうか。

欲を言えば AWS のスナップショットと同等の機能が出て欲しいなと思っています。頼むぞ GCP

ビザスクではエンジニアの仲間を募集しています! 少しでもビザスク開発組織にご興味を持たれた方は、ぜひ一度カジュアルにお話ししましょう! developer-recruit.visasq.works