後ろを向いて後退します

これって前に進んでいることになりませんか?

TerraformでAWS Lambdaを管理したいときの個人的な一つの答え

Terraform Advent Calendar 2019

本記事は Terraform Advent Calendar 2019 8日目の記事です。

qiita.com

プロローグ

普段Terraformを書いていると、インフラのコンポーネントとしてのLambdaもTerraformの世界で管理したい気持ちになります。とはいえTerraformで全てを管理しようとするとデプロイパッケージの作成とかライブラリのインストールとか結構辛いのでこの1年間色々試行錯誤をしてきました。

apexという良い感じのTerraformと調和したLambda用デプロイツールもありましたが、先日No longer maintainedの文字がREADME上に確認されたためプロダクション投入もできず困ってしまいました。

github.com

Chapter 1 : AWS Lambda Layerを利用した開発

dev.classmethod.jp

AWS Lambda Layerは、re:Invent 2018で発表されたAWS Lambdaのサービスの一つです。仕組みとか特徴の話は詳しくはクラスメソッドさんの記事に書いてありますが、端的に言うとオレオレパッケージを作って複数のLambda functionで使い回せるようになるというやつです。

必要なライブラリを含めてコードをLayerとしてデプロイすれば、サポートされているランタイムのLambda functionからは自由にインポートして使うことができます。このおかげで、vendoringをしていない場合のデプロイパッケージを作るときに必要だったライブラリインストールの作業や、共通処理とか似たような処理を綺麗にまとめるときの苦労から解放されるようになりました。

便利なのは、Layerに同梱されているライブラリなら自作・サードパーティ製を問わずインポートできる点です。本来デプロイパッケージごとに個別に同梱されている必要のあるライブラリ類を中央集権的に管理できるのは大きなメリットです。

re:Inventでサービスが発表されてから半年もしないうちにTerraformのAWS ProviderでもLambda Layerがサポートされているので、(比較的)ストレスフリーなLambda functionの開発をTerraformで行えます。

1: stress-free lambda development with lambda layer

Chapter 2 : SNS + SQS + Lambdaで他のサービスと安全に繋ぐパターン

約1年半くらい前にAWS Lambda functionがイベントソースとしてSQSをサポートするようになりました。SQSにメッセージがエンキューされると、イベンドドリブンでLambda functionが発火して正常終了すると自動的にメッセージがデキューされるようになっています。

何点か注意事項があって、

  • SQSのvisibility timeoutはトリガーするLambda functionのtimeoutよりも長くなければいけない。
  • Lambda functionを実行するIAMロールは対象のSQSキューのRead/Update/Delete権限が必要。
  • Terraformでやる場合は aws_lambda_events_source_mapping を作成する必要がある。

などの点に注意する必要があります。

Lambdaと一緒にSQSを利用することで、リトライ処理が簡単にできるようになったり一度のLambda functionの起動で複数のメッセージを捌けるなどのメリットがありますが、如何せん取り違えや構築の手間がネックになりやすいです。というわけでSNSを含めたLambda function周りのコンポーネントをサッと構築できるようにTerraformのコードを書いてみました。

2: sns-sqs-lambda flow for connecting various services

Chapter 3 : Dead Letter Queueのハンドリング

SQSキューでDead Letter Queueをハンドリングするためのキューを追加するとき、TerraformではRedrivePolicyを追記して構築すると正常に処理されなかったメッセージをDead Letter Queueとして指定されたSQSキューに送ることができます。

以下のサンプルでは、動作検証と復旧作業後の再実行がしやすいようにDead Letter QueueをハンドリングするためのLambda functionを設定して、 event オブジェクトをS3バケットにそのまま書き出すような処理をしています。

3: DeadLetterQueue handler

Chapter 4 : CloudWatchダッシュボードの自動生成

最近気づいたんですが、CloudWatchダッシュボードって定義情報をJSONで保持しているらしいです。

Terraformも aws_cloudwatch_dashboardJSONを受け取ってダッシュボードを生成するので、 template_file とforeachを組み合わせてARNのリストを渡すだけで良い感じのダッシュボードを生成できるようにするとモニタリングダッシュボードも楽に作れて良さそうです。

www.terraform.io

少し冗長なコードです。

github.com

4: CloudWatch Dashboard

エピローグ

1年間悩み続けてきたので多分この先もstate管理とかライブラリのインストール問題とか色々悩み続けることになるとは思いますが、今の所この方法で良い感じにLambda開発を進められているので紹介しました。

言うまでもないですが他にもLambdaのデプロイ管理ツールとかたくさんあると思うので、開発フローとか運用にうまく載せられるものを使っていきたいですね。