自分用の備忘録・作業ログです。
荒くてすみません。mm
要件
1.Firestore のバックアップをスケジューリングしたい 2.2週間経過したバックアップの削除もスケジューリングしたい参考リンク:
#まずは手動でバックアップを取る
まずは下記ページから読んでいく
できたこと: firebaseの同一プロジェクト内のStorageに バックアップ用の専用フォルダ「bk」を追加作成し、そちらに手動でバックアップする
【追記】
※自動削除を行う場合には、バックアップ専用のバケットをStorage内に作っておいた方が都合がいい。
なのでディレクトリとして「bk」を作成して保存することは推奨しない。
ざっくりとした流れメモ:
1) Google Cloud プロジェクトに対する課金を有効に
2) Cloud Shell へ(プロジェクト選択)
3) Google Cloud SDK をインストールして初期化(ログイン&プロジェクト選択)
4) Firebaseのプロジェクト内のstrageに、任意のバックアップ用フォルダを作成する(今回は「bk」フォルダを作成)
5) Cloud Firestore の [インポート / エクスポート] ページに移動し、作成したバックアップ用のフォルダを選択
6) エクスポートする
一旦まずはエクスポートはできた。
(※単純にエクスポートを手動でとるだけなら、2)と3)は飛ばして良さそう。)
次は
自動でバックアップを取ってもらうためにスケジューリングしたい。
自動でバックアップを指定した時間に取るように設定
functionsを使用して、ある時間(今回は毎日午前4時)に
自動でバックアップをとるようにする。
上記のページを読んでいくぞ。
ざっくりとした流れメモ:
1) Firebase CLI をインストール
curl -sL https://firebase.tools | bash
「bash」って書いてあるので、「私zshですが大丈夫…?」って思ったんですが大丈夫でした。
インストールする時の設定ですかね。
(ちなみグローバルなものみたいなのでプロジェクト内ではなくインストール)
既に入っていたので最新版に更新
通常、新機能やバグ修正が含まれているのは Firebase CLI の最新バージョンだけです。
CLI の更新を頻繁に行うことをおすすめします。
curl -sL firebase.tools | upgrade=true bash
⚠️つまづいたところ: 後ほど記述する、cloud functionsのデプロイ時に nodeのバージョンが「12.20.0」に対応しておらず詰まりました。 一旦、グローバルのnodeのバージョンを「12.20.0」にした上で firebase toolsをインストールすることで解消しました。
// プロジェクトのディレクトリにて下記実行
nodenv global 12.20.0
npm install -g firebase-tools
firebase -V // ちゃんと動くか確かめ
// その後、(functions作成した後、)functionsのディレクトリに移動してからデプロイ
firebase deploy --only functions:scheduledBackup
もし、別のgoogleアカウントで既にログインしていたら
logoutしてlogin
firebase logout
firebase login
2)Cloud Datastore インポート / エクスポート管理者ロールを割り当て
参考URLにはコマンドで叩くように書いてあるが、
下記URLからGUIでも権限付与が可能。
https://console.cloud.google.com/iam-admin/iam
(PROJECT_ID@appspot.gserviceaccount.com
に対して
Cloud Datastore インポート / エクスポート管理者
ロールを割り当てる)
3)Cloud 関数と Cloud Scheduler ジョブを作成する
https://firebase.google.com/docs/firestore/solutions/schedule-export?hl=ja
ソースコードの例を見ながらこんな感じでCloud functionsを実装。
以下、scheduledBackup.js
const functions = require('firebase-functions')
const firestore = require('@google-cloud/firestore')
const client = new firestore.v1.FirestoreAdminClient()
// Replace 【バケット名】:FirebaseのStorageのページに書いてあるリンク名を参照
const bucket = `gs://【バケット名】`
//例 const bucket = `gs://hogehoge-project-backup.appspot.com`
exports.scheduledFirestoreExport = functions
.region('asia-northeast1')
// .pubsub.schedule('*/2 * * * *')
.pubsub.schedule('0 4 * * *')
.timeZone('Asia/Tokyo')
.onRun((context) => {
const projectId = process.env.GCP_PROJECT || process.env.GCLOUD_PROJECT
const databaseName = client.databasePath(projectId, '(default)')
return client
.exportDocuments({
name: databaseName,
outputUriPrefix: bucket,
// Leave collectionIds empty to export all collections
// or set to a list of collection IDs to export,
// collectionIds: ['users', 'posts']
collectionIds: []
})
.then((responses) => {
const response = responses[0]
console.log(`Operation Name: ${response.name}`)
})
.catch((err) => {
console.error(err)
throw new Error('Export operation failed')
})
})
おまけ:使わなかったコード(ディレクトリ指定&日付指定)
const functions = require('firebase-functions')
const firestore = require('@google-cloud/firestore')
const client = new firestore.v1.FirestoreAdminClient()
const moment = require('moment')
exports.scheduledFirestoreExport = functions
.region('asia-northeast1')
// 分 時 日 月 曜日 の順に指定。
// テスト用に2分おきにバックアップを取る指定
// .pubsub.schedule('*/2 * * * *')
// 毎日深夜4時にバックアップを取る指定
.pubsub.schedule('0 4 * * *')
// この指定のタイムゾーンに則って実行
.timeZone('Asia/Tokyo')
.onRun((context) => {
// timestampをとろうとすると、9時間ずれるので今回はmomentを使って調整。
const timestamp = moment().add(9, 'hours').format('YYYYMMDD-HHmmss')
// Replace 【projectname】:FirebaseのStorageのページに書いてあるリンク名を参照
// 今回は「bk」というフォルダの下に「timestamp」ごとにフォルダを作って保存する
const bucket = `gs://【projectname】.appspot.com/bk/${timestamp}`
const projectId = process.env.GCP_PROJECT || process.env.GCLOUD_PROJECT
const databaseName = client.databasePath(projectId, '(default)')
return client
.exportDocuments({
name: databaseName,
outputUriPrefix: bucket,
collectionIds: []
})
.then((responses) => {
const response = responses[0]
console.log(`Operation Name: ${response.name}`)
})
.catch((err) => {
console.error(err)
throw new Error('Export operation failed')
})
})
今回は下記のような構成なので
index.js
でrequireする。
📁functions
∟📄index.js // ←ここでrequire
∟📁.cert
∟📄【project名】-firebase-adminsdk-xxxxxxxxxxx.json // ←デプロイに必要
∟📁funcs
∟📁scheduled
∟📄scheduledBackup.js // ←これを
∟📄.node-version // 12.20.0
以下、index.js
const admin = require('firebase-admin')
const serviceAccount = require('./.cert/【project名】-firebase-adminsdk-xxxxxxxxxxx.json')
/**
* initialize admin
*/
admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
})
// 他で使ってるやつ
exports.scheduledBackup = require('./funcs/hogehoge.js')
exports.scheduledBackup = require('./funcs/hugahuga.js')
// 今回作ったやつ
exports.scheduledBackup = require('./funcs/scheduled/scheduledBackup.js')
4)デプロイ
デプロイするときには .cert
内に 【project名】-firebase-adminsdk-xxxxxxxxxxx.json
が必要。
また、全てのfunctionsをデプロイするととても重くなるので
該当のものだけ単体でデプロイするのがいい。時間がかかるので。
firebase deploy --only functions // これだと全部デプロイされる
firebase deploy --only functions:scheduledBackup // これだと指定したfunctionのみデプロイされる
設定されたかどうか確認したい時は
こちらの「cloudscheduler」のページでできる。
https://console.cloud.google.com/cloudscheduler
functionsのコンソールを確認したい時は
firebase管理画面の
https://console.firebase.google.com/u/0/project/【プロジェクト名】/functions/list
のページの、右側「…」から見ることができる。
一定期間過ぎたバックアップファイルの削除
こちらの記事を参考にさせていただきました↓🙏
GCSライフサイクル機能を使ってファイルを定期削除する
要点は以下。
・GCSのライフサイクル機能を使う
・バケット単位で「作成から一定時間が経ったデータ」を削除することが可能
(今回はバックアップ専用のバケットを作って、そちらに保存する。
当初はバケット内に専用のディレクトリを作成してその中に保存しようとしていたが、路線変更した。)
(※バケット単位でルールを指定することができる。)
・gsutilツールのコマンドで、設定用のjsonファイルをGCSに設定する
・反映まで24時間くらいかかることもある
他のgoogleアカウントでログインしている場合はログアウトしてからログインし直す。
コマンドは
###ログイン
$ gcloud auth login
###ログアウト
$ gcloud auth revoke
###プロジェクト一覧
$ gcloud projects list
その他コマンドは
以下、
https://qiita.com/Sekky0905/items/65c60da94fe945a454fa
から引用させていただきます。🙏
(もし記事が削除された時用のメモです。)
設定用jsonファイル
14日後に削除する場合
{
"lifecycle": {
"rule": [
{
"action": {
"type": "Delete"
},
"condition": {
"age": 14,
"isLive": true
}
}
]
}
}
"type": "Delete"
ライブ オブジェクトまたはアーカイブされたオブジェクトを削除する
"age": 14
日数指定条件、ageで指定した日数が経過したら条件が満たされたとして、actionが発動する
1年後であれば "age": 365
gsutilツールのコマンドでjsonの設定をGCSに設定する
gsutil lifecycle set [jsonのファイル名] gs://[設定対象のGCSのバケット名]
設定の確認コマンド
gsutil lifecycle get gs://[設定対象のGCSのバケット名]
これが返ってきたら設定うまくいってる
{"rule": [{"action": {"type": "Delete"}, "condition": {"age": 14, "isLive": true}}]}
以下のURLからも確認できる
https://console.cloud.google.com/storage/browser/【バケット名】;tab=lifecycle
リファレンス
https://cloud.google.com/storage/docs/managing-lifecycles