エンジニアのはしがき

プログラミングの日々の知見を書き連ねているブログです

AWS Lambdaを運用しての所感

f:id:tansantktk:20201120002649p:plain

Lambdaを本番環境で約2年程運用してきましたが、機能追加・修正や保守のことを考えると最初からこうしておけばよかったなーと後悔することもありました。 現在までの知見で個人的に考慮した方がいいこと、やっておいた方がいいことを書き連ねてみます!

CloudWatchにログ出力させる

これは保守する上で必須だと思います。

開発者がソースコードに標準出力を明示的に記述していなくても、Lambdaが呼び出された時と処理完了時にはCloudWatchにログが出ますので、ログ出力を有効化するだけでもしておくべきです。

f:id:tansantktk:20210529063347p:plain

なお、CloudWatch Logsへの書き込み権限を持ったロールを適用していないと、ログ出力されません。

脳死で新規にLambdaを作成してるとたまに見落とす時があるので要注意です。

複雑な処理をさせるなら標準出力を明示的に記述しておく

エンジンがNode.jsならconsole.log()、.Net CoreならConcole.WriteLine()Pythonならprint()にあたります。

それぞれ微妙にCloudWatch上での出力フォーマットが異なるようですが、引数指定した文字列を出力するという点は同じです。

大量のデータを加工してデータベースを操作するような処理をLambdaで実行させた際に、各データがどのような判定結果で処理されたのかが把握しきれなかったことがあり、運用上苦労しました。

その為、ビジネスロジックの中に明示的に標準出力を仕込むことで、各データの処理フローが開発者に明確に伝わるようにコーディングを心がけています。

ただやり過ぎるとコードの見通しが悪くなりますので、適切な箇所を見極めて出力させる必要もあります。難しいところです。

ファイル操作できるディレクトリは/tmpのみ

Lambdaで一時的にファイル生成したり操作をしたい時には、/tmp内で実行する必要があり、それ以外のディレクトリで実施しようとすると例外となります。

実際の処理としては、S3へファイルを転送する前段階で一時的にzipを生成したりするケース等があると思いますが、この制限を考慮したコーディングが必要です。

タイムアウト設定は最大15分まで

以前よりはだいぶ長くなったそうですが、あまりにも長時間にわたるバッチ処理のような処理をさせることには向いていません。

再帰的にLambda関数を実行させて実質的にタイムアウトを伸ばすことは可能ですが、開発者の意図しない永久ループが発生してしまい、Lambdaの利用料金がとんでもないことになる恐れがありますので、相応の理由が無い限りはおすすめしません。

AWS公式でも「しないでください」と警告されています。

Lambda 関数内で、任意の条件が満たされるまでその関数自身を自動的に呼び出すような再帰的なコードを使用しないでください。これを行うと意図しないボリュームで関数が呼び出され、料金が急増する可能性があります。誤ってこのようなコードを使用した場合は、すぐに関数の予約された同時実行数を 0 に設定して、コードを更新している間のすべての関数の呼び出しをスロットリングします。

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/best-practices.html

ただ、白状すると私は過去にそのような実装をしたことがあります…😂

諸々の理由でEC2やFargateが使えなかった為の苦肉の策でした。お察しください…。

頻繁にバージョンアップがあるならバージョニングしておく

エイリアス」と「バージョン」を作成し、外部からLambdaを呼び出す際にはエイリアスのARN経由で特定のバージョンを呼び出すような構成にしておくと、バージョン切替時にエイリアスとバージョンの紐付けを変更するだけで済むようになるので管理しやすくなります。

例えばうっかり深刻なバグの混入したバージョンをデプロイしてしまった場合、前のバージョンへ戻すことが求められることがあるかと思いますが、その際にはエイリアスが前バージョンを参照するように変更すればいいので対応が楽です。

#