Cloud Firestoreのバックアップ・リストア
Cloud Firestoreにバックアップの仕組みが無いことは以前からの課題でしたが、ようやく gcloud
コマンドとしてimport・exportが提供されました🎉
(Cloud Next 2018 でもアナウンスがあったそうですが、以下の記事で知りました。)
ちなみに、これまでは次のOSSを利用するのが定番だったと思います。
Export・Importのやり方は次のドキュメントによくまとまっていますが、本記事ではそれらを実際に使いながら解説していきます。
前提条件
GCPへの課金を有効化する必要があります。FirebaseはBlaze planにする必要が出てきます。
また、いくつかの権限も必要です。自身がオーナーのプロジェクトで自ら実行する場合は特に気にせずで大丈夫ですが、そうでない場合、以下の権限割り当てを済ませておく必要があります。
- Cloud Firestore roles:
Owner
,Cloud Datastore Owner
, orCloud Datastore Import Export Admin
- Cloud Storage roles:
Owner
orStorage Admin
gcloudコマンド実行環境の用意
以下の2通りがありますが、コマンドライン操作だけで済む後者のやり方がおすすめです。
- Cloud Shell を利用
- Google Cloud SDK をインストール
すでにインストール済みの手元のSDKが古くて後述の gcloud beta firestore
コマンドがない場合は以下のコマンドで更新が必要です。
gcloud components update
プロジェクト設定
次のコマンドなどで、gcloudコマンドに設定されているプロジェクトが確認できます。
gcloud info | grep project
操作対象のプロジェクトと異なっている場合は、次のコマンドで切り替えておきます。特にインポート先のプロジェクトを間違える大事故を起こさないように注意です。
gcloud config set project [PROJECT_ID]
Google Cloud StorageのBucket用意
Google Cloud Storage にエクスポート先のBucketをあらかじめ用意しておく必要があります(既存の適当なBucketから選ぶことも可能ですが隔離した方が扱いやすいはずです)。
名前は、Realtime Databaseのバックアップは [PROJECT_ID]-backups
というBucketでなされるので[PROJECT_ID]-backups-firestore
あたりの名前が良いかなと思って、僕はそうしています。
リージョンは、以下のどちらかですが、前者の必要性は薄く後者の方が安いので後者を選びました。
- Multi-Regional
- Regional (us-central1などFirestoreのリージョンと揃える)
Firestoreドキュメントのエクスポート
次のコマンドを実行するだけです。 [BUCKET_NAME]
はもちろん上で用意したものを指定します。
gcloud beta firestore export gs://[BUCKET_NAME]
成功すると、次のようなログを吐きつつ処理が終了します。
➜ cloud beta firestore export gs://[PROJECT_ID]-backups-firestore
Waiting for [projects/[PROJECT_ID]/databases/(default)/operations/ASA1MTcwOTI5NDQJGnRsdWFmZWQHEmxhcnRuZWNzdS1
zYm9qLW5pbWRhFAosEg] to finish...done.
metadata:
'@type': type.googleapis.com/google.firestore.admin.v1beta1.ExportDocumentsMetadata
operationState: PROCESSING
outputUriPrefix: gs://[PROJECT_ID]-backups-firestore/2018-08-09T03:27:33_84792
startTime: '2018-08-09T03:27:33.459300Z'
name: projects/[PROJECT_ID]/databases/(default)/operations/ASA1MTcwOTI5NDQJGnRsdWFmZWQHEmxhcnRuZWNzdS1zYm9qLW5pbWRhFAosEg
--collection-ids
フラグを指定して、特定のコレクションだけのエクスポートも可能です。
gcloud beta firestore export gs://[BUCKET_NAME] --collection-ids='[COLLECTION_ID_1]','[COLLECTION_ID_2]'
ただし、 --collection-ids
フラグで指定したコレクションのサブコレクションは対象外なので、サブコレクションも含めたい場合はそれらも明示的に指定する必要があります。--collection-ids
フラグ無指定なら、サブコレクション含めてすべてエクスポートされます。バックアップ目的なら通常無指定が良いはずです。--collection-ids
フラグは基本的にはバックアップ目的ではなく別プロジェクトにデータを移して検証・データ分析などするためのものであると認識しています。
Realtime Databaseの記事ですが、バックアップは次の用途などで有用と書かれています。
- オフライン スクリプティング
- 履歴データ分析
- 破損データやデータロストからのリカバリ
本記事では、需要の高そうなバックアップ・リストア(上の箇条書きの3点目に相当)に敢えて焦点を当てて説明しています。
実行結果の確認
上記コマンドではエクスポートの開始が成功しただけで、処理はバックグラウンドで実行されています。
エクスポートのログの最後の行の [OPERATION_NAME]
を用いて、次のコマンドで確認することができます。出力の1行目に done: true
と記載されていれば完了したということです。
gcloud beta firestore operations describe ASA1MTcwOTI5NDQJGnRsdWFmZWQHEmxhcnRuZWNzdS1zYm9qLW5pbWRhFAosEg
最近の実行結果を全件確認したい場合は次のコマンドです。
gcloud beta firestore operations list
削除・キャンセルもできますが、キャンセルはロールバックではなく途中の中途半端な状態で終わるだけなので、やらかした時のキャンセル用途としてはあまり使えないと思います(中途半端でも良いからとにかくキャンセルしたいというケースはあるかもしれません)。
gcloud beta firestore operations delete [OPERATION_NAME]
gcloud beta firestore operations cancel [OPERATION_NAME]
Google Cloud StorageのBucketを覗くと、次のようにパスで区切られたものが生成されているのを確認できます。中身はおそらく独自フォーマットです。とりあえずインポート作業に必要になってくるのは、 2018-08-09T01:58:11_44344
などの名前のみです。
Firestoreドキュメントのインポート
次のコマンドでインポートができます。[EXPORT_PREFIX]部分に上の例だと2018-08-09T01:58:11_44344
などを指定します。
gcloud beta firestore import gs://[BUCKET_NAME]/[EXPORT_PREFIX]/
成功すると、次のようなログが吐かれます。
➜ cloud beta firestore import gs://[PROJECT_ID]-backups-firestore/2018-08-09T01:58:11_44344/
Waiting for [projects/[PROJECT_ID]/databases/(default)/operations/AiA4NDcwNjE1NDQJGnRsdWFmZWQHEmxhcnRuZWNzdS1zYm9qLW5pbWRhFAosEg] to finish...done.
metadata:
'@type': type.googleapis.com/google.firestore.admin.v1beta1.ImportDocumentsMetadata
inputUriPrefix: gs://[PROJECT_ID]-backups-firestore/2018-08-09T01:58:11_44344
operationState: PROCESSING
startTime: '2018-08-09T04:07:22.151940Z'
name: projects/[PROJECT_ID]/databases/(default)/operations/AiA4NDcwNjE1NDQJGnRsdWFmZWQHEmxhcnRuZWNzdS1zYm9qLW5pbWRhFAosEg
これもエクスポートと同様に実際の処理はバックグラウンドで行われていて、以下で進捗・最終結果を確認できます。
gcloud beta firestore operations describe AiA4NDcwNjE1NDQJGnRsdWFmZWQHEmxhcnRuZWNzdS1zYm9qLW5pbWRhFAosEg
出力の1行目に done: true
と記載されていれば、Firestore上でもデータがインポートされていることが確認できるはずです。
以上がFirestoreのエクスポート・インポートの流れとなります。実際にやる場合は、次のような流れになると思います。
- 本番環境ではなく別途開発環境など用意してそこでエクスポート・インポートを試す
- うまくいったら本番環境でもエクスポート
- 何かしらの事故で本番環境のFirestoreのデータをエクスポート時に戻したい事態になったらインポート
あるいは、バックアップ・リストア用途以外にも、別環境のデータを移動してテスト環境で検証したい時にも有用かと思います。
バックアップ処理の定期実行
以下の別記事で構築手順例を説明しています。
初めは gcloud
コマンドを実行可能な環境を用意するアプローチを取ってしまいましたが、
あとからREST APIの存在に気付いて、こちらのやり方の方がずっと簡単でおすすめです。
また、Realtime DatabaseではFirebase Webコンソール上の操作で簡単に日次バックアップが取れるようになっていて、Firestoreにも今後同様の機能が搭載されると予想しています。逆に言うと、それまでの間はエクスポートコマンドの定期実行の仕組みを自前で整えるしかないですね。