lulu

【AWS lambda】lambdaの定期実行(EventBridge:CloudWatch Events)をTerraformで設定する

やること

AWS lambdaの定期実行(EventBridge:CloudWatch Events)をTerraformで設定する方法を紹介いたします。

前提

上記2記事の続きになります。

ファイル構成

↑の記事の通り、terraformでlambda関数を作成していた場合、以下のようなディレクトリ構成になっています(.terraformやtfstateは割愛)

$ tree .
.
├── index.js
├── node_modules
├── lambda.zip
├── main.tf
└── package.lock.json

そして、Terraformのソースを記載するmain.tfは以下のようになっています。

provider "aws" {
  region = "ap-northeast-1"
}

resource "aws_iam_role" "iam_for_lambda" {
  name = "iam_for_lambda_afasdasdf"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

resource "aws_lambda_function" "test_lambda" {
  filename      = "lambda.zip"
  function_name = "lambda_function_name"
  role          = aws_iam_role.iam_for_lambda.arn
  handler       = "index.handler"
  source_code_hash = filebase64sha256("lambda.zip")
  runtime = "nodejs14.x"

  timeout = 30
}

resource "aws_cloudwatch_log_group" "example" {
  name              = "/aws/lambda/lambda_function_name"
  retention_in_days = 14
}

resource "aws_iam_role_policy_attachment" "lambda_logs" {
  role       = aws_iam_role.iam_for_lambda.name
  policy_arn = aws_iam_policy.lambda_logging.arn
}

resource "aws_iam_policy" "lambda_logging" {
  name        = "lambda_logging"
  path        = "/"
  description = "IAM policy for logging from a lambda"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*",
      "Effect": "Allow"
    }
  ]
}
EOF
}

今回はこのファイルに定期実行用のresource(cloudwatch events)を追加していきます。

cloudwatch events用の記述の追記

main.tfに以下を追記

resource "aws_cloudwatch_event_rule" "five_minutes" {
    name                = "five_minutes"
    schedule_expression = "rate(5 minutes)"
}

resource "aws_cloudwatch_event_target" "output_report_every_month" {
    rule      = aws_cloudwatch_event_rule.five_minutes.name
    target_id = "five_minutes"
    arn       = aws_lambda_function.test_lambda.arn
}

resource "aws_lambda_permission" "allow_cloudwatch_to_call_output_report" {
    statement_id  = "AllowExecutionFromCloudWatch"
    action        = "lambda:InvokeFunction"
    function_name = aws_lambda_function.test_lambda.function_name
    principal     = "events.amazonaws.com"
    source_arn    = aws_cloudwatch_event_rule.five_minutes.arn
}

上から順に、

  • cloudwatch event ruleの作成
  • cloudwatch event targetの作成
  • lambdaにcloudwatch eventをトリガーとして登録

になります。

完成版のコード

provider "aws" {
  region = "ap-northeast-1"
}

resource "aws_iam_role" "iam_for_lambda" {
  name = "iam_for_lambda_afasdasdf"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

resource "aws_lambda_function" "test_lambda" {
  filename      = "lambda.zip"
  function_name = "lambda_function_name"
  role          = aws_iam_role.iam_for_lambda.arn
  handler       = "index.handler"
  source_code_hash = filebase64sha256("lambda.zip")
  runtime = "nodejs14.x"

  timeout = 30
}

resource "aws_cloudwatch_log_group" "example" {
  name              = "/aws/lambda/lambda_function_name"
  retention_in_days = 14
}

resource "aws_iam_role_policy_attachment" "lambda_logs" {
  role       = aws_iam_role.iam_for_lambda.name
  policy_arn = aws_iam_policy.lambda_logging.arn
}

resource "aws_iam_policy" "lambda_logging" {
  name        = "lambda_logging"
  path        = "/"
  description = "IAM policy for logging from a lambda"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*",
      "Effect": "Allow"
    }
  ]
}
EOF
}


resource "aws_cloudwatch_event_rule" "five_minutes" {
    name                = "five_minutes"
    schedule_expression = "rate(5 minutes)"
}

resource "aws_cloudwatch_event_target" "output_report_every_month" {
    rule      = aws_cloudwatch_event_rule.five_minutes.name
    target_id = "five_minutes"
    arn       = aws_lambda_function.test_lambda.arn
}

resource "aws_lambda_permission" "allow_cloudwatch_to_call_output_report" {
    statement_id  = "AllowExecutionFromCloudWatch"
    action        = "lambda:InvokeFunction"
    function_name = aws_lambda_function.test_lambda.function_name
    principal     = "events.amazonaws.com"
    source_arn    = aws_cloudwatch_event_rule.five_minutes.arn
}

こちらが完成版のコードになります。
このコードがあるディレクトリで、

$ terraform init
$ terraform apply

していただけたら、5分に一回、magical-academia.comをGETしてcloudwatch logsにlogを保存するlambda関数が作成できます。