10日間 で AWS Lambda 関数を 28億回 実行した話
この記事は 本番環境でやらかしちゃった人 Advent Calendar 2019 25 日目の記事です。
はじめに
こんにちは、エンジニアの内山です。
最近は AWS を使ったサーバレス開発に従事しています。
今回は、サーバレス開発時にやらかしてしまったお話です。
どんなことが起こった?
プログラムのバグが原因で、AWS Lambda 上で再起呼び出しの無限ループが起こりました。さらに発生時にはそのことに気づけませんでした。
発生時から 10 日後の月末に、請求額が想定よりも異常に高いという報告を受け、その時点で初めて無限ループが起こっていることが発覚しました。
10 日間 で、AWS Lambda 関数が 28億回__ほど実行されており、付随するサービス(X-Ray/CloudWatch Logsなど)の料金も加わって、__27万円 ほどの料金が発生してしまいました。
経緯
ある Lambda 関数から別の Lambda 関数を非同期で実行する処理を実装していました。実際とは少し違いますが、以下のような動作を想定していました。
しかし、バグを入れ込んでしまい、自分自身を非同期で呼び出す形にしてしまいました。
この結果、無限に自分自身を呼び出す Lambda が発生し、気づかずにそのまま放置してしまいました。
要因
「別 Lambda を非同期で実行する関数」と「呼び出された Lambda上 で実行する関数」のそれぞれの名前が同じで、パッケージ名が1文字違いとなっており、見分けが非常に困難な状態でした。具体的には以下のような名前でした。
invoker.PutFileToS3
・・・ 別 Lambda 関数を非同期で実行する関数の名前invoked.PutFileToS3
・・・ 呼び出された Lambda 側で実行する関数の名前
お分かりいただけたでしょうか。
呼び出される側の Lambda で invoker.PutFileToS3
を呼び出すように実装してしまい、結果自分自身を呼び出す形にしてしまいました。
本当に単純なミスです。
再発防止策
別 Lambda を呼び出す関数の名前をわかりやすくする、または Step Functions を使う
無限ループが発生しないようにするための防止策です。
今回は関数名が紛らわしいことが要因でしたので、__それぞれの関数の名前を見分けやすいように変更しました__。
また、__複数の Lambda を実行する処理は、AWS Step Functions で実装するほうが良いです__。Step Functions で実装すると、複数の Lambda の実行順序が可視化されて把握しやすくなります。またループや条件分岐など細やか制御もできるのも利点です。
AWS 請求アラームを設定する
気をつけていても、無限ループなどの思わぬリソースの使用が発生してしまう場合もあります。AWS には、請求アラームを設定できます。
各アカウントで想定する請求額の上限を決めておき、それを設定しておいたほうが良いです。
監視を行う
これについては、本番環境では当たり前の話ですね。
今回は、本投入される前の機能であったため、監視が行われていませんでした。結果、何が起こっているのかを把握することができず、放置してしまいました。
__サーバレス開発においては、開発用のAWS環境でも監視することを検討したほうが良いです__。開発環境であっても、実際に何が起こっているのかを把握することは大事になってきます。
おわりに
今回のことが発覚した際に、社内では再発防止策の検討が行われ、即座に実施されました。会社に損害が出てしまっている状態であるのに、良い学びの機会として捉え、今後の開発に生かしていこうという前向きな雰囲気でした。このような環境で仕事ができていることに感謝しております。
今回のやらかしを糧に、今後とも精進していきたいです。
MMMは、会社としてもAWS Lambdaに力を入れています。ぜひ以下のページもご覧ください。