Google Cloud勉強用アカウントを開設してコスト自動アクションを設定する

## 前提
- Googleアカウントを持っていること
## やりたいこと
- GCPのアカウントを作る
- 一定以上コストが発生したときには課金を停止する
    - 不慣れなので脆弱な設定をしてしまって仮想サーバ乗っ取られてとかのリスクを避けるため
    - ただ無料トライアルは勝手に有料アカウントに移行はされないらしい

## アカウント開設
- https://cloud.google.com/?hl=ja などから登録する
- 同意して続行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/4e74bebe-8ede-adc2-2c13-01396d3ca4ae.png)
- お支払いプロファイルを作成する
        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/503845e8-9d78-b09a-0a12-ee597ff4f092.png)
    - 「新しいお支払いプロファイルを作成する」から、個人情報を記入
- 今回無料トライアルなので、もろもろ回答
    - 必ずしも必要なのかは不明
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/e170e54e-4f24-d01d-9990-cd12d86c237e.png)

## コスト管理の自動レスポンス
- 下記を参考
    - https://cloud.google.com/billing/docs/how-to/notify?hl=ja
### 予算通知を設定する
- 下記を参考
    - https://cloud.google.com/billing/docs/how-to/budgets-programmatic-notifications?hl=ja
- My First Projectが作成されているので、そこに移動して、「Pub/Sub」のコンソールに移動

- 「トピックを作成」
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/476cbeb4-d8ce-5379-4576-33d584f993f9.png)
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/027bbd12-2611-015b-bb13-ac0bb0eaed00.png)

- 「予算とアラート」( https://console.cloud.google.com/billing/budgets )を開く
- 「予算を作成」
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/c6cec5de-cb32-3fac-ee95-133c2b65bf96.png)
- どのくらいのリソースでどのくらいかかるのかも掴みたいので、「クレジット」はチェックを外した
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/420ccd61-900d-c853-d1b4-aeda8c03afb9.png)
- その後は流れに沿って予算を作成する。最後の「Pub/Sub トピックをこの予算に接続する」で、先ほど作ったPub/Subトピックを選択する
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/049352ec-9ef3-64c8-5a0e-e8b3f68467e2.png)
- Clouf Billing APIを有効化する
    - https://console.cloud.google.com/apis/api/cloudbilling.googleapis.com?hl=ja&_ga=2.225304540.731644427.1720792757-745651918.1713018633
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/f0233d48-722e-a788-2e02-6cb4e6ce64ed.png)

### 通知をリッスンする
- Cloud Functionを作成する
    - (Pub/SubがEventBridgeでCloudFunctionsがLambdaみたいなことなのかな...)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/aa2f469a-0460-5e08-37d8-a0c8c8c28182.png)
- もろもろ設定していったのですが
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/c8c964f2-08a1-a5b3-0ac7-4dc10bdeb414.png)
- 怒られました
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/509decd1-5737-3a4e-8ab3-aaa98dff45a9.png)
    - service-xxxxxxxxxx@gcp-...は、Pub/Sub用の内部的なサービスアカウントとのこと
    - roles/iam.serviceAccountTokenCreatorはアクセストークンを作成する権限
    - CloudFunctionがメッセージを受信するための権限を、Pub/Subが発行したアクセストークンを借用して得る？
- ここで私はしていなかったが、たぶんロールを新規作成したほうがいい
- https://cloud.google.com/billing/docs/how-to/notify?hl=ja#cap_disable_billing_to_stop_usage に記載の通りペタペタ貼り付けてデプロイする
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/780c469b-a5a0-fd00-28b3-7e6242a748c8.png)
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/0782ef62-76bf-8565-5e70-7d25c0436362.png)
    - 結構デプロイに時間かかるんだな
    - Lambdaよりは長いな
- この関数のロールがデフォルトでは課金停止ができないので権限を追加する
- 関数のページの「詳細」タブにサービスアカウントがあるので、アカウント名をチェック
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/c43b3f26-2e8a-fc22-05c6-109b4ec7357c.png)
- ここへアクセス https://console.cloud.google.com/billing?hl=ja&_ga=2.233283544.731644427.1720792757-745651918.1713018633
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/4df94461-a042-0803-9bf4-67f474dd67f0.png)
- このように設定
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/041d410b-8a53-5f7c-a0c0-6fb0794ebd48.png)

## テスト
- Pub/Subの下のほうからテストができるので、試してみる
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/dead39ee-84b9-673d-4cfd-9ee9ca8f0f02.png)
- https://cloud.google.com/billing/docs/how-to/notify?hl=ja#test-your-cloud-function に記載のようにメッセージ本文を設定し、「公開」
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/dea5bcfb-a1f3-9650-6eaa-88132672b29a.png)
- 試してみたところ、プロジェクト名が定義されておらずエラーだったっぽいので、環境変数を設定
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/34cc36a3-58ea-2b78-231b-25da539c4021.png)
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/38f90f7b-73b2-d373-58b1-286634120c3e.png)

- 成功した
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/208ebb7d-5405-66be-db8a-843d38f2d5cd.png)
- 請求先アカウントとの紐づけが消えていることがわかる
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/f834ef99-b266-ca73-358f-cd20efb68e80.png)
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759447/3b720827-e8aa-641e-3cfe-82f982dbb1d0.png)


    - ちなみにこの間、2hくらい失敗し続け、ロールをいじくりまわしていたので、何かしら追加でロールをアタッチしてしまっている可能性はある
    - 結局、Billing APIを有効化できていなかった
    - コピペしたままだとログにメッセージしか吐かれないので、エラーが起きた時には下記のようにレスポンスメッセージを出すようにするとよい
    ```python:before
        try:
            res = projects.updateBillingInfo(name=project_name, body=body).execute()
            print(f"Billing disabled: {json.dumps(res)}")
        except Exception:
            print("Failed to disable billing, possibly check permissions")
    ```
    ```python:after
        try:
            res = projects.updateBillingInfo(name=project_name, body=body).execute()
            print(f"Billing disabled: {json.dumps(res)}")
        except Exception:
            print("Failed to disable billing, possibly check permissions" + str(res))
    ```

## 感想
- IAMまわりがAWSと結構違う感じがして難しい...
- AWSだとAPIは最初から有効化されている(サービスが有効化されていないとなにもできないにしても)けど、GCPだとAPIを有効化しないと叩けないものが多い