ちょっと待って！そのGCP、本当に無料枠？

この記事は [ここのえ Advent Calendar 2023](https://qiita.com/advent-calendar/2023/99no_exit) Day 11の記事です。

# Intro

最近GCPを使い始めたのですが、無料期間中に心当たりのないクレジットの減少があり、疑問に思っていました。

無料トライアルやAlways Freeに関する情報は 以下のページで確認していたのですが、

https://cloud.google.com/free?hl=ja

実はよくよく見てみると以下のような詳細なドキュメントがあり、一部サービスではリージョン等の制限があることに気づきました。

https://cloud.google.com/free/docs/free-cloud-features?hl=ja

ただGoogleくんの優しいところとして、無料期間でクレジットを配布してくれているのでそういった罠にも気づきやすくなっています。ありがとう。


という事で、実際に自分が踏み抜いたパターンについて紹介していきます。

# Cloud Functionsを`gcloud deploy`したらクレジットが減る？

定時実行するNode.jsのプログラムを作っていたのですが、折角なのでGCPを使って回してみたいと考えます。
今回の登場人物はこいつらです。

- Cloud Functions
    - Nodeのプログラムを回すメインの個所
- Cloud Scheduler
    - 毎時10:00にジョブをFunctionsに送る
- Cloud Build
    - ローカルからデプロイした際に、Functionsの構築のために走る
- Identity and Access Management (IAM)
    - FunctionsとSchedulerのロール設定用

一つ一つ順番に見ていきます。

## 容疑者1: Cloud Functions

今回の主役である、Cloud Functionsくんです。色々走りそうですが、Always Freeの対象を見るとバチクソに太っ腹なサービスになっています。

> - 200 万回の呼び出し（1 か月あたり、バックグラウンド呼び出しと HTTP 呼び出しを含む）
> - 400,000 GB 秒、200,000 GHz 秒のコンピューティング時間
> - 5 GB の下り（外向き）ネットワーク（1 か月あたり）

Nodeのプログラムは毎日10:00に1インスタンス走るだけで、処理時間も30秒程度でたかが知れています。送受信するデータもJSONファイルだけなので、下りネットワークも問題にならなそうです。
早々に容疑者から外れました。

## 容疑者2: Cloud Scheduler

現在の構成では、毎時10:00にCloud Functionを呼び出しています。さて、Schedulerの無料枠はどうなっているでしょうか？

> - 無料ジョブ/月:	3

この無料ジョブはプロジェクト毎ではなく、アカウント単位でチェックされるものになります。ですが使い始めたばかりなので、他のプロジェクトでCloud Schedulerをセットしたことはありません。

どうもこれも違いそうです。

## 容疑者3: Cloud Build

これはかなり怪しいです。Cloud Buildはローカルからデプロイした際に自動で走るのですが、特に何も設定したわけではないので、何か悪さしてそうな予感があります。見てみましょう。

> - 120 ビルド分数（1 日あたり）

ちょっとはっきりと分かりません。何となく大丈夫そうな気はしますが、詳細を調べてみます。
特に設定していない場合は、クイックスタートに指定されている `e2-standard-2` が走るようです[^1]。また「ビルド分」という単位についても調べてみます。

> ビルド分は、Cloud Build が開始したビルドが実行されている時間を分単位で表します。1 分に満たない端数は、実際に使用された秒数で課金されます。ネットワークの上り（内向き）と下り（外向き）の料金は、ビルド分の料金に含まれます。
>
> ビルドがキューに入っている時間はビルド分に含まれません。料金は、ビルドを開始した Google Cloud Console プロジェクトの請求先アカウントに課金されます。
>
> - e2-standard-2
>     - $0.006/ビルド分。毎月最初の 2,500 ビルド分は無料です

今回はローカルで `Parcel` を回してbundleを作ってあるので、クラウド上ではデプロイしたものを展開し、Cloud Functionsが読み込むだけの構成になっています。当然そんなにビルドに時間がかからないので、Cloud Buildも犯人ではなさそうです。

## 容疑者4: IAM

そういえば何も考えずに使っていたIAMですが、料金は大丈夫でしょうか？

> Google Cloud のお客様は、IAM を追加料金なしでご利用いただけます。請求は他の Google Cloud サービスの利用分に対してのみ行われます。

なんかごめん。

## 一体誰がクレジットを？

ここまで見てきた限り、今回出てきた登場人物はどれも無料枠の中で収まっているように見えます。
こうして捜査は行き詰ってしまいました。2時間ドラマに例えるなら中盤ぐらいの、最初の容疑者にアリバイがあるのが分かるタイミングです。う～ん参った。

こうなったら手がかりを探すためにひたすら各サービスの設定を細かく見ていくしかありません。

そしてCloud Functionの設定を舐めまわすように見ていくと、こんなものを発見します……

![cf-storage.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617021/b371b845-9d70-3de0-4714-e65ba0514338.png)

**ん？ Cloud Storage?**

## そして解決へ…

どうやら `gcloud deploy` コマンドを使ってローカルからデプロイを行うと、Cloud Storageにzipとしてアップロードされるようです。

しかし、[**無料枠プロダクト**](https://cloud.google.com/free?hl=ja) のページにこうも書いてあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617021/b2d007d9-d387-aa06-19ac-dc45ce2531d4.png)

バンドル後の`index.js`のサイズは `4.79 KB` なので、単純計算では `1,094,546` 回はデプロイできそうです。右下の青矢印が気になります。詳細を見てみましょう……

> - 5 GB 月の Regional Storage（米国リージョンのみ）
> - 5,000 回のクラス A オペレーション（1 か月あたり）
> - 50,000 回のクラス B オペレーション（1 か月あたり）
> - 1 GB の北米から全リージョン宛ての下りネットワーク（1 か月あたり、中国とオーストラリアを除く）
>
> 無料枠を利用できるのは us-east1、us-west1、us-central1 リージョンのみです。使用量の計算は、これらのリージョンすべての合計が集計されます。

**Cloud Storage、お前だったのか……**

何を隠そう、近いからという安直な理由で `asia-northeast1` を使っていたのです。

`gcloud deploy` するとデプロイされたものが `Cloud Storage` に入るのですが、当然リージョンは `Cloud Functions` と同じリージョンに配置されます。
そこで無料枠ではない **TOKYO** に配置されてしまい、Cloud Storageに料金がかかった、という算段になります。

# もっと簡単に確認できます

実はこんな面倒な手順を踏まなくても、簡単に原因を探ることができます。

GCPのコンソールに入ると表示される welcome ページで、**プロダクトの費用を確認する** というボタンがあり、ここから確認することで何にどれだけのコストがかかっているのか、一目でチェックすることが可能です。

実はここまでの話は半分フィクションで、Cloud Storageが悪いこと自体はここを見て分かっていたのですが、何がCloud Storageを使っているのか全く見当がつかずに右往左往した…　という感じです。

# 終わりに

クラウドサービスはは複数のサービスが密接に結びついて動作しているので、全体の流れを追おうとすると結構大変だな……と思わされる出来事でした。

昔は自宅にラックサーバがあるタイプの誤家庭に住んでいたので、あんまりこれまでクラウドサービスは触ってこなかったのですが、改めてもっと色々触って試してみなきゃな…と考えさせられました。

そんな中でもGCPは無料トライアルでクレジットがある程度配布されているので、90日間使い放題でガンガンいろんなサービスを試して、その中でこういった気づきができるのは本当にありがたいな…と思います。今後も色々試してみたいです。

[^1]:https://cloud.google.com/build/pricing?hl=ja