システム事業部の阿部です。
タイトルにもありますが今回はちょっと恐ろしかった話です。
Lambdaの金額が800$を超えた
ある日いつも通り仕事をしているとSlackの指定のチャンネルに、
【XX/YY~XX/YY(1週間)の請求額は、948.42 USDです】と通知が入りました。
(毎月400$ぐらいの利用料なので、1週間単位での報告は100$ぐらいのはずが、桁が1つ違う!!!)
通知機能に不具合でもあったのかなーと、恐る恐るAWSコンソールを開きました。
すると、Lambdaの実行回数が【46,949,513.570 seconds】
無料枠が【400,000.000 seconds】なので桁が2つも違う。
原因はLambda関数の再起呼び出し
この時作っていた機能は↓のようなもので、
- S3にファイルをアップロードするとLambda関数を起動
- 別システムにAPIでファイルアップロードを通知する
- アップロードされたファイルのキャッシュを無効にする
(同じファイルが更新されることもあるため、常に最新が表示されるように)
勘のいい皆様ならお気づきだと思いますが。
③のキャッシュ無効処理でアップロードされたファイルのメタ情報を更新するため、S3としてはファイルがアップロードされたと認識するため、①~③が再帰的に呼び出されLambdaの処理がえぐいことになっていました。
これでも間一髪
Slackで請求情報を通知する機能を作ったのが3ヶ月前。
これがなければ大変なことになっていました。
通知は1週間単位でしたがこの機能をリリースしてから実際に通知がくるまでの期間は【3日間】でした。
気づかず放置していたら月額【10,000$】。
通知を作ってくれたM田君に心底感謝しました。
トリガーイベントは適当に設定しない
S3をトリガーにLabmdaを起動する場合、↓のような設定が可能です。
元々は【ALL object create evens】を設定しておりましたが、
- 【Post】【Put】【CompileteMultipartUpload】に限定すること
- ファイルのメタ情報の更新の際にはCopyメソッドを使うことでCopyイベントとする
ことで再起呼び出しを防ぐことができました。
ただ、不安が残ったので、
if('ObjectCreated:Put' == event['Records'][0]['eventName'] ||
'ObjectCreated:CompileteMultipartUpload' == event['Records'][0]['eventName']||
'ObjectCreated:Post' == event['Records'][0]['eventName']) { //メタ情報の更新処理 }
として、Labmda側にも念のため除外処理を入れてみました。
AWSを使う際に気を付けたいこと
色々な記事でも皆様書いてますが、新しいアーキテクトを試したりしていく中で、【想定外】はつきものです。
すぐに気づける機構を準備しておくこと、これが非常に重要だったなと痛感した出来事でした。
- AWSの請求機能での通知を有効しておく
- 簡単な通知システムを独自で作っておく
方法はなんでもいいと思いますが、後になってやっておいてよかったと実感できる機会が必ず来ると思います。
こんな失敗がこの世からなくなりますように。