やりたいこと
・TerraformでAWS Lambdaをデプロイしたい
・ローカルでlambdaソースを編集したらAWSへ連動できるか検証したい
前提
・AWSアカウント作成済み
・AWS IAMユーザーを作成し、access_keyとsecret_keyを発行済み
・Terraformインストール済み
・AWS CLIインストール済み
・VSCODEインストール済み
(お好みのエディターで大丈夫)
・Pythonインストール済み
(今回はpython3.9でlambadaを作ってみたいですが、極簡単なソースコードなのでバージョンどうてもいいかと思う)
環境
$ terraform -v
Terraform v1.5.5
on windows_amd64
+ provider registry.terraform.io/hashicorp/aws v5.13.1
$ python -V
Python 3.9.13
構築リソース
・AWS Lambda function
・AWS IAM role
・AWS IAM policy
ディレクトリ構成
必要最小限のソース構成ですが
root
┣━ lambda
┃ ┗━ test
┃ ┗━ src
┃ ┣━ test_terraform.py
┃ ┗━ test_terraform.zip
┣━ main.tf
┣━ variables.tf
┗━ lambda.tf
※補足
・lambdaフォルダに複数lambda functionのソースコードを入れる予定でtestフォルダで階層を掘ってますが、適宜階層を変えてもらって大丈夫
・test_terraform.zipはterraform実行で自動で作られたやつで、自分で用意する必要がない(後述説明)
ソースの中身
main.tf
・main.tfには基本、全体共通で重要な設定、例えば「AWS プロバイダの設定」を書く
・lambda関数実行時、cloudWatchへログを書き込むのに権限が必要、今回は三つの権限を付与してあげたいと思う
・今回は便宜上そのIAM設定を一緒にmain.tfに入れた。別途iam.tfで分けて作っても大丈夫
# AWS プロバイダの設定
provider "aws" {
access_key = var.access_key
secret_key = var.secret_key
region = var.region
}
# lambda用Roleの設定
resource "aws_iam_role" "lambda_iam_role" {
name = "terraform_lambda_iam_role"
assume_role_policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
POLICY
}
# lambda用Policyの作成
resource "aws_iam_role_policy" "lambda_access_policy" {
name = "terraform_lambda_access_policy"
role = aws_iam_role.lambda_iam_role.id
policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:CreateLogGroup",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
}
]
}
POLICY
}
variables.tf
・variables.tfに全ソース共通の変数を書く
・リージョンは東京にしたが、適宜変更して大丈夫
・access_keyとsecret_keyは事前に発行したやつを使用
variable "region" {
default = "ap-northeast-1"
}
variable "access_key" {
default = "自分のaccess_key"
}
variable "secret_key" {
default = "自分のsecret_key"
}
lambda.tf
・terraformのdataで、ローカルにあるpythonのソースのパスを教えてあげて、後でterraform plan実行時にzip化してくれて便利!
・terraform apply時は、source_code_hash(さっき作ったソースのzipファイル)をlambdaにアップしてくれる
# ローカルにあるlambdaのソースコード
data "archive_file" "test_terraform" {
type = "zip"
source_dir = "lambda/test/src"
output_path = "lambda/test/src/test_terraform.zip"
}
# AWSへ作るlambda function
resource "aws_lambda_function" "test_terraform" {
function_name = "test_terraform"
filename = data.archive_file.test_terraform.output_path
source_code_hash = data.archive_file.test_terraform.output_base64sha256
runtime = "python3.9"
role = aws_iam_role.lambda_iam_role.arn
handler = "test_terraform.handler"
}
test_terraform.py
・どうでもいいテストの内容ですwww
def handler(event, context):
print('test')
return()
Terraformでlambda functionを新規作成
念のため初期化してあげよう
terraform init
これが出たら成功かな
Terraform has been successfully initialized!
次にterraformの実行計画を確認しよう
terraform plan
新規ファイル、もしくは増分か差分がある場合、こういうふうに結果が出てくる
Plan: 4 to add, 0 to change, 0 to destroy.
terraform planを実行後、zip化したpythonのファイルが出てくるはず
terraform apply
ちゃんと成功したそうです!
今回は新規作成なので、「4 added」と表示してますが、今後修正分を反映するときは、changed(増分差分の反映)かdestroyed(削除)となるはず。
Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
AWS側を確認すると、AWS functionが立派にできてます!ちゃんとpython3.9になってますね!
AWS functionのソースを見てみると、zipファイルがちゃんとアップされ、ソースの中身は無事書き込まれた!
そして、lambda functionの持ってるIAM権限を確認すると、さっき作ってあげた三つの権限はちゃんと付与されてます!
ついてに、IAMも確認しよう!
lambdaへ付与したいロールは作られて、
cloudWatchへログを書き込むための三つの権限を持ってるpolicyも作られた!
最後、AWSで一回lambda functionを実行したうえ、cloudWatchを確認しよう!
lambda function専用のロググループが作られて、さっき実行した記録も残ってますね!
ローカルでlambdaのソースコードを編集
先ほどterraformで作られたlambada functionはちゃんとterraformの管理配下になってるか知りたいので、少しtest_terraform.pyを修正してみよう
def handler(event, context):
print('test again')
return()
そして、もう一度コマンドを実行
terraform plan
一つ変更があるよって、教えてくれた
Plan: 0 to add, 1 to change, 0 to destroy.
この時点でzipも作り直してくれたようです(日付が更新された)
では変更した分をAWSへデプロイしようと、
terraform apply
一個変更分をデプロイしたって、言ってますね
Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
最後、AWS側を確認すると、ソースコードをちゃんと最新化してくれた
終わりに
お疲れ様です!今回のやりたいことが無事終わった!
・TerraformでAWS Lambdaをデプロイしたい
⇒デプロイできた
・ローカルでlambdaソースを編集したらAWSへ連動できるか検証したい
⇒連動できる、terraform planで管理されてる