コンテンツにスキップ

lambda pattern

概要

lambda patternは、AWS Lambdaの関数を作成するpatternです。 Lambda関数だけでなく、当該関数を実行するトリガーや、Lambda関数の実行終了後の通知も同時に構築できます。

想定する適用対象環境

lambda patternはRuntime環境で使用されることを想定しています。

依存するpattern

lambda patternには、事前に実行が必要なパターンはありません。

ただし、以下の場合には事前の準備が必要となりますのでご注意ください。

構築されるリソース

リソース名 説明
AWS Lambda Lambda関数を作成します。
AWS IAM Lambda関数の実行ロールを作成します。条件によってはSNS topicへのpublishを行うポリシーやVPC内のリソースにアクセスするためのポリシー等を作成します。
Amazon CloudWatch Lambda関数のログを配置するロググループを作成します。
Amazon EventBridge Lambda関数のスケジュール実行する場合、ルールおよび、ターゲットを作成します。
Amazon S3(S3) Lambda関数の発火イベントにAmazon S3イベント通知を利用する場合は、S3イベント通知設定を作成します。

モジュールの理解に向けて

AWS Lambdaは、インフラのプロビジョニングなしに、コードを実行できるサービスです。 これにより、開発者はサーバー等を気にすることなく実行するアプリケーション(Lambda関数)へ集中できますし、 過剰なインフラにコストを支払う必要もありません。

一方でLambda関数は単体では存在し得ず、その実行のトリガーを必要とします。 また、Lambda関数がVPC内のリソースへのアクセスを必要とする場合はそれ専用の設定が必要となりますし、実行時にエラーが発生した場合に通知を受け取りたいこともあるでしょう。

本patternは、そういったLambda関数で煩雑となり得る設定を一元的に設定可能とするものです。

構成図

Lambda関数のデプロイ

Terraformでデプロイを行う

本patternを用いてLambda関数をデプロイする場合、Lambda関数のソースファイルが配置されたディレクトリ名を source_dirに相対パスで指定します。 指定したパス以下のリソースがzip形式に圧縮・アップロードされ、Lambda関数として登録されます。

module "lambda" {
  ...
  source_dir = "./lambda_function"
}

ディレクトリの中にはLambda関数とは無関係のファイルが含まれている場合もあるでしょう(設定ファイルやテストコード等)。 このような場合、本patternではsource_dir_exclude_filesに指定することでLambda関数の実行に不要なファイルを除外できます。


⚠️ ディレクトリ指定や、ワイルドカード(*)を使った指定はできない点にご注意ください。


module "lambda" {
  ...
  source_dir               = "./lambda_function"
  source_dir_exclude_files = [ # Lambda関数実行に不要なファイルをリストする
    "package.json",
    "package-lock.json",
  ]
}

Lambda関数のデプロイ方法については公式ドキュメントも参照してください。

ℹ️ lambda patternでは指定されたディレクトリのzip圧縮とデプロイのみ実施し、依存関係のあるパッケージのダウンロード等は行いません。同梱するパッケージがある場合は、公式ドキュメントの記載を参照していただき、事前にディレクトリ内へ配置しておいてください。

Lambda関数の環境変数を設定する場合は、入出力リファレンスenvironmentで設定してください。

ℹ️ Lambdaに値を渡すには、環境変数の他に AWS Systems Manager パラメータストア も利用可能です。
詳細は こちら を参照してください。
Eponaのparameter_store patternもあわせてご参照ください。

CI/CDパイプラインを利用する

Eponaでは、AWS CodePipelineなどを利用したCI/CDパイプラインにも対応しています。概要についてはcd_pipeline_lambda patternガイドを参照してください。

Lambda関数へのIAMポリシーの付与

Lambda関数がAmazon DynamoDB等、他のAWSリソースへアクセスする場合、Lambda関数にはそれらのリソースへのアクセス権限をIAMポリシーとして付与しなければなりません。

本patternではLambda関数に割り当てるIAMロールを作成し、そのARNをrole_arnという名称でOutput Valuesに出力しています。 Lambda関数が必要とするIAMポリシーは、このrole_arnに割り当ててください。

以下に、Amazon DynamoDBストリームからレコードを読み出すためのアクセス許可をLambda関数に与える例を示します。

module "lambda" {
  source = git::https://gitlab.com/eponas/epona.git//modules/aws/patterns/lambda?ref=v0.2.6"
  ...
}
# このmoduleにより、Lambda関数用のロールが作成され、そのロールをrole_arnにより参照できるようになります

data "aws_iam_policy" "dynamodb" {
  arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaDynamoDBExecutionRole"
}

resource "aws_iam_role_policy_attachment" "iam" {
  # moduleのrole_arnを指定することで、必要なロールをアタッチできます
  role       = module.lambda.role_name
  policy_arn = data.aws_iam_policy.dynamodb
}

Lambda関数の実行トリガー

Lambda関数はデプロイしただけでは実行されず、関数を「どのようなときに実行するか」というトリガーを指定する必要があります。 本patternでは代表的な実行トリガーとして、以下をサポートしています。

  • Amazon EventBridgeを使ったスケジュール実行
  • Amazon S3バケット上のオブジェクト操作をトリガーとする実行

なお、トリガーは複数種類同時に指定が可能です。

ℹ️ 複数のトリガーを設定し、同時に条件を満たした場合、Lambda関数は同時に並列で起動します。

また、まれにですが 1つのトリガーにより複数回実行される ことがあります。

トリガーに応じて厳密に1回の実行(exactly-once)を担保する必要がある場合は、こちらの記載を参照していただき、必要な措置を検討してください。

ℹ️ Lambda関数をイベントにより呼び出す(非同期呼び出し)場合、AWS Lambdaはイベントをキューに入れて管理し、エラー発生時には自動的に再試行します。イベントによりLambda関数を起動する場合は、再試行を考慮した実装となるようご留意ください。詳細はこちらをご参照ください。

Amazon EventBridgeを使ったスケジュール実行

Amazon EventBridgeを使用し、毎時実行や日次実行といった定期実行や、特定時刻での実行といったスケジュール実行が可能です。

スケジュール実行する場合、schedule_expressionにスケジュール式を指定してください。 記述方法については、Rate または Cron を使用したスケジュール式を参照してください。

なお、スケジュール実行を一時的に無効化できます。この場合は、is_enabled_schedulefalseを指定してください。

module "lambda" {
  ...
  # Lambda関数を毎時実行したい場合
  schedule_expression = "rate(1 hour)"
}

Amazon S3バケット上のオブジェクト操作をトリガーとする実行

時刻ではなく、S3バケット上で何かオブジェクトが作成されたタイミングや更新・削除されたタイミングでもLambda関数を実行できます。

この場合は、どのバケットのどのようなオブジェクトを対象にするのか、そしてどのような操作を対象とするのかを指定してください。

なお、どのような操作を対象とするかを指定する際、本patternではAmazon S3 イベント通知を利用しています。 このため、指定方法については当該ドキュメントを参照してください。

module "lambda" {
  ...
  # どのような操作(event)をトリガーとするのか
  invoke_object_events = [
    "s3:ObjectCreated:*", # オブジェクトが作成されたときに実行
  ]

  # どのバケットやオブジェクトを対象にトリガーとするのか。prefix/suffixを両方指定した場合、AND条件として判断します
  invoke_bucket_name          = "your_bucket_name"
  invoke_bucket_arn           = "arn:aws:s3:::your_bucket_name"
  invoke_object_filter_prefix = "image_"
  invoke_object_filter_suffix = ".png"
}

Lambda関数が実行完了した際のSNS通知

LambdaをAmazon API Gatewayなどから同期的に呼び出す場合、成功・失敗は即座に判別できます。

一方、スケジュールやイベントなど、ユーザーが介在しない状態で非同期的にLambdaが実行される場合、その実行結果を受け取るには別途仕組みを用意する必要があります。

lambda patternでは、Lambda関数の実行完了時に、Amazon SNS(以下、SNS)へ通知できます。 これにより、例えばLambda関数の実行が完了した場合にメールを送る、といったことを実現できます。

なお、SNS Topicへ通知するにあたり、本patternでSNS topic自体は作成しません。ユーザー側での準備が必要となる点にご注意ください。 これはSNSの使用用途が多岐に渡り、事前の想定が困難であるためです。

SNSへの通知機能を利用する際は、Lambda関数の実行成功時、失敗時でそれぞれSNS topicのARNを最大1つ指定します。 なお、成功時・失敗時用に同一のSNS topicを指定しても問題ありません。

module "lambda" {
  ...
  notify_sns_topic_on_success = "arn:aws:sns:ap-northeast-1:000000000000:lambda-notification-success"
  notify_sns_topic_on_failure = "arn:aws:sns:ap-northeast-1:000000000000:lambda-notification-failure"

参考として、Lambda関数の成功時、失敗時のSNS通知のサンプルを以下に示します。

成功時サンプル

{
  "version": "1.0",
  "timestamp": "2021-07-12T10:31:45.866Z",
  "requestContext": {
    "requestId": "64329d74-bbde-49c3-9105-557a24a8aaaa",
    "functionArn": "arn:aws:lambda:ap-northeast-1:000000000000:function:YourLambdaFunction:$LATEST",
    "condition": "Success",
    "approximateInvokeCount": 1
  },
  "requestPayload": {},
  "responseContext": {
    "statusCode": 200,
    "executedVersion": "$LATEST"
  },
  "responsePayload": "2021/07/12/[$LATEST]b219eebba4894af59b50ccbb8a37aaaa"
}

失敗時サンプル

{
  "version": "1.0",
  "timestamp": "2021-07-12T10:26:29.290Z",
  "requestContext": {
    "requestId": "b9a868fb-96ef-4101-b4df-f12ce53eaaaa",
    "functionArn": "arn:aws:lambda:ap-northeast-1:000000000000:function:YourLambdaFunction:$LATEST",
    "condition": "RetriesExhausted",
    "approximateInvokeCount": 3
  },
  "requestPayload": {},
  "responseContext": {
    "statusCode": 200,
    "executedVersion": "$LATEST",
    "functionError": "Unhandled"
  },
  "responsePayload": {
    "errorType": "ReferenceError",
    "errorMessage": "function is not defined",
    "trace": [
      "ReferenceError: sz is not defined",
      "    at Runtime.exports.handler (/var/task/index.js:2:1)",
      "    at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)"
    ]
  }
}

ℹ️ SNSに通知された内容は、Lambdaあるいは AWS Chatbot を介して SlackMicrosoft Teams 等のツールにも通知できます。
以下のリンク先もあわせてご参照ください。

Lambda関数のVPCへの配置

Lambda関数は、通常、利用者のAmazon VPC(以下、VPC)の外に置かれます(参考)。

一方で、Amazon RDS等、利用者のVPC内のリソースに対してLambda関数からアクセスしたいケースがあります。 このような場合、Lambda関数をVPC内に配置しますが、この配置についても本patternではサポートしています。

なお、本patternではVPCは作成しません。VPCの作成に関しては、必要に応じてnetwork patternをご利用ください。 以下にnetwork patternで作成したVPC内にLambda関数を作成する例を示します。

data "terraform_remote_state" "production_network" {
  backend = "s3"

  config = {
    bucket         = "myservice-production-terraform-tfstate"
    key            = "network/terraform.tfstate"
    encrypt        = true
    dynamodb_table = "myservice_terraform_tfstate_lock"
    role_arn       = "arn:aws:iam::[Production環境のアカウントID]:role/RuntimeTerraformBackendAccessRole"
  }
}

# Lambda関数用にセキュリティグループを作成する
resource "aws_security_group" "lambda" {
  vpc_id = data.terraform_remote_state.production_network.outputs.network.vpc_id
  ...
}

module "lambda" {
  source                        = "git::https://gitlab.com/eponas/epona.git//modules/aws/patterns/lambda?ref=v0.2.6"
  source_dir                    = "./lambda_function"
  function_name                 = "YourLambdaFuncionName"
  runtime                       = "nodejs14.x"
  handler                       = "index.handler"
  environment                   = { hoge = "moge" }
  vpc_config_subnet_ids         = data.terraform_remote_state.production_network.outputs.network.private_subnets
  vpc_config_security_group_ids = [aws_security_group.lambda.id]
}

なお、Eponaでのterraform_remote_stateの利用方法はこちらをご覧ください。

ℹ️ Lambda関数をVPC内に置くことで、Lambdaからのインターネットアクセスに制約が生じたり、VPC側に新たな設定が必要となったりすることがあります。設定に際しては以下の参照先もあわせてご参照ください。

Lambda関数の同時実行数

Lambda関数には同時実行数の制約を課すことができます。これにより、Lambda関数がアクセスするリソースの スケーラビリティの制約以上に同時実行数を増やさないようにできます。

詳細はLambda 関数の同時実行数の管理を参照ください。

本patternでは、上記ページの「リザーブド同時実行」をLambda関数に設定できます。 設定するためには、reserved_concurrent_executionsに数値を指定します。0を指定すると関数は実行されません。 -1を指定すると同時実行数を制限しません。

module "lambda" {
  ...
  reserved_concurrent_executions = 0
}

エイリアス

Lambda関数では1つ以上のエイリアスを作成できます。

Lambda関数はバージョンをサポートしており、バージョンに対してエイリアスを作成できます。 lambda patternでは、デフォルトではLambda関数の最新バージョン(初期構築時のバージョンは1)に対して エイリアスを作成します。

Eponaでは、Lambda関数の更新およびデプロイはcd_pipeline_lambda patternを使用して実施することを 想定しています。詳細はcd_pipeline_lambda patternのガイドをご参照ください。

ℹ️ 初期構築後、本patternによりLambda関数を更新しても、エイリアスに紐づく バージョンは変更されません。
エイリアスに紐づくバージョンの変更には、cd_pipeline_lambda patternで構築したパイプラインの実行が 必要です。

module "lambda" {
  ...
  aliases = [
    "default"
  ]
}

詳細は公式ドキュメントを参照してください。

制限

2021/09現在、lambda patternには以下の制限があります。

  • Lambda関数のコードの変更はローカルにあるディレクトリから、あるいはcd_pipeline_lambda patternを利用したデプロイが前提になっています
    • Amazon S3上に配置されたソースコードからのデプロイや、Amazon ECR上のコンテナのデプロイには未対応です
  • Lambdaレイヤーには対応しておりません
  • Amazon EFSには対応しておりません

サンプル

module "lambda" {
  source = "../../../../../modules/aws/patterns/lambda/"

  function_name = "my-function"
  source_dir    = "./src"
  source_dir_exclude_files = [
    "package-lock.json",
    "package.json",
  ]
  ignore_change_source = false
  runtime              = "nodejs14.x"
  description          = "サンプル"
  handler              = "index.handler"
  environment = {
    VAR = "VALUE"
  }

  memory_size = 128
  timeout     = 60 # 60秒

  tracing_mode                   = "Active"
  reserved_concurrent_executions = 1

  log_group_retention_in_days = 7

  schedule_expression = "cron(0 0 * * ? *)" # 毎日 09:00 (JST)に起動
  is_enabled_schedule = true
}

関連するpattern

lambda patternに関連するpatternを以下に記載します。

pattern名 説明
network VPC内にAWS Lambdaを配置する場合のVPCを作成する
step_functions AWS LambdaなどのAWSサービスを連携したワークフローを構築する
api_gateway APIを作成・公開するためのAmazon API Gatewayを作成する
cd_pipeline_lambda Lambda関数のデプロイメントパイプラインを構築する
cd_pipeline_lambda_trigger Lambda関数のデプロイのトリガとなるイベントやDelivery環境のリソースアクセスに必要なロールなどを構築する

入出力リファレンス

Requirements

Name Version
terraform ~> 0.14.10
aws >= 3.37.0, < 4.0.0

Inputs

Name Description Type Default Required
function_name Lambda関数の名称を指定する。 string n/a yes
handler Lambda関数のエントリーポイントとなる、関数内のメソッド名を指定する。
Node.jsの例
string n/a yes
runtime 利用するランタイムを指定する。
指定できる値についてはこちらを参照
string n/a yes
source_dir Lambda関数のソースが配置されたディレクトリを指定する。 string n/a yes
aliases Lambda関数に付与するエイリアスを指定する。複数指定が可能。 list(string) [] no
description Lambda関数の説明を記載する。 string null no
environment Lambda関数が使用する環境変数を{key = value}の形式で指定する。 map(string) {} no
ignore_change_source source_dirで指定されたディレクトリの中身が変更されていても、Lambda関数を更新しないようにする場合はtrueを指定する。デフォルトはfalse。なお、falseの場合、source_dirで指定されたディレクトリの中身と、AWS環境上にデプロイ済みのLambda関数を比較し、差分があればsource_dirの内容でLambda関数を上書きする。 bool false no
invoke_bucket_arn Lambda関数の実行トリガーとなるS3バケットのARNを指定する。invoke_bucket_nameと同時に指定する必要がある。 string null no
invoke_bucket_name Lambda関数の実行トリガーとなるS3バケットの名称を指定する。invoke_bucket_arnと同時に指定する必要がある。 string null no
invoke_object_events Lambda関数の実行トリガーとなるS3バケットのイベントを指定できる。デフォルトは作成時。

指定する内容についてはAmazon S3 イベント通知を参照。
このパラメータを設定する際は、invoke_bucket_arninvoke_bucket_nameもあわせて設定する必要がある。
list(string)
[
"s3:ObjectCreated:*"
]
no
invoke_object_filter_prefix Lambda関数をS3バケットのイベントで実行する場合で、対象となるオブジェクトをプレフィックスで絞り込む際に設定する。

詳細は公式ドキュメントを参照。
このパラメータを設定する際は、invoke_bucket_arninvoke_bucket_nameもあわせて設定する必要がある。
string null no
invoke_object_filter_suffix Lambda関数をS3バケットのイベントで実行する場合で、対象となるオブジェクトをサフィックスで絞り込む際に設定する。

詳細は公式ドキュメントを参照。
このパラメータを設定する際は、invoke_bucket_arninvoke_bucket_nameもあわせて設定する必要がある。
string null no
is_enabled_schedule Lambda関数をスケジュール実行する場合で、一時的にスケジュール実行を止める場合に設定する。デフォルトはtrue(実行する)であり、止める場合はfalse(実行しない)と設定する。 bool true no
log_group_retention_in_days CloudWatch Logsのロググループでログを保持する日数を指定する。デフォルトは14日。 number 14 no
memory_size Lambda関数に割り当てるメモリサイズをMB単位で指定する。
指定できる値の制約についてはLambda quotasを参照。
number 128 no
notify_sns_topic_on_failure Lambdaから実行失敗を通知する際の通知先となるSNSトピックのARNを指定する。 string null no
notify_sns_topic_on_success Lambdaから実行成功を通知する際の通知先となるSNSトピックのARNを指定する。 string null no
reserved_concurrent_executions Lambda関数の同時実行数を設定する。公式ドキュメントリザーブド同時実行数に該当する。
指定できる値についてはreserved_concurrent_executionsを参照。
number -1 no
schedule_expression Lambdaをスケジュール実行する場合、スケジュール式をcron()式あるいはrate()式で指定する。

記述方法についてはRateまたはCronを使用したスケジュール式を参照。
string null no
source_dir_exclude_files source_dirで指定したディレクトリ配下で、zipファイルに含めないファイルを指定する。

例えば、source_dirnodeで、その中のtest.jsを除外したい場合は、test.jsと指定する(source_dirのディレクトリ名は含めない。なお、*は使えない)。

実際は、
source_dir_exclude_files = [
"test.js",
"node_modules/eslint-config-eslint/package.json"
]
のようにlist(string)で指定する。
list(string) [] no
tags タグを指定する。 map(string) {} no
timeout Lambda関数に許可する実行時間(タイムアウト)を秒単位で指定する。デフォルトでは3秒、最大は900秒となる。 number null no
tracing_mode AWS X-Rayを使用して実行状況をトレースする場合、トレースの種類を指定する。PassThroughActiveを指定する。デフォルトはPassThrough

詳細は公式ドキュメントおよびTerraformドキュメントを参照。
string "PassThrough" no
vpc_config_security_group_ids Lambda関数をVPC内に配置する場合、Lambdaに許容するルールを設定したセキュリティグループをアタッチする。 list(string) [] no
vpc_config_subnet_ids Lambda関数をVPC内に配置する場合、Lambdaを接続するサブネットIDを指定する。 list(string) [] no

Outputs

Name Description
arn Lambda関数のARN
function_name Lambda関数の名称
invoke_arn API GatewayからLambda関数を呼び出すために使用されるARN
qualified_arn Lambda関数のバージョンのついたARN
role_arn Lambda実行ロールのARN
role_name Lambda実行ロールの名称。他のAWSリソースへのアクセス権限が必要な場合は、このロールにアタッチする
version Lambda関数のバージョン

※ このドキュメントはクリエイティブコモンズ(Creative Commons) 4.0 の「表示—継承」に準拠しています。

※ このドキュメントに記載されている会社名、製品名は、各社の登録商標または商標です。

© 2021 TIS Inc.