ℹ️
INFO
Google Cloudで予算超過時に自動的に請求を停止する完全な実装ガイド。Pub/Sub、Cloud Run、予算アラートを使った5ステップの設定方法から、無限ループ対策、ACK応答、権限設定の詳細まで、実体験に基づいてまとめました。
そんな中、初めてGoogle Cloud Platform(GCP)を触ったのが、まさにこの予算超過停止処理の作成でした。使える金額が限られているからこそ、少ない予算に到達する前に強制的に料金が増えないようにする緊急手段が必要だったのです。
試作や実験でクラウドサービスを使う際、予想外の課金に怯える日々から、この自動停止機能によってようやく解放されました。本番環境では慎重に運用する必要がありますが、個人開発者として、これほど心強い機能はありません。
⚠️
WARNING
この方法は、プロジェクトの請求先アカウントを物理的に解除する非常に強力で原始的な手段です。設定した予算額に達した時点で、請求先アカウントが必要な主要サービスが即座に停止します。ただし、予算を超えてもすぐにアラートが出るわけではなく、Google側の集計タイミング次第で数時間(場合によっては6時間以上)かかります。そのため、実際の課金額が設定額を超えてから停止することもあります。この点を必ず理解した上で導入してください。
予算超過時に自動的に請求を停止する完全な仕組み。Pub/Subトピックの作成から、予算アラートの設定、Cloud Run関数の実装、権限設定まで、5ステップで実装できます。ただし、実装後に発生する問題(無限ループ、権限エラー)も含めて、すべてのトラブルシューティングとベストプラクティスをまとめました。
予算超過時に自動的に請求を停止する仕組みは、5つのステップで実装できます。ただし、実装後に発生する問題(無限ループ、権限エラー)も含めて、すべてのトラブルシューティングとベストプラクティスをPart 2とPart 3で解説します。
予算アラートのメッセージを受け取るための「連絡路」を作成します。Pub/Sub(Publish/Subscribe、メッセージングサービス)は、予算アラートが発火した際にCloud Run関数に通知を送信する役割を担います。
ℹ️
INFO
💡 検索バーの活用:上部の検索バーに pub と入力すると、Pub/Subサービスへのリンクが表示されます。この検索バーはかなり強力で、サービス名や機能名を入力するだけで素早く目的のサービスにアクセスできます。
ℹ️
INFO
💡 検索バーの活用:上部の検索バーに 予算とアラート と入力すると、該当するサービスへのリンクが表示されます。メニューを探すより素早くアクセスできます。
⚠️
WARNING
📝 予算設定の注意点:画面下部の説明文に記載されている通り、費用は通常24時間以内に記録されます。費用を報告する時間を考慮して、予算を低めに設定することが推奨されています。これが、実際に止めたい金額より10〜20%低く設定する理由の一つです。また、予算を超えてもすぐにアラートが出るわけではなく、Google側の集計タイミング次第で数時間(場合によっては6時間以上)かかります。そのため、1,000円設定でも実際には1,100円〜1,200円程度課金されてから止まることがあります。
動作の流れ
予算アラート → Pub/Sub通知 → Pub/Subがメッセージ送信 → Cloud Runの関数が実行 → 請求停止処理
つまり、予算アラートが発火すると、Pub/Subトピックに通知が送信され、その通知を受けてCloud Runの関数が自動的に実行され、請求停止処理が行われます。
ℹ️
INFO
💡 検索バーの活用:上部の検索バーに cloud functions または cloud run と入力すると、サービスへのリンクが表示されます。
⚠️
WARNING
⚠️ 重要:このトリガー設定により、Pub/Subトピックにメッセージが送信されると、自動的にこのCloud Run関数が実行されるようになります。エントリポイントがデフォルト(例: hello_pubsub など)のままだと、関数を実行しようとした際に「その名前の関数が見つかりません」というエラーになり、自動停止が作動しません。
⚠️
WARNING
⚠️ 重要:以下のコード内の project_id = "gen-lang-client-0302946227" の部分を、ご自身のプロジェクトIDに書き換えてご利用ください。プロジェクトIDは、Google Cloudコンソールのウェルカムページで確認できます。
改善版コードのポイント
1. 冪等性の確保(重複メッセージ対策):
- 処理前に既に請求先アカウントが解除されているかチェックします。
- 既に解除されている場合は、処理をスキップして正常終了します。
- これにより、同じメッセージが複数回配信されても、安全に処理できます。
2. エラーハンドリングの改善:
- エラーが発生した場合でも、関数は正常終了させるようにしています。
- これにより、Cloud Run関数が適切にACKを送信し、再配信を防ぎます。
- ただし、実際のエラーはログに記録されるため、問題の追跡が可能です。
3. ACKの自動送信:Cloud Run関数でPub/Subトリガーを使用する場合、関数が正常に完了すると自動的にACKが送信されます。エラーが発生しても、例外をキャッチして正常終了させれば、ACKが送信され、再配信を防ぐことができます。
requirements.txt の内容
functions-framework==3.*
google-api-python-client
ステップ4: APIの有効化
Cloud Billing API(外部サービスとやり取りする仕組み)を有効化します。これがないと、プログラムが請求システムにアクセスできません。
手順:
- Cloud Billing API を有効にするを開きます。
- [有効にする] をクリックします。
自動的に有効化されるサービス
予算超過停止処理を設定する過程で、以下のような複数のサービスが自動的に有効化されます。自動処理を進めていくと、ほぼ半自動でこれらのサービスがONになるか、またはダイアログで「有効化してください」と丁寧に知らせてくれます。
主に有効化されるサービス:
- Cloud Billing API:請求管理に必要
- Cloud Pub/Sub API:予算アラートの通知に必要
- Cloud Run Admin API:Cloud Run関数の実行に必要
- Cloud Logging API:ログの記録に必要
- Cloud Build API:関数のデプロイに必要
- Eventarc API:イベントトリガーに必要
- Identity and Access Management (IAM) API:権限管理に必要
ℹ️
INFO
💡 自動有効化について:これらのサービスは、設定手順を進めていく過程で自動的に有効化されるか、または必要なタイミングで「このAPIを有効化してください」というダイアログが表示されます。手動で一つずつ有効化する必要は基本的にありません。Google Cloudが適切なタイミングで案内してくれます。
ステップ5: 権限(IAM)の設定(最重要)
Cloud Run関数のサービスアカウントに「お支払い元管理者」(Billing Account Administrator)と「プロジェクトの請求費用管理者」(Project Billing Manager)の
両方の権限を付与します。片方だけでは確実に動作しません。詳細な設定手順と、2つの権限が必要な理由については、Part 3で解説します。
⚠️
WARNING
🔴 最重要:なぜ権限が必要なのか。この関数は、請求先アカウントとプロジェクトを切り離すという非常に強力な処理を実行します。請求先アカウントを切り離すと、有料サービスのほとんどが即座に停止します。具体的には、Cloud Run、Cloud Functions、Compute Engine、Cloud SQL、BigQuery、Cloud Storage(有料枠)、Vertex AI、APIサービスなど、請求先アカウントが必要なサービスは全て利用できなくなります。このような強力な処理を実行するには、関数に「お支払い元管理者」(Billing Account Administrator)と「プロジェクトの請求費用管理者」(Project Billing Manager)の両方の権限が必要です。権限がないと、関数は実行時に403 ForbiddenやPermission Deniedエラーで失敗し、自動停止処理が作動しません。
Part 2: トラブルシューティングとベストプラクティス
設定手順を実装した際に発生する可能性のある問題と、その解決方法をまとめました。特に、Pub/Subの無限ループ(再配信)対策と、メッセージ確認応答(ACK)の重要性について詳しく解説します。
Pub/Subの無限ループ(再配信)を確実に防ぐ
Pub/Subは、関数がエラー(例外)で終了すると、「処理に失敗したんだな」と判断して良かれと思って何度もメッセージを再送してきます。
⚠️
WARNING
🔴 重要:Pub/Subの無限ループ(再配信)を確実に防ぐ。Pub/Subは、関数がエラー(例外)で終了すると、「処理に失敗したんだな」と判断して良かれと思って何度もメッセージを再送してきます。
問題の発生パターン:
- 1回目:予算超過で請求先アカウントを解除 → 成功 ✅
- 2回目:同じメッセージが再配信される → 「もう止まってるよ!」というエラー(403 Forbidden)が発生 ❌
- 3回目以降:エラーが続く → Pub/Subは「処理に失敗した」と判断して再送 → 無限ループに陥る 🔄
結果として、ログにエラーが大量に記録され、不要な再配信が続いてしまいます。
改善版コードの解決策:
- 1回目:予算超過で請求先アカウントを解除 → 成功 ✅
- 2回目:同じメッセージが再配信される → 既に止まっているかチェック → 「既に解除されています。処理をスキップします。」と表示して正常終了(return) ✅
- 3回目以降:Google Cloudは「無事に受け取った(ACK完了)」と判断し、再送を止める ✅
既に請求先アカウントが解除されている場合は「処理をスキップ」して正常終了(return)するため、Google Cloudは「無事に受け取った(ACK完了)」と判断し、再送を止めてくれます。これにより、
無限ループ(再配信)を確実に防ぐことができます。
なぜ複数回実行されるのか?
ℹ️
INFO
💡 重要なポイント:なぜ複数回実行されるのか?予算アラート自体は複数回発火していません。 Google Cloudの予算アラートは、予算のしきい値を超えた時点で一度だけ通知を送信するのが一般的です。
問題はPub/Subのメッセージ配信特性にあります:
- Pub/Subは「at-least-once」(少なくとも1回)配信モデルを採用しており、同じメッセージが複数回配信される可能性があります。
- メッセージの確認応答(ACK)が適切に行われなかった場合、一定時間後に自動的に再配信されます。
- Cloud Run関数がメッセージ処理後にエラーが発生したり、ACKがタイムアウトしたりすると、Pub/Subはメッセージが処理されなかったと判断し、再配信します。
- 最初の実行で紐付け解除は成功しましたが、その後の処理で何らかの理由でACKが適切に行われなかった可能性があります。
結論:予算アラートが複数回発火しているのではなく、
Pub/Subからの同じメッセージが複数回配信されていることが原因です。そのため、2回目・3回目の実行時に、既に請求先アカウントが解除されている状態で再度解除を試みるか、または権限チェックが厳密になり、エラーが発生しています。
メッセージ確認応答(ACK)を適切に行う方法
Cloud Run関数でPub/Subトリガーを使用する場合、
関数が正常に完了すると自動的にACKが送信されます。ただし、以下の点に注意が必要です:
- 関数は必ず正常終了させる:エラーが発生した場合でも、例外をキャッチして関数を正常終了させると、ACKが送信され、再配信を防げます。改善版コードでは、エラーハンドリングでこれを実現しています。
- 冪等性の確保(重複処理対策):同じメッセージが複数回配信されても安全に処理できるように、処理前に状態をチェックします。改善版コードでは、請求先アカウントが既に解除されているかチェックしています。
- 処理時間を短縮する:Pub/Subの確認応答期限(デフォルト10秒)内に処理を完了させることが推奨されます。処理時間が長い場合は、Cloud Runのタイムアウト設定やPub/Subの確認応答期限を延長することも可能です。
- エラーはログに記録する:エラーが発生しても関数を正常終了させることでACKを送信しつつ、エラー内容はログに記録して問題を追跡できるようにします。
改善版コードを使用することで:
- ✅ 既に請求先アカウントが解除されている場合は、処理をスキップして正常終了(ACK送信)
- ✅ エラーが発生しても、例外をキャッチして正常終了(ACK送信)
- ✅ 重複メッセージが配信されても、安全に処理可能(冪等性確保)
- ✅ 不要な再配信を防ぎ、ログのエラーを削減
Pub/Subのメッセージ保持期間について
⚠️
WARNING
⚠️ 重要:Pub/Subのメッセージ再送機能について。最初、ACK応答を考えずにトリガーで紐づけカットのみで実装していた場合、再度紐づけしても切れていたという問題が発生することがあります。これは、Pub/Subのメッセージ再送機能が原因です。
Pub/Subのメッセージ保持期間:Google Cloud Pub/Subは、
未確認(未ACK)のメッセージを最大7日間保持します。この期間中、メッセージが適切にACKされないと、何度も再送され続けます。
問題の発生パターン:
- 予算超過で請求先アカウントを解除 → 成功 ✅
- しかし、関数がエラーで終了したため、ACKが送信されない ❌
- Pub/Subは「メッセージが処理されなかった」と判断し、再送を続ける 🔄
- 請求先アカウントを手動で再度紐づけしても、古いメッセージが再送され続け、再度解除されてしまう 🔄
- この状態が最大7日間続く可能性がある ⏰
解決策:
- コード側の対策:改善版コードでは、既に請求先アカウントが解除されている場合は処理をスキップして正常終了(ACK送信)するため、再送を防げます。
- 手動での対策:もし既に古いメッセージが残っている場合は、手動でメッセージをパージ(削除)することができます。
手動でメッセージをパージ(削除)する方法
もし既に古いメッセージが残っていて、再送が続いている場合は、手動でメッセージをパージ(削除)することができます。これにより、未確認のメッセージを一括で削除し、再送を止めることができます。
手順:
- [Pub/Sub] > [サブスクリプション] を開きます。
- サブスクリプション一覧から、
stop-billing-topic-sub(または作成したサブスクリプション名)をクリックして開きます。
- サブスクリプションの詳細画面で、上部のアクションボタンから 「メッセージをパージ」(Purge Messages)ボタンをクリックします。
- 確認ダイアログが表示されます。警告メッセージを確認し、「パージ」ボタンをクリックします。
- これにより、サブスクリプション内のすべての未確認メッセージが削除され、再送が止まります。
⚠️
WARNING
⚠️ 注意:パージされたメッセージは復元できません。また、確認済みメッセージの保持が無効になっている場合、パージされたメッセージは完全に削除されます。
Part 3: 権限設定の詳細
2つの権限が必要な理由、各権限の設定手順、よくある設定ミスと解決策などの詳細を解説します。特に、なぜ「請求先アカウント管理者」のみでは不十分なのか、その理由を詳しく説明します。
なぜ2つの権限が必要なのか
Google Cloudでは、プロジェクトと請求先アカウントの紐付け解除には、
2つの権限が両方必要です。
2つの権限が必要な理由
請求先アカウント側の権限:「お支払い元管理者」(Billing Account Administrator)→ 「お財布(請求先アカウント)を開ける権限」
プロジェクト側の権限:「プロジェクトの請求費用管理者」(Project Billing Manager)→ 「プロジェクトとお財布の間の鎖を切り離す権限」(resourcemanager.projects.deleteBillingAssignment)
なぜ両方必要なのか? Google Cloudでは、他人のプロジェクトに勝手に自分の請求先を紐付けられたり、逆に勝手に外されたりしないよう、「お財布側の許可」と「プロジェクト側の許可」が両方そろわないと紐付け解除ができないセキュリティルールになっています。
なぜ「請求先アカウント管理者」のみでは不十分なのか
実際の運用では、
「請求先アカウント管理者」の権限のみでも、紐付け解除自体は成功することがあります。しかし、その後の自動処理で問題が発生します。
最初は、「請求先アカウント管理者」のみでも、紐付け解除自体は成功します。API呼び出し自体は成功し、紐付け解除が実行されます。ログには 請求の無効化に成功しました と表示されます。しかし、Cloud Run関数自体は即座には停止しません。通常、しばらくの間は動作し続けます。そのため、Pub/Subからのメッセージが複数回配信されたり、同じメッセージが再処理されたりすることがあります。
同じ関数が再度実行されると(Pub/Subからの再送信やリトライにより)、この時点でGoogle Cloudがプロジェクト側の権限も厳密にチェックします。既に請求先アカウントが解除されている状態で再度解除を試みるか、または検証段階でプロジェクト側の権限が求められ、User does not have permission on project to disable billing や resourcemanager.projects.deleteBillingAssignment というエラー(403 Forbidden)が発生します。
エラーが続くと、Pub/Subは「処理に失敗した」と判断して再送を続けます。この状態が最大7日間続く可能性があります。そのため、請求先アカウントを手動で再度紐づけしても、古いメッセージが再送され続け、再度解除されてしまいます。
実際のログ例(「請求先アカウント管理者」のみの場合):
13:55:11 - 請求の無効化に成功しました: {'billingEnabled': False}
13:55:15 - 予算超過のため、請求を無効化します...(再実行)
13:55:16 - エラーが発生しました: HttpError 403
"User does not have permission on project to disable billing"
permission: 'resourcemanager.projects.deleteBillingAssignment'
13:55:28 - 予算超過のため、請求を無効化します...(3回目の実行)
このログから分かること:最初の実行(13:55:11)では成功しましたが、2回目の実行(13:55:15)、3回目の実行(13:55:28)でエラーが発生しています。
⚠️
WARNING
⚠️ 結論:「請求先アカウント管理者」のみでも一時的に成功することがありますが、その後の自動処理でエラーになるため、最初から両方の権限を設定することが推奨されます。特に、請求先アカウントを手動で紐付け直した後は、Google Cloud側が厳密にチェックするようになり、プロジェクト側の権限がないと確実にエラーで失敗します。
権限設定手順
以下の手順で、Cloud Run関数のサービスアカウントに
両方の権限を付与します。
ステップ1:サービスアカウントの確認
- Cloud Runの画面で、作成した関数
stop-billing-function を開きます。
- 「セキュリティ」タブまたは「設定」タブから、サービスアカウントのメールアドレスを確認します。
- 例:
stop-billing-function@プロジェクトID.iam.gserviceaccount.com
- このメールアドレスをコピーしておきます。
ステップ2:請求先アカウント側の権限設定
- [お支払い] > [アカウント管理] を開きます。
- 画面右側の [権限] パネルで、[プリンシパルを追加] をクリックします。
- 新しいプリンシパル:コピーしておいたCloud Run関数のサービスアカウントのメールアドレスを貼り付けます。
- ロールを選択:
-
[お支払い] カテゴリを選択します。
- 表示されるロール一覧から、
[お支払い元管理者](
Billing Account Administrator)を選択します。
- ⚠️ 注意:「お支払い元閲覧者」「お支払い元ユーザー」「お支払い元コスト マネージャー」などと間違えないよう注意してください。これらでは請求先の切り離しはできません。
- [保存] をクリックします。
ℹ️
INFO
💡 補足:請求先アカウント側で両方の権限を設定することも可能。請求先アカウント側の権限設定画面では、「請求先アカウント管理者」だけでなく、「プロジェクトの請求費用管理者」も同時に設定できます。「+ 別のロールを追加」をクリックして、追加のロールとして「プロジェクトの請求費用管理者」(Project Billing Manager)を選択し、一度に両方の権限を設定することも可能です。ただし、通常は請求先アカウント側で「請求先アカウント管理者」を設定し、プロジェクト側のIAMで「プロジェクトの請求費用管理者」を設定する方法が一般的です。
ステップ3:プロジェクト側の権限設定(必須)
次に、プロジェクト側の権限を設定します。これがないと、請求先アカウントを紐付け直した後などにエラーで失敗する可能性があります。
- [IAM と管理] > [IAM] を開きます。
- リストから
stop-billing-function@... のサービスアカウントを探します。
- 右側の鉛筆アイコン(編集)をクリックします。
- [別のロールを追加] をクリックします。
- ロールを選択:
- 検索バーに
請求 または
billing と入力します。
- 表示されるロール一覧から、
「プロジェクトの請求費用管理者」(英語名:
Project Billing Manager)を選択します。
- ⚠️ 注意:「プロジェクトの請求費用閲覧者」(Project Billing Viewer)などと間違えないよう注意してください。これでは請求先の切り離しはできません。
- [保存] をクリックします。
✅
SUCCESS
✅ 完成:2つの権限が設定されました。これで、Cloud Run関数のサービスアカウントに以下の2つの権限が付与されました:
- ✅ 請求先アカウント管理者(Billing Account Administrator)
- ✅ プロジェクトの請求費用管理者(Project Billing Manager)
この状態が、
最も安全で確実な「完成形」です。今後、どんなタイミングでも失敗することなく、確実に課金を止めてくれるようになります。「請求先アカウント管理者」のみでも一時的に成功することがありますが、その後の自動処理でエラーになるため、
最初から両方の権限を設定することが推奨されます。
⚠️
WARNING
⚠️ 注意:非常に強力な権限。この権限は非常に強力なので、この関数専用のサービスアカウントであることを必ず確認してください。誤って他のサービスアカウントに付与すると、セキュリティリスクになります。「お支払い元閲覧者」(Billing Account Viewer)や「お支払い元ユーザー」(Billing Account User)などと間違えないよう注意してください。これらでは請求先の切り離し処理は実行できません。
権限設定後の確認
権限設定後、Cloud Run関数のログを確認してください。テスト実行時に403 ForbiddenやPermission Deniedエラーが出ていなければ、権限設定は成功しています。
テスト方法:
- Cloud Runの画面で、作成した関数
stop-billing-function を開きます。
- 上部のタブから 「テスト」(Test)ボタンをクリックします。
- 「オブザーバビリティ」タブを選択し、「ログ」(Logs)を開きます(テスト実行後のログを確認するため)。
- 再度「テスト」タブに戻り、「イベント JSON」の入力欄に、以下のテスト用データを貼り付けます。
- 「テストを実行」(または「送信」)ボタンをクリックします。
正しいテスト用 JSON データ:
{
"message": {
"data": "eyJjb3N0QW1vdW50IjogMTAwLCAiYnVkZ2V0QW1vdW50IjogNTB9"
}
}
※
data の中身は「コスト100、予算50」という情報を
Base64エンコードしたものです。デコードすると
{"costAmount": 100, "budgetAmount": 50} になります。
動作確認とテスト
関数が正しく動作するか、テストで確認しましょう。Cloud Run関数のテスト方法は2つあります:
コンソールでのテストと
Cloud Shellでのcurlコマンドです。
テスト実行後、ログに以下のようなメッセージが表示されれば成功です:
【状況確認】現在のコスト: 100, 予算額: 50
コストが予算を超過しました。停止処理を開始します...
実行:請求先アカウントの紐付けを解除しています...
成功:予算 100円にて請求を無効化しました。
もしエラーが発生した場合は、以下の点を確認してください:
- プロジェクトIDが正しいか:コード内の
project_id が実際のプロジェクトIDと一致しているか確認してください。
- 権限設定が完了しているか:「請求先アカウント管理者」と「プロジェクトの請求費用管理者」の両方の権限が設定されているか確認してください。
- エントリポイントが正しいか:Cloud Run関数のエントリポイントが
stop_billing に設定されているか確認してください。
- APIが有効化されているか:Cloud Billing APIが有効化されているか確認してください。
課金が止まった後の「復活」のさせ方
課金が止まると、このCloud Run関数も含めて、請求先アカウントが必要な主要サービス(Cloud Run、Cloud Functions、Compute Engine、Cloud SQL、BigQueryなど)が動かなくなります。Always Free Tierの一部サービスは引き続き利用可能ですが、実用上よく使うサービスは請求先アカウントが必要なため、ほぼすべてのサービスが利用できなくなります。元に戻したくなった時のために、以下の手順をメモしておいてください。
手順:
- Google Cloudコンソールの [お支払い] > [アカウント管理] を開きます。
- 「請求先アカウントのないプロジェクト」にあなたのプロジェクト(
gen-lang-client-0302******* など)があるはずです。
- 右側の [︙](三点リーダー)をクリックし、[請求を変更] を選択します。
- 自分の請求先アカウントを選び直して [アカウントを設定] をクリックします。
- これで復活します。各サービスは自動では再起動しないため、必要に応じて手動で再起動してください。
注意すべき副作用とリスク
この仕組みを導入する前に、以下のリスクを必ず理解しておいてください。
停止するサービスと利用可能なサービス
請求先アカウントを切り離すと、以下の主要サービスが停止します:
停止するサービス:
- コンピューティングサービス:Cloud Run、Cloud Functions、Compute Engine(GCE)、App Engine、GKE(Google Kubernetes Engine)
- データベース:Cloud SQL、Cloud Spanner、Firestore(有料枠)、Bigtable、Memorystore
- ストレージ:Cloud Storage(有料枠を超過した場合)、Persistent Disk
- AI/機械学習:Vertex AI、AutoML、Translation API、Vision API、Speech-to-Text APIなどの有料API
- ネットワーク:Cloud Load Balancing、Cloud CDN、VPCネットワーク(有料機能)
- その他:BigQuery(有料枠)、Cloud Pub/Sub(有料枠)、Cloud Monitoring(有料機能)、Cloud Logging(有料枠)
これらのサービスが停止すると、Webサイトやアプリケーションがアクセス不可になり、データベースへの接続もできなくなります。
利用可能なサービス(Always Free Tier):
- Cloud Storage:月5GBのストレージ、月5,000回のクラスA操作、月50,000回のクラスB操作(米国、東京、大阪リージョンのStandardストレージクラスのみ)
- Firebase:一部のFirebaseサービス(Firebase Authentication、Firebase Hostingなど)の無料枠
ただし、Cloud Run、Cloud Functions(第2世代)、Compute Engine、Cloud SQL、BigQueryなど、実用上よく使う主要サービスは、無料枠であっても
請求先アカウントの設定が必須です。そのため、請求先アカウントを切り離すと、これらのサービスは利用できなくなります。
タイムラグ(重要)
予算を超えてもすぐにアラートが出るわけではなく、Google側の集計タイミング次第で数時間(場合によっては6時間以上)かかります。課金データはリアルタイムで反映されるわけではなく、Google側のバッチ処理によって定期的に集計されるため、そのタイミングまで予算アラートは発火しません。そのため、
1,000円設定でも実際には
1,100円〜1,200円程度課金されてから止まることがあります。予算設定は、実際に止めたい金額より
10〜20%低く設定することを強く推奨します。
データ消失のリスク
書き込み中に強制停止されるため、まれにデータベースのデータが破損する可能性があります。また、請求先アカウントを切り離すと、停止したサービスに保存されているデータへのアクセスができなくなります(データ自体は削除されませんが、請求先アカウントを再設定するまでアクセスできません)。
復旧が手動
翌月になっても自動では再開しません。手動で請求先を再設定し、各サービスを再起動する必要があります。
予算超過停止の実装を振り返る
予算超過時に自動的に請求を停止する仕組みは、
Pub/Sub、Cloud Run、予算アラートを連携させることで実現できます。これは
非常に強力で原始的な手段であり、プロジェクト全体の請求先を物理的に解除します。
重要な注意点
- タイムラグ:予算を超えてもすぐにアラートが出るわけではなく、Google側の集計タイミング次第で数時間(場合によっては6時間以上)かかります。実際に止めたい金額より10〜20%低く設定することを強く推奨します。
- 権限設定:「お支払い元管理者」(Billing Account Administrator)と「プロジェクトの請求費用管理者」(Project Billing Manager)の両方の権限が必要です。片方だけでは確実に動作しません。
- Pub/Subの無限ループ対策:Pub/Subは、関数がエラーで終了すると、メッセージを再送し続けます。改善版コードでは、処理前に既に請求先アカウントが解除されているかチェックし、既に解除されている場合は処理をスキップして正常終了するように実装しています。
- サービスの停止:請求先アカウントが必要な主要サービス(Cloud Run、Cloud Functions、Compute Engine、Cloud SQL、BigQueryなど)が即座に停止します。Always Free Tierの一部サービスは利用可能ですが、実用上はほぼすべてのサービスが利用できなくなります。
- 導入前の確認:必ずリスクを理解し、テスト環境で動作確認を行った上で、本番環境に適用してください。
実装のポイント
- 冪等性の確保:処理前に既に請求先アカウントが解除されているかチェックし、既に解除されている場合は処理をスキップして正常終了します。これにより、同じメッセージが複数回配信されても、安全に処理できます。
- エラーハンドリングの改善:エラーが発生した場合でも、関数は正常終了させるようにしています。これにより、Cloud Run関数が適切にACKを送信し、再配信を防ぎます。
- ACKの自動送信:Cloud Run関数でPub/Subトリガーを使用する場合、関数が正常に完了すると自動的にACKが送信されます。エラーが発生しても、例外をキャッチして正常終了させれば、ACKが送信され、再配信を防ぐことができます。
公式ドキュメントと参考リンク
予算管理に悩む開発者の助けになれば幸いです。設定の際は、必ずテスト環境で動作確認を行ってから本番環境に適用してください。試作や実験でクラウドサービスを使う際、予想外の課金に怯える日々から、この自動停止機能によってようやく解放されました。本番環境では慎重に運用する必要がありますが、個人開発者として、これほど心強い機能はありません。