GCPのCloud Shellを使ってFirestoreのデータを別アカウント間で移行する
モチベ
個人的に作ったFlutter×Firebaseの出退勤アプリを社内で使ってもらってたんですが、退職することになったので、会社のアカウントにデータを移行することになりました。
使ったもの
- Cloud Shell
- Cloud Storage
- Service Account
- Firestore
前提条件
元々使っていたFirebase
アカウントをSRCアカウントとします。
新しく使うFirebase
アカウントをDSTアカウントとします。
- SRCアカウント、DSTアカウント共に課金を有効かさせておくこと(少なくともBlazeプラン、Sparkプランはだめです)
- SRCアカウント、DSTアカウント共にCloud IAMの権限が与えられていること。https://cloud.google.com/iam/docs/granting-changing-revoking-access?hl=ja#grant_access
- SRC、DST共にFirestoreの構成リージョンを確認しておくこと。
- 今回はSRCはusマルチリージョン、DSTはasiaマルチリージョンです。
手順
最初に大まかな流れを説明すると以下のようになります。
- GCPコンソールでCloud Shellを準備する
- SRCアカウントの
Firestore
からデータのエクスポートを利用してCloud Storage
バケットにデータを移す - DSTアカウントでサービスアカウントを作成する
- そのサービスアカウントにSRCアカウントのバケットにアクセスする権限を与える
- SRCアカウントのバケットをDSTアカウントに転送する
- DSTアカウントでデータのインポートを利用してバケットから
Firestore
にデータを取り入れる
それでは一つ一つ説明していきます〜
タイトルのかっこの中は作業をSRCアカウントとDSTアカウントのどちらでやるのかを表しています。
1. (SRC,DST) Cloud Shellを準備する
まずはCloud Shellを起動します。GCPコンソールでCloud Shellターミナルを出します。
おそらく最初は別のプロジェクトが指定されていると思います。
user_name@cloudshell:~ (river-woodland)$
このriver-woodland
がCloud Shell内で指定されているプロジェクトです。ここを変えずにそのまま進めると、別プロジェクトの操作しちゃうってことになるので気をつけましょう。
というわけでgcloud
コマンドを使ってFirebase
プロジェクトのIDを指定しましょう。
ちなみにFirebase
プロジェクトのIDはFirebaseコンソールのプロジェクトの設定画面から確認できます。
gcloud config set project [FIREBASE_PROJECT_ID]
仮にFirebase
プロジェクトのIDがfirebase-icetower
だとすると
gcloud config set project firebase-icetower
で指定できます。
user_name@cloudshell:~ (firebase-icetower)$
みたいな表示に変われば成功です。
2. (SRC) Firestore → Cloud Storage Bucket (エクスポート)
それでは今まで使っていたFirestore
のデータをCloud Storage Bucketにエクスポートしていきます。
まずはバケットの作成です。公式ドキュメントに書いてある通りに作成していきます。
今回はCloud Shellを使って作成していきます。
gsutil mb -p [PROJECT_ID] -c [STORAGE_CLASS] -l [BUCKET_LOCATION] -b on gs://[BUCKET_NAME]
なんかたくさんオプションがあってわけわかめだと思いますので説明していきます。
- p : GCPプロジェクトのIDを指定します。Firebaseプロジェクトと同じでOKです。
- c : ストレージクラスです。一時的なデータ格納なので
Standard
でいいと思います。 - l : バケットのリージョンを指定できます。Firestoreのリージョンと同じにしましょう。じゃないとダメらしいです。
- b : 均一なバケットレベルのアクセスを有効にするか否かです。onでいいでしょう。
SRCのFirestoreプロジェクトの構成リージョンはus
マルチリージョンなので、仮にPROJECT_ID
がfirebase-icetower
だとするとこうなります。
gsutil mb -p firebase-icetower -c Standard -l us -b on gs://source_bucket
source_bucket
は自分で決めてOKです。neo_armstrong_cyclone_jet_armstrong_bucket
でも大丈夫です。
gsutil ls
でバケットの作成が確認できれば成功です。
そうしたら漸くですが、Firestoreのデータを作成したバケットの中に入れていきます。
と、その前にもしエクスポートは時間がかかる作業なのでその間にFirestoreへの書き込みが行われないことを担保する必要があります。
ポイントは2つです.
- Firestoreのセキュリティルールを変更して書き込みを一時的に阻止する
- Firebaseの管理サーバーがあるのであれば、シャットダウンするか書き込みオペレーションを停止させる。
今回は平日のみの使用を想定しているのと、管理サーバーを利用していないことから、手順を省きます。
上記2つ確認できたらFirestoreのデータをエクスポートしていきます。
gcloud firestore export gs://source_bucket --async
はいOKです。出力の中にoutputUriPrefix
があると思うんですが、後で使います。必ずメモしておきましょう。
outputUriPrefix: gs://source_bucket/2021-06-27T08:06:32_12345
↑こういうやつです。
3. (DST) サービスアカウントの作成
ここまでできたら続いてサービスアカウントを作成していきます。
DSTアカウント側で1.と同じCloud Shellの準備を忘れずに行いましょう。
Cloud Shellの準備ができたら、サービスアカウントの作成を行っていきます。
Cloud Consoleでもできますが今回はCloud Shellを使っていきます。
gcloud iam service-accounts create [SERVICE_ACCOUNT_ID] \
--description="[DESCRIPTION]" \
--display-name="[DISPLAY_NAME]"
[DESCRIPTION]
はなくてもOKですが、後でこれなんのために作ったっけ?を防止するためにも説明を書いておきましょう。
[SERVICE_ACCOUNT_ID]
と[DISPLAY_NAME]
はIDと名前です。必須ですが自分で決めてOKです。
後でこのサービスアカウントを使って作業する時にオーナー権限が必要になるので付与していきます。
(*)コマンドで作成する方法が見つからなかったのでCloud Console(GUI)を使って付与していきます…!
左上のハンバーガーメニューからIAMと管理/IAMを選択します。
選択できたらIAMの追加ボタンを押して追加していきます。追加ボタンを押すと下の画面が出てくると思います。
ここでメンバーとロールを聞かれますが、メンバーはさっき追加したサービスアカウントのEMAIL、ロールはオーナーで作成します。
サービスアカウントのEMAILはgcloud iam service-accounts list
で確認できます。
保存したら完了です。
(補足)
gcloud projects add-iam-policy-binding
でも同じことができるかなと思いましたがうまくいきませんでした。上手くいった方がいましたら教えていただけると幸いです…!
4. (SRC) DSTのサービスアカウントにSRCバケットへのアクセス権限を付与
DST側のサービスアカウントが作成できたらSRC側でSRCバケットへのアクセス権限を付与します。
gsutil iam ch \
serviceAccount:[SERVICE_ACCOUNT_EMAIL]:objectViewer \
gs://at10dance_transform
[SERVICE_ACCOUNT_EMAIL]
はそのままですが、さっき作ったサービスアカウントのEMAILです。
service-account@firebase-icetower.iam.gserviceaccount.com
みたいなやつです。
5. (DST) SRCバケットをDSTバケットに転送
DSTのサービスアカウントにSRCバケットへのアクセス権限が付与までできたと思うので、DST側からSRCバケットのコピーをDSTプロジェクト内に作ることで転送が完了できます。
まずは先ほど作ったサービスアカウントを有効にします。
サービスアカウントのキーファイルを作成して
gcloud iam service-accounts keys create [key-file] \
--iam-account=[SERVICE_ACCOUNT_EMAIL]
[key-file]
はキーファイルのPATHです。なんでもOKですkeys.json
でも./neo_armstrong/cyclone_jet/armstrong.json
でもなんでもいいです。あとで分かれば。
[SERVICE_ACCOUNT_EMAIL]
はサービスアカウントのEMAILです。
キーファイルをもとにサービスアカウントを有効化していきます。
gcloud auth activate-service-account [SERVICE_ACCOUNT_EMAIL] --key-file=[key-file]
これでサービスアカウントの有効化ができました。
次に転送先のバケットも作っておきます。
gsutil mb -p firebase-icetower -c Standard -l us -b on gs://dst_bucket
あとは転送するのみです
gsutil cp -r gs://source_bucket gs://dst_bucket
Operation Completed
て表示されたらOKです。
6. (DST) Cloud Storage Bucket → Firestore (インポート)
ついに来ました最後です…!DSTアカウントのFirestoreにデータをインポートします!!
最後だからって気を抜いたらあかんで!!
gcloud firestore import gs://[SOURCE_BUCKET]/[EXPORT_PREFIX] --async
[SOURCE_BUCKET]
はSRC側のバケット名ですsource_bucket
です。
[EXPORT_PREFIX]
はSRC側でFirestoreからエクスポートした時のoutputUriPrefix
です2021-06-27T08:06:32_12345
っていうさっきメモしてねって言ったやつです。
gcloud firestore operations list
でoperationState
がSUCCESSFUL
になってたら完了です。Firestore
を見にいって確認してみましょう!!
はい!!!終わり!!!!!
参考文献
Discussion