LambdaFASTALERT開発チームバックエンドエンジニアの鈴木(泰)です。Lambdaの構成管理のためにTerraformを導入してみたというお話です。Terraformの話に入る前に、FASTALERTチーム、workerレポジトリ、今回Terraformの導入に至った動機について、少しだけお話しさせてください。リスク情報をAIが自動収集し、収集された情報をお客様にとって使いやすい形で提供するBtoB向けのSaaSです。成長過程のサービスであるため、顧客からのフィードバックを含め、寄せられる要望へ迅速に対応しなければなりません。上記のような事情から、FASTALERTのバックグラウンド処理の内容は規模が小さく多岐に渡り(広く浅い)、「開発速度」が重要となってきます。様々なバックグラウンド処理データやシステムの監視とメトリクス算出、データベース中の防災情報の管理、防災情報へのメタ情報、社内システム連携トリガーも様々。API、運用者が不定期的に手動で実行する、等。開発速度を重要視するチームの慣習ほぼ全てのコンポネントがCD化されている、本番稼働するシステムの全ソースコードはGitで管理されている、Gitのタグを付与するだけのお手軽リリース、IaCの導入、スクラム開発workerレポジトリFASTALERTチームにはworkerという名前のレポジトリがあります。このレポジトリは、様々なバックグラウンド処理を小さい工数で提供し、かつ、ソースコード管理システムでソースコードを管理し、CI/CDを完備することを目的とし、Lambda製の様々なバックグラウンド処理を一元的に管理しており、Lambda関数を簡単に追加できるようにしています。具体的には(1)ソースコードを書く(2)デプロイ用のコードを追加(3)Gitのタグを付与する。これだけで新しいLambda関数をリリース可能です。本記事執筆時においては約50個のLambda関数が管理されており、ソースコードの追加・更新が頻繁に行なわれています。apexのメンテナンス停止workerレポジトリでは、Lambda関数の構成管理ツールとしてこれまではapexを利用していました。apexが2019年にメンテナンスを停止しました。今回のTerraform導入は、このapexのEOLを受けてのことです。Terraformを採用することとなった決め手となったのは、以下の点です。AWS上の実際のリソース設定とTerraformのstateを柔軟に解消できる。FASTALERT開発チームのメンバーはTerraformを使い慣れている。AWS上の実際のリソース設定とTerraformのstateを柔軟に解消できる過去の経験上、SAMはリソース定義(yamlファイル)と実際のインフラ設定の間に生じた差分の解決がとても面倒臭い、という印象があります(昔、SAMを利用していたとき、差分が生じて、CloudFormationが動かなくなり、CloudFormationに紐づくリソースを丸ごと削除して新しく作り直す、というような危険な運用をしたことが苦い経験として記憶に焼き付いていたりします)。IaCを進める過程において、構成管理用のソースコードと実際のインフラ設定の間に差分が生まれるということはよくあります。FASTALERTチームのように開発速度が求められる現場においては、そのような差分が発生する可能性はとても高いです。Terraformは、CloudFormationを使用しておらず、かつ、実際のインフラ設定との差分を解消するためのimportコマンドがあるため、差分の発生に対して柔軟に対処することができます。FASTALERT開発チームのメンバーはTerraformを使い慣れているTerraformを採用したもう1つの理由は、FASTALERT開発チームメンバーがTerraformに慣れているという点です。最近FASTALERTチームでは、構成管理をTerraform化することを推奨しており、Terraformを使えるメンバーが増えつつあります。Lambdaの構成管理のためにTerraformを導入(詳細)それでは、我々がどのようにしてTerraform化を実現したかについてお伝えいたします。本記事で紹介している詳細実装は、Python3.8、Terraform1.1.7で動作することを前提としています。コードサンプルはこちらにあります。ディレクトリ構造workerレポジトリは以下のようなディレクトリ構造です。Pipfile.lockは依存ライブラリを管理します。terraform/ディレクトリについての詳細です。build-pkg.shはLambda用のzipを作るためのスクリプトです(後述)。functionsディレクトリ配下にはLambda関数のエントリーポイント群があります。Terraformディレクトリ配下にはTerraformのコードがあります。共通するリソース(IAMとか)はmain.tfに書いています。基本的にはLambda関数1つにつき、1つのファイルです。ディレクトリ配下のpythonのソースコードと同じ。terraform/lambda_process_checker.tfterraform/lambda_export_api_log.tf...以下省略...ファイルの中身functions/process_checker/main.pyの中には、Lambdaのエントリーポイントがあります。...以下省略...terraform/main.tfの中には、共通するリソース定義があります。...以下省略...terraform/lambda_process_checker.tfの中には、Lambda関数リソースの定義があります。dists.zipは、build-pkg.sh(後述)が生成するLambda関数のパッケージです。"lambda_process_checker.handler"}Lambdaのデプロイ方法Lambda関数のパッケージを作る。applyコマンドを実行する。Lambda関数のパッケージを作るLambda関数用のzipファイルを作ります。全てのLambda関数のエントリーポイント、その実行に必要となる依存ライブラリを全て1つのzipファイルの中に格納します。関数をデプロイするworkerレポジトリ上のbuild-pkg.shがzipファイルを作ります。build-pkg.shが正常終了するとdists.zipというファイルが生成されます。${OUT_DIR}/注意点この実装方法ですと、Lambda関数の数が増えていくのに伴い、dists.zipファイルのサイズが大きくなることが懸念されます。dists.zipファイルのサイズが大きくなることを回避するための実装方針として、サイズが大きくなりがちな変数の定義(長い文字列や配列、連想配列の定数値)はDynamoDBやS3等の永続化層へ配置するようにしています。Pythonのソースコードが増えるだけであれば、ファイルのサイズが大きくなることは回避できます。(それでも、Pythonの依存パッケージのサイズが大きくなってしまう懸念点は依然として残されています。Layers等の利用を検討すべきかもしれません。applyコマンドを実行するdists.zipが生成された後、以下のコマンドを実行し、Lambda関数をデプロイします。新しいLambda関数を作成する場合、Pythonのソースコード、Terraformの定義ファイルを追加するだけです。new_func1という新しいLambdaを追加する場合、以下の2つを追加するだけです。逆に既存のLambdaを削除する場合、2つのファイルを削除するだけです。functions/new_func1/main.pyterraform/lambda_new_func1.tfコードサンプルはこちらにあります。Lambdaの構成管理ツールとしてTerraformを導入してから3ヶ月ほど経っています。本対応を終えて、振り返って思うことをお話しします。本記事で紹介した実装方法のメリットは、シンプルな構成であることかなと思います。ソースコードとインフラのリソース定義が1つのレポジトリで完結し、全体の見通しが良いです。Lambdaの追加や削除がとても簡単にできます。実務的に困るようなデメリットは今のところは顕在化していません。本記事で紹介した、規模の小さなプログラムを一元管理するようなタイプのレポジトリ(上記のworkerレポジトリ)の注意点として以下のことがあげられます。本来マイクロサービスとして独立して作るべき処理を、処理の追加とリリースが簡単という理由だけで、追加してはならないということです。このタイプのレポジトリに追加して良い処理は、緊急性が必要とされ、かつ、マイクロサービスとして切り出すことの費用対効果が得られないもの(規模の小さな処理、マイクロサービスとして切り出すべきかどうか、その境界が曖昧な処理)、に限定すべきです。applyコマンドの実行は、CD環境上で自動化されています。Pythonソースコードのユニットテストの実行は、CI環境上で自動化されています。我々の本番環境では、workerレポジトリ上で管理されているLambda関数は約50個あるため、functions/ディレクトリ配下には50個のLambdaのエントリーポイント、terraform/ディレクトリ配下には50個のLambda関数リソース定義があります。実際には、Terraformのリソース定義ファイルはもう少し作り込んであります(Lambdaのトリガーリソースの定義、モジュール機能、-var-fileオプション、stateファイル管理周り)。今回の記事では省略しました。50個全てのLambdaを、無停止でapexからTerraformへ切り替える作業が本当に大変なところであり、話したいところでもあるのですが(汗)、記事がとても長くなってしまうので省略しました。(CDO)の小笠原(@yamitzky)です。Corp.引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。