Cloud Functions for Firebaseを無料枠の範囲内で使っていたはずなのに、GCP(Google Cloud Platform)上で費用が発生していた。なぜ?何に気をつければよいの?
という方向けの記事です。
自分がこの状況に遭遇し、たった数円ではありますが、想定外の費用が発生してしまいました。
原因と対策を調査するため、Cloud Functionsの公式説明、ネット記事の調査、Firebaseのサポートへの問い合わせなどをしたので、ご参考にその結果を共有できればと思います。
※以降、「関数」は「Functions」という表記で統一しています。
一部推測も含まれますが、現時点での自分なりの結論は、以下のとおりです。
- Functionsをデプロイすると、レプリケーション(複製)やコンテナイメージの保存等により、Cloud Storageの費用が発生する場合がある
- 予期せぬ費用発生を抑える対策としては、①デプロイは最新のFirebase CLI環境下で行うこと、②無駄にデプロイの回数を増やさないこと、③費用はFirebaseではなくGCPの費用レポート画面でチェックすること。
あくまで現時点での自分の理解であり、間違っている部分もあると思いますので、お気づきの際はご指摘くださいm(_ _)m。
なお、Cloud Functionsについては、下記記事で使用例を紹介していますので、よろしければご参照ください。
40代からプログラミング(Flutter)を始めて、GooglePlayとAppStoreにアプリを公開しているhalzo appdevです。
作成したアプリはこちら↓ 全てFlutterで開発したアプリです。
リージョン間のレプリケーションが行われたことで課金が発生
Cloud Functionsのデプロイを複数回実行した数日後に、GCP(Google Cloud Platform)から「予算の100%に達しました」というメールが来て、4円の費用が発生していることが分かりました。
Functionsの呼び出し回数は数回程度だったため、無料枠の範囲内と認識しており、また、過去に同様のFunctionsをデプロイした際にも、料金は発生しなかったので、驚きました。
ネット上を調べると、Firebaseの費用関係は、サポートに問い合わせ可能とのことだったので(参考記事)、早速下記のページ
から問い合わせたところ、サポートのご担当者から、下記回答をいただきました(一部抜粋)。
In your specific case the billing correspond to the next item:
・Networking Traffic Egress GCP Replication within Northern America.
The cost per GB to Inter-region replication is $0.02. In your case you have 1.46 GB consumed, that is $0.0292 in your local currency is around ¥4.08.
(和訳)
あなたのケースでは、請求内容は次の項目に該当します。
・北米内のネットワーキング トラフィックの下り GCP レプリケーション。
リージョン間レプリケーションの GB あたりのコストは 0.02 USD です。 あなたの場合、1.46 GB が消費されています。つまり、現地通貨で $0.0292 は約 ¥4.08 です。
Functionsをデプロイしたリージョンで、レプリケーション(複製)が行われ、その通信が有料課金対象だったようです。
回答メール内で、参照先として紹介されていた、GCP公式サイトの下記ドキュメント
を確認したところ、Cloud Storageは、「データストレージ」、「データ処理」、「ネットワーク使用量」の3つに対して費用発生するとのことで、自分のケースでは「データ処理」の1つである「リージョン間レプリケーション」で課金(1GBあたり0.02$)が発生したようです。
Firebase上では、Cloud Storageの利用設定を一切していなかったので、まさかCloud Storageの費用が発生するとは思いませんでした。。
Firebase Functionsの管理画面(使用量と請求額)は正確ではない
Firebase Functionsの管理画面では、「Cloud Storage」、「Functions」いずれも無料枠内となっていたので、その点もサポートに問い合わせました。
回答は、Firebaseの管理画面の金額は正確ではないので(更新頻度も低い)、あくまで費用の情報は、GCPの管理画面の「お支払い」→「レポート」の画面で確認するように、とのことでした。
確かに、レポート画面を見ると、「Networking Traffic Egress GCP Replication within Northern America」の利用で、4円の費用が発生しているのが分かりました。
なぜリージョン間レプリケーションが行われたのか?
結論から言うと、明確には分かりませんでした。。
サポートにも質問したのですが、後述するデプロイ時のコンテナイメージ構築の流れは教えてもらったものの(これ自体は、初めて知ったので、有り難かったのですが)、レプリケーションされた理由については、「使用したNode.jsのランタイム構築方法による」という感じで、明確な回答は、得られませんでした(自分が知識不足でうまく質問できなかった事もあり、、)。
ネットで調べると、後述する「###.artifacts.###」の蓄積による費用増加問題の記事は多く見つかりますが、レプリケーションによる費用発生の記事は少なく、唯一、Redditの下記スレッドが見つかりました。
この投稿者の方の質問内容は、自分とほぼ同じ状況でした。
この中の下記やりとり
で、複数のリージョン(マルチリージョン)に保存すると、負荷分散や障害対応の観点から、レプリケーションが行われる、との回答がされていました。
その他にも、同スレッド内に、「マルチリージョンを選択したため」や「レプリケーションを有効にしたため」とのコメントもありました。
Functionsをデプロイする際、Node.jsを使っているため(こちらの記事で使用例をご紹介しています)、npmコマンドでインポートしたソースコードの中で、関連しそうな箇所を確認しましたが、リージョンやレプリケーションを指定している様子は見られませんでした。。
ここからは完全に推測になりますが、、後述する「###.artifacts.###」のバケットについて、その保存地域をGCPで確認すると、「us(米国の複数のリージョン)」となっているので、
デプロイすると、「###.artifacts.###」が複数リージョンに保存され、その結果、レプリケーションが発生した、ということなのかもしれません。
ただ、過去に同様のFunctionsをデプロイしたときの履歴を確認すると、「###.artifacts.###」が複数リージョンに保存されていても、レプリケーションは発生していませんでした。この点は、Google側で要否の判断を自動で行っているのかもしれません。
下記のGCP公式説明ページ
には、下記の説明があります。
Cloud Functions はリージョナルです。つまり、Cloud Functions を実行するインフラストラクチャは特定のリージョンに配置され、そのリージョン内のすべてのゾーンで冗長的に利用できるように Google によって管理されます。
また、下記のGCP公式説明ページ
には、以下の記述もあります。
お客様はリージョンを選択できますが、リージョンを構成するゾーンは選択できません。データとトラフィックは、リージョン内のゾーン間で自動的に負荷分散されます。
これらはあくまでリージョン内の話ではありますが、これと同様に、リージョン間においても、Googleの自動判断で分散が行われるのかな、、という気がします。
1つ思い当たる点としては、レプリケーションが発生した日に、実験的に、複数回に渡り(5〜6回)、Functionsをデプロイしたことです。
※デプロイ済のFunctionsを削除せず、上書きする形でデプロイしたり、Functionsを削除してから新規でデプロイしたりしたほか、デプロイ時に使用するNode.jsのバージョンも、10、14、16の3通りでやったりしました。
どの要素が原因かは分かりませんが、単にデプロイ回数が多かったことで、そのうち1回が、レプリケーション必要との判断になったのかもしれません(全く見当違いかもしれませんが、、)。
デプロイ時に生成されるバケットにより、Cloud Storageの費用が発生する恐れもあり
Functionsの予期せぬ費用発生、という内容で調べると、この趣旨の記事が多くヒットします。
参考にさせていただいた記事は以下のとおりです(ありがとうございますm(_ _)m)。
概略としては、Cloud Functions for Firebaseの下記公式サイト
に説明があるとおり、Functionsをデプロイすると、
- Firebase CLIは、Functions(関数)コードの.zipアーカイブを作成する。
- このアーカイブは、Cloud FunctionsがプロジェクトにArtifactレジストリリポジトリ(gcf-artifactsという名前)を作成する前に、Cloud Storageバケット(接頭辞gcf-sources)にアップロードされる。
- Cloud Buildが、Functions(関数)コードを取得し、Functions(関数)ソースをビルドする。
- ビルドされたFunctions(関数)コードのコンテナイメージは、プロジェクトのプライベートArtifact Registryリポジトリ(gcf-artifactsという名前)にアップロードされ、新しいFunctions(関数)がロールアウトされる。
というプロセスが走るそうです。
細かい用語は理解が及んでいない部分もありますが、、要は、Functionsをデプロイするためには、Functions本体や、その他の一時的な参照データの保存場所としてCloud Storageを使う、と理解しました。
※Firebase用ではないCloud Functionsの場合は、こちらのプロセスになるようですが、一時的にCloud Storageを使うという点では、大まかには同じと理解しました。
そのため、Firebase側ではCloud Storageを使っていないつもりでも、Functionsをデプロイすると使ってしまう、という話です。
ただ、デプロイが終われば、「###.artifacts.###」という名前のバケットは必要ないため、いずれの参考記事でも、これを削除することでStorageの使用量を減らす、という対策が紹介されていました。
日次では有料ラインに届かずとも、累積すると費用が発生する?
自分の場合も、確かに下図のとおり、「###.artifacts.###」のバケットが68.3MB発生しており、Firebaseの管理画面上にも、ほぼ同容量が認識されていました。
Firebase側を見ると、無料枠上限である5GBには達していないので、一見、問題ないように見えますが、GCP側の費用レポートを見たところ、累積費用が下図のように表示されていました。
これを見ると、毎日わずかながら、1円に満たない費用が積算されているので、いつかは1円に到達しそうです。。
そのため、少量とは言え、無駄なバケットを削除することにしました。
削除方法は、ライフサイクルの設定による方法(「XX日後に削除」など)がよく紹介されていますが、こちらやこちらの記事コメントによると、望ましくないようです。
一方で、同記事コメントによると、Firebase CLIのバージョンが9.14以降であれば、余計な「artifacts」は生成されない、と書かれていました。
そのため、いったん下図のとおり、手動でバケットを全て削除し、
Firebase側のFunctionsも削除した上で、
最新のFirebase CLIのバージョン(実行当時は、11.19.0)の下で、再度、同じFunctionsをデプロイしました。
この再デプロイ後、問題なくFunctionsが動作している事を確認しました。
すると、下図のように、「gcf-sources###」のバケットのみが生成され、「###.artifacts.###」のバケットは生成されませんでした。
また、費用レポートの画面でも、累積額の増加が止まりました(途中、デプロイ済のFunctionsを削除せず、上書きのデプロイを試した関係で、一時的に増えている日があります、、)。
念のため、Firebase側でCloud Storageを確認すると、やはり「gcf-sources###」のバケット分のみ(161KB)がカウントされていました。
※既存バケットを全削除した際、「###.artifacts.###」→「gcf-sources###」という順番で、段階的に削除した関係で、減り方が階段状になっています。
費用の予測情報はあまり気にしなくて良い
下図のとおり、GCPの費用レポートでは、予測のラインが薄いグレーで描かれていますが、これは過去のトレンドからの推定であり、実際には発生しない費用が見込まれることも多く、あまり気にしなくて良いようです。
自分の場合、12月に再びレプリケーション費用が発生する見込みになっていたので、その点もサポートに質問しましたが、上記の通り「気にしなくて良い」との回答でした(事実、月末に近づいて来ると、予測ラインが修正され、見込み費用はゼロに変わりました)。
今後どう対処するのが良いか?
最新のFirebase CLIの環境下でデプロイすることで、無駄な「###.artifacts.###」は発生せず、その結果、マルチリージョンへの保存も回避されるため、レプリケーション発生も抑制できると思われます。
「###.artifacts.###」の保存が発生した場合、レプリケーションの発生有無についてはコントロールが難しそうなので、無駄なデプロイはできるだけ控えることと、デプロイしたら都度、GCPの費用レポート(Firebaseの画面ではなく)を見て、想定外の費用が発生していないかを確認することが必要かと思います。
※こちらの記事に教えていただきましたが、もし発生した「###.artifacts.###」を削除したい場合は、下記の公式説明
にある「gcr-cleaner」という非公式ツールを使う方法があるようです(ただ、難解な印象なので、試せてはいません。。)。
以上、推測や理解途上の内容も含まれており恐縮ですが、何かのご参考になれば幸いです。
最後までお読みいただき、ありがとうございました。
個人アプリ開発で役立ったもの
おすすめの学習教材
\超初心者向けでオススメな元Udemyの講座/
\キャンペーン時を狙えば安価で網羅的な内容が学べる(日本語訳あり)/
\Gitの基礎について無料で学べる/
おすすめの学習書籍
\実用的。image_pickerに関してかなり助けられた/
\Dartの基礎文法を素早くインプットできる/
コメント
記事ありがとうございます。大変参考になりました。
私も当初同様に請求が発生し、原因究明していてこちらのサイトを拝見しました。
記事を読んで最新のFirebase CLIでデプロイを実験してみましたが、確かにArtifact RegistryはCloud Storageからなくなりました。
しかし追加請求は発生しているように見えます。
おそらく、ご掲示の以下フォーラムにもある通り”the firebase deploy process automatically cleans up its container images after a deploy.”なので、コンテナイメージのレプリケーション後に自動的に削除しているだけであってレプリケーション自体は発生しているのではないかと予想しています。
https://stackoverflow.com/questions/63578581/firebase-storage-artifacts?answertab=votes#tab-top
結局、デプロイ時にレプリケーションがほぼ確実に発生する以上、現状Cloud Functions for Firebaseを無料で使用することは不可能だと思いました。
間違っていましたらご指摘ください。
(一応、Firebaseサポートにも、最新CLIを使って無料枠条件を満たせば無料で利用できるか聞いてみていますが、望み薄だと思っております…。もし有用な回答が来ましたら共有いたします)
すいばり様
コメントいただき、ありがとうございます!
費用発生が避けられない点について、ご指摘のとおりだと思いました。また、なるほど、コンテナイメージの保存=コンテナイメージのレプリケーションということなのですね。。
レプリケーションという言葉の記載が、Google Cloud公式説明の中にもほとんど見つからず、、理解が及んでおりませんでした。
そのため、コンテナイメージが保存されることと、レプリケーションが行われることは、別事象だと思ってしまっており、前者については、公式説明から保存されるロジックは理解できたのですが、後者が行われた理由がわからず、色々調べていた次第でした。
大変勉強になりました。今後ともよろしくお願いいたします。