Cloud Scheduler で Firestore を定期的にバックアップする

Cloud Scheduler で Firestore を定期的にバックアップする

こんにちは。サーバ、インフラ周りを担当している鷲見(@soichisumi)です。

先日、GCP に Cloud Scheduler が追加されました。 GCP のコンソールまたは CLI から、定期的にタスクを実行できるというサービスです。

実行できるタスクは以下の3つです.

  • HTTPリクエスト
  • Pub/Sub メッセージ
  • App Engineアプリケーション

App Engine の cron job が HTTP リクエスト、Pub/Sub もターゲットに指定できるようになって外出しされたようなサービスだと思えば良さそうです。

これで今まで定期実行のために行っていた、App Engine + cron job や Apps Script の実装・デプロイが不要になります 🎉🎉🎉

早速使ってみましょう。

Cloud Firestore をバックアップする 関数 の実装

今回作る Firestore バックアップのアーキテクチャは下図のようになります。

image

まず Cloud Scheduler で起動する、Firestore をバックアップする 関数 を実装します。

バックアップには FirestoreのCloud API を利用します。

他にも GCP のリソースを操作する様々な API が提供されているので、 GCP のサービスを連携する際には所望の API がないか見てみると面白いと思います。

また、API を利用する際にはアクセストークンの発行が必要です。アクセストークンを発行するサービスアカウントは次の2つのロールを持っている必要があります。

アクセストークンを取得して Cloud API を呼び出し、バックアップジョブを登録する Javascript コードが下記になります。

また、保存先のバケットも合わせて作成します。下記コードであればgs://${projectId}-firestore-backup となります(${projectId}は GCP or Firebase のプロジェクトID)。リージョンは、 Multi-Regional or Regional を選択し、関数 と同じリージョンを選択するようにしてください。


const functions = require('firebase-functions');
const { google } = require('googleapis');
const rp = require('request-promise');
const projectId = process.env.GCLOUD_PROJECT; // 関数が属しているGCPプロジェクトIDが環境変数に登録されている

async function getAccessToken(){
	// [**https://developers.google.com/identity/protocols/googlescopes**](https://developers.google.com/identity/protocols/googlescopes)
	const scopes = [**'[https://www.googleapis.com/auth/datastore](https://www.googleapis.com/auth/datastore)', '[https://www.googleapis.com/auth/cloud-platform](https://www.googleapis.com/auth/cloud-platform)'**];
	let serviceAccount = require('./keys/service-account.json');
	
	const jwtClient = new google.auth.JWT(
	    serviceAccount.client_email,
	    undefined,
	    serviceAccount.private_key,
	    scopes,
	    undefined
	);
	try{
	    const authorization = await jwtClient.authorize();
	    return authorization.access_token;
	}catch(err){
	    return err;
	}
}

async function exportFirestore(){
	try{
		const accessToken = await getAccessToken();
		const endpoint = `https://firestore.googleapis.com/v1beta1/projects/${projectId}/databases/(default):exportDocuments`;
		const option = {
			headers: {
				Authorization: `Bearer ${accessToken}`
			},
			json: true,
			body: {
				outputUriPrefix: `gs://${projectId}-firestore-backup`,
			}
		};
		const res = await rp.post(endpoint, option);
		return res;
	}catch(err){
		console.log(`error occurred when doing backup: ${err}`);
		return err;
	}
}

exports.FirestoreBackup = functions.pubsub
																		.topic('FirestoreBackup')
																		.onPublish(async (msg)=>{
	try{
		const res = await exportFirestore();
		console.log(`firestore backup job is successfully registered: ${res}`);
		return res;
	}catch(err){
		console.log(`error occurred when backuping: ${err}`);
	}
	});

package.jsonは次のようになります。async/awaitを使うため、ランタイムは Node 8 とします。


{
	"name": "functions",
	"description": "Cloud Functions for Firebase",
	"scripts": {
	},
	"dependencies": {
		"firebase-admin": "^6.0.0",
		"firebase-functions": "^2.0.5",
		"googleapis": "^34.0.0",
		"request": "^2.88.0",
		"request-promise": "^4.2.2"
	},
	"devDependencies": {
		"eslint": "^4.12.0",
		"eslint-plugin-promise": "^3.6.0"
	},
	"private": true,
	"engines": {
	"node": "8"
	}
}

上記実装は GCPUGのブログ記事を参考にしています。こちらも読んでみると参考になるかもしれません。

以上で Firestoreをバックアップするfunctionの準備が終わりました。

Cloud Scheduler でジョブを作成する

それでは本題の Cloud Scheduler を使っていきましょう。

サービス一覧の中に Cloud Scheduler が追加されているので、選択します。

image

その後、ジョブの詳細を入力します。 今回は Cloud Functions を用いて Firestore のバックアップを行います。 前節での実装に合わせて、ターゲットは Pub/Sub、トピックは FirestoreBackup、ペイロードは backup とします。

頻度欄の書式はこちらの公式ドキュメントを参考にしてください。

image

これでジョブの追加は完了です。簡単ですね。

動作を確認する

以上で、Cloud SchedulerとCloud Functionsの連携が完了しました。動作確認してみましょう。

GCPコンソールから直接ジョブを起動できます。ジョブの一覧から今すぐ実行ボタンを押します。

image

すると FirestoreBackupトピックに Pub/Sub メッセージが送られ、FirestoreBackup 関数が起動します。

image

Cloud storageをみてみるとバックアップファイルが作成されています。restoreは gcloud beta firestore import gs://${projectId}-firestore-backup で行うことができます。

image

以上により、Cloud SchedulerでFirestoreを定期的にバックアップできるようになりました。

まとめ

Cloud Scheduler を用いて Firestore のバックアップを簡単にスケジューリングできました。GAEやGASで定期実行のためのプログラムを書く必要がなくなり、便利ですね。

料金もジョブ 3つまで無料、4 つ以降はジョブ1つ辺り $0.1 / Month ととても安いです。(参考: Cloud Scheduler Pricing)

定期的に行っているタスクがある場合はぜひ使ってみて下さい!

Tip us!

エンジニアチームのブログを書くモチベーションが上がります!

image