1週間で消えないCloud SQLのバックアップを自動で取得する

# Cloud SQLの自動バックアップ

Cloud SQLはGCP(Google Cloud Platform)のマネージドSQLサーバーです。AWSのRDSと思えばよいです。Cloud SQLには日次の自動バックアップ機能が標準でありますが、これは1週間で消えてしまい、本番環境としてはいささか心もとないものです。この状況を解消するのが本記事の目的です。

# Cloud SQLのバックアップの種類

Cloud SQLのバックアップには、次の2種類があります。([詳細](https://cloud.google.com/sql/docs/sqlserver/backup-recovery/backups?hl=ja_JP#types_of_backups))

- 自動バックアップ
- オンデマンドバックアップ

自動バックアップは何もしなくても日次で一週間分取得されます。お手軽ですが、1週間を超えた古いバックアップは自動で削除されます。

オンデマンドバックアップはいわゆる「手動」バックアップで、管理画面から明示的に「バックアップを作成」の操作をしたときに作成されます。オンデマンドバックアップは明示的に削除しない限り永遠に残り続けます。

本番環境では、1週間を超えたバックアップを残しておきたいので、選択肢はオンデマンドバックアップしかありません。しかし、これを定期的に手動で実行するのは大変ですし、人間なので忘れます。

そこで、本記事ではオンデマンドバックアップを自動化する方法を紹介します。

# 自動化の概要

ここで紹介する自動化の方法は、恐らく考え得る中で最も一般的なものだと思いますが、GCPの公式ドキュメントには見当たらなかったので、この記事を書いています。

下記が全体の流れです。

- Cloud Scheduler で定期的にバックアップを起動するPub/Sub Topicを発行する
- 上記のPub/Sub Topicを受けてCloud Functionsを起動し、sqladmin APIを使ってCloud SQLのバックアップ作成を起動する

# 自動化の手順

## バックアップを起動するCloud Functionsを作成

今回はPython 3.8を使います。関数名は`backup-sql`とでもしておきましょうか。ついでに同名のCloud Pub/Subトピックも作成しておきましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7519/a907d8be-ec2c-8880-3fd0-678b5154fd26.png)

ランタイムは`Python 3.8`を選択し、下記のファイルを作成して保存しましょう。コピペで大丈夫です。

```text:requirements.txt
# Function dependencies, for example:
# package>=version
oauth2client
google-api-python-client
```

```python:main.py
import os, json
from googleapiclient import discovery
from oauth2client.client import GoogleCredentials

def backup_sql(event, context):
    """Triggered from a message on a Cloud Pub/Sub topic.
    Args:
         event (dict): Event payload.
         context (google.cloud.functions.Context): Metadata for the event.
    """
    credentials = GoogleCredentials.get_application_default()
    service = discovery.build('sqladmin', 'v1beta4', credentials=credentials)
    req = service.backupRuns().insert(project=os.getenv('GCP_PROJECT'), instance=os.getenv('SQL_INSTANCE_NAME'))   
    res = req.execute()
    print(res)
```

最後に、プロジェクト名とSQLインスタンス名をランタイム環境変数に設定しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7519/e82dbcc0-9022-3d1e-cc12-787fe9810a79.png)

これで、関数のテストをしてオンデマンドバックアップが作成されていれば成功です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7519/58d9a9a0-1e1a-2d23-4bd1-6e9ef5fb961e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7519/6e7a24f4-1ae7-d0c7-41c6-fabbe46ff8d7.png)

## Cloud SchedulerをPub/Sub Topicに紐づける

ここまでくれば、先ほど作ったPub/Sub TopicをCloud Schedulerに紐づければ終わりです。

頻度は[crontab形式](https://cloud.google.com/scheduler/docs/configuring/cron-job-schedules?hl=JA&_ga=2.29109436.-1683007748.1562552967&_gac=1.112754038.1605678050.Cj0KCQiAhs79BRD0ARIsAC6XpaXXOn8T98Q1jRIch3ne3Mi7hEMmi5BFoiIUZMNCo6mKyVDK2-sHUkEaAtqBEALw_wcB#defining_the_job_schedule)で入力します。下記では、日本時間の毎週日曜日の3:34に起動するよう設定しています。（なぜかタイムゾーンの説明が化けていますが気にしない）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7519/1743788f-cb27-c412-b284-125cc61c9abe.png)

ポイントは、トピック名を先ほど作成したトピック名と一致させることとです。ペイロードは使っていないので、空のjsonを入れておきましょう。

# 実運用でさらに検討すべき事項

本記事では、単純にバックアップの自動作成のみをターゲットにしていますが、実際に利用するときには古いバックアップの削除も含めてフローを回す必要があると思います。バックアップはディスク容量課金に効いてくるので、長期間運用する場合には特に気を付けてください。日次、週次、月次、年次などを組み合わせて、用途にマッチさせて体系化する設計が必要です。特に、不要なバックアップが大量に溜まると、手動で削除するのはなかなか難儀です。

また、今回のプログラムでは、バックアップ作成をキックしてはいますが、その結果は確認していません。厳密にやるのであれば、BackupRunsインスタンスのidを取得して、そのidのインスタンスのstatusが`SUCCESSFUL`になるのを確認し、万一`FAILED`になった場合、何らかの手段でアラートを発行するなどする必要があります。

このあたりを念頭に置いて、Cloud Functionsを用途に合った形に書き換えてご利用ください。その際はこのあたりのドキュメントが役に立つことと思います。
https://cloud.google.com/sql/docs/mysql/admin-api/rest/v1beta4/backupRuns