AWS LambdaのコードをTerraformでデプロイする
今更感もありますが、今日はTerraformでのAWS Lambdaのコード化について書きます。 AWS Lambdaは Cloud9 がコンソール上に組み込まれたこともあり、開発がさらに容易になりました。 ブラウザエディタは そのままwebにつながる というのが最大の強みですが、まだまだ手元のリポジトリでコードを管理している手前、AWSのサービスだけで完結できていないのが現状です。 今回はAWS LambdaのコードをTerraformを使ってデプロイする方法を説明しようと思います。
↓ちなみに下が組み込まれたCloud9
TerraformでAWS Lambdaをデプロイしたい
Infrastructure as Code
はクラウド界隈でバズってだいぶ時間も立っていますので、あまりここでは触れません。
必要に応じて界隈の方のブログや以下の書籍を読んでください。
AWS Lambdaがサービスとして登場した頃は、簡易なバッチ的な仕組みとしての用途が多く、作り捨てなコードが多かったです。 その後、連携可能な他のAWSサービスも増えて、VPC内に立ち上げることも可能になり(起動時間はかなり遅いですけど)、用途の幅に広がりが出てきました。 そんな 「まぁ、Lambdaでいっか」 ケースが増えると同時に、一度デプロイしたLambdaのコードを修正して再デプロイするというケースも増えてきました。
業務上 Terraform
を使ってAWSリソースをコード化しているので、Lambdaもその管理の対象にしようと思ったのが契機です。
やってみる
実際にLambdaをTerraformでデプロイするコード化してみました。 コードサンプルは こちら にあります。
簡単にリポジトリの説明をしておきます。
デプロイ用のマシンに必要なライブラリ等は以下になります。
- Terraform
- Python 3.6
またディレクトリ構成はこんな感じです。
1.
2├── Makefile
3├── README.md
4├── build.sh
5├── lambda-src
6│ ├── __init__.py
7│ └── main.py
8├── requirements.txt
9└── terraform
10 ├── backend.tf
11 ├── dev.tfvars
12 ├── lambda.tf
13 ├── provider.tf
14 └── variables.tf
lambda-src
ディレクトリにはLambdaで実行するPythonコード、 terraform
ディレクトリにはLmabdaのデプロイに使用するterraformの設定が格納されています。
めんどい前処理の類はシェル(build.sh
)でラップしてあって、開発者は make
のサブコマンドだけ意識しておけば良い、という作りにしています。
この方法自体は我流なので、よりスマートな方法はあると思います。
以降は実装する上でのポイントだけ記載していきます。
コードのエントリータイプはzipにしよう
Lambdaにソースコードを適用する方法は3種類存在します。
- Edit Code Inline
- ブラウザ上のエディタに直接書く方法。デプロイ後のコードを突貫で修正したりする時によく使う。
- Upload a .ZIP file
- zipファイルでアップロードする方法。今回はこれを採用する。
- Uplaod a file from Amazon S3
- S3からファイルを読み込む方法。
個人的には2番目の zipファイルでアップロードする方法 をオススメします。
理由としては以下
- 依存モジュールを含めてアップロードできる
- わざわざS3を積極的に経由するケースが思いつかない。(Lambdaに対して直接操作できない時とか?)
シェルでzip圧縮したいソース一式を作成する
シェルを使えば何でもできてしまうので、Terraformで完結させたい方には興ざめかもしれませんが、低コストだったのでこれにしました。
build.sh
の処理を見ていただければわかるのですが、 zip圧縮させたいファイル郡を管理する必要があるので、
専用の workspace
ディレクリを作成し、そこに依存モジュールとソースコードをまるごと放り込みます。
build.sh
1#!/usr/bin/env bash
2
3SCRIPT_DIR=$(cd $(dirname $0); pwd)
4WORKSPACE=${SCRIPT_DIR}/workspace
5SRC_DIR=${SCRIPT_DIR}/lambda-src
6
7if [ -d ${WORKSPACE} ]; then
8 rm -rf ${WORKSPACE}
9fi
10mkdir ${WORKSPACE}
11
12pip3 install -r ${SCRIPT_DIR}/requirements.txt -t ${WORKSPACE}
13cp -rf ${SRC_DIR}/* ${WORKSPACE}
Terraformでzip圧縮&デプロイ
workspace
ディレクトリのzip圧縮とデプロイを定義します。
terraformで archive_file
というデータリソースを使用することで、指定されたディレクトリをzip圧縮して出力することができます。
加えて、Lambda関数の作成の際に aws_lambda_function
リソースの source_code_hash
プロパティに、zipアーカイブしたデータリソースのbase64エンコードを指定することができるので、これでzipのデプロイコードの完成です。
1#####################################
2#Lambda
3#####################################
4resource "aws_lambda_function" "auth_log_monitoring" {
5 filename = "../lambda.zip"
6 function_name = "do_something"
7 role = "arn:aws:iam::${var.account_id}:role/XXXXXXRole"
8 handler = "main.lambda_handler"
9 source_code_hash = "${data.archive_file.lambda_zip.output_base64sha256}"
10 runtime = "python3.6"
11 timeout = 150
12}
13
14data "archive_file" "lambda_zip" {
15 type = "zip"
16 source_dir = "../workspace"
17 output_path = "../lambda.zip"
18}
ビルド&デプロイをつなげる
あとは build.sh
でのビルド処理とterraformでのデプロイをつなげてあげればOKです。
今回は Makefile
に以下のような定義をして、コマンド一発で処理ができるようにラップしています。
Makefile
1deploy:
2 @${CD} && \
3 sh ../build.sh && \
4 terraform workspace select ${ENV} && \
5 terraform apply \
6 -var-file=${VARS}
あとは make deploy
を打てば実行できます。(リポジトリ的にはterraformのリモートバケットの初期化を先に行う必要はあります。)
まとめ
Terraformを使用して、AWS Lambdaのソースコードのデプロイができるようになりました。 実際にはシェルを間にかませてビルドを行なっていますが、シェル内での処理自体はシンプルなので、横展開もしやすくなっています。 1点欠点としては、ランタイムがpythonの場合にはterraform実行時に毎回ハッシュにdiffが出てしまう という点。つまり、毎度デプロイしてしまうという所です。 しかし、今あるコードを正としてデプロイし続けることに問題がなければ、目をつむっても良い欠点なので、今の所気にしていません。 ちなみにランタイムがNodeだとこれはおきませんでした。