先日公開したログ情報共有サービスLogCrowの中で、ちょっとしたデータ分析用のバッチ処理を走らせるためにCloud Runを使ってみようとした時の話です。
Cloud Runとは?
Cloud Runとは、任意のコンテナイメージをビルド・デプロイし、HTTPのリクエストや、Cloud PubSubをトリガーとしてコンテナに処理を実行させるサービスです。
中はKnativeベースで構成されています。マネージドKnativeサービスです。
サーバレスシステムの基盤になるサービスの1つです。似たようなサービスとしてCloud Functionsがありますが、Functionsはコンテナイメージをデプロイするのではなく、コードをデプロイして動かすものであり、サポートされている言語やバージョンに制約があります。
今回Cloud Runを利用するに至ったのも、元々はCloud FunctionsでGoのプログラムを動かそうとしたのですが、どうしても依存ライブラリがGo1.12以上のバージョンが必要で、Cloud FunctionsのGo1.11という制約に当てはまらなかったためです。
Cloud Runには無料枠が提供されていてCloud Runが稼働時に利用したリソース量に応じています。
CPUなら最初の 180,000 vCPU 秒は無料、メモリなら最初の 360,000 GB 秒は無料、リクエスト数は200 万リクエストまで無料、NWは北米内の下り(外向き)は、1GB まで無料となっているので、ちょっとお試しする分には絶対に無料枠超えることはないだろうと思っていました。
試した仕組み
Cloud FunctionsでCloud StorageにファイルがアップロードされたことをトリガーにPubSubにメッセージを送信。
PubSubのサブスクリプションにCloud Runのエンドポイントにメッセージを発行するように登録。
発生したこと
StorageにファイルアップロードしてCloud Runが実行されるところまでは問題なく実行されました。
試しに動かしていた際、一旦ここまで流れるところまで確認して詳細な実行結果まで見ていなかったのが問題でした。。
実行したCloud Runの実行結果が500(Internal ServerError)になっていました。
ファイルアップロードしなければ特に何も起こらないので問題ないと思って数日そのままで放置してました。すると、たまたま月末で、当月の課金額のレポートメールが来てびっくり。。
ちょっとしか使ってないはずのCloud Runの課金額があっという間に15,000円程に膨れ上がってました。。
よく見るとCloud Runによるリソースの消費量がすごいことに。。
すぐにCloud Runの実行ログを見ると、多量のリクエストがやってきて、ひたすらに実行エラーを返し続けている状態に。
注意すべきポイント
原因はCloud PubSubがCloud Runからの500エラーのAckを受け取ってしまったために正常実行するまで何度も何度もリクエストを再送し続けていたためでした。。
PubSubのサブスクリプションをデフォルト設定で登録すると、以下のように処理が正常完了しなかった場合に再送するようになっています。
- レスポンスコードが異常である(200、201、202、204、102以外のレスポンスコードが返る)
- 応答(Ack)時間が10秒以内に返ってこない
さらに、正常処理出来なかったメッセージについては7日間は消えずに再送し続けます。
このような仕様のため、リクエストの嵐となったわけです。。
成功するまで実行してくれるのは便利な反面気をつけないと痛い目を見るので注意です。
万が一Cloud Runの処理に失敗したとしても再実行を最小限にとどめたい場合には、保持期間を調整することができます。
最短10分~最長7日の範囲で指定可能です。
gcloudのコマンドラインでsubscription登録する場合には以下オプションで指定します。
- --message-retention-duration
Cloud Runの処理が時間がかかるような処理の場合もデフォルトの10秒以内のAckだと時間オーバーする可能性があるので、処理時間の見込みに応じて、調整します。
最短10秒~最長600秒の範囲で指定可能です。
- --ack-deadline
その他のオプションは以下にあります。
なお、もし連続したリクエストが発生してしまって、PubSubのpushを止めたい場合には登録したサブスクリプションを削除する必要があります。
さいごに
利用する際にはドキュメントをしっかり理解してから使わないとダメですね。
今回無料枠を超える量の処理が走ってしまいましたが、Googleさんから最初に付与していただいた$300のクレジットの範囲で収まる被害で済みました。これには感謝です。