Closed11

SNSの通知をLambdaでわかりやすくする

not75743not75743

例えばスポットインスタンスの停止イベントをSNSでメール通知した場合、
このようなメッセージがくる

改行されないjsonですね
これでは見づらいのでLambdaで加工してみます

not75743not75743

chatbotに飛ばす場合

いくぶんか見やすくなるのですが、やはりNameタグなりの情報がほしいところ

not75743not75743

ポイント

eventbridgeターゲットの指定

snsトピックがターゲットとなっている場合、Lambda関数に変更します。

resource "aws_cloudwatch_event_target" "sns" {
  rule = aws_cloudwatch_event_rule.spot-interruption-rule.name
  arn  = aws_lambda_function.eventbridge-lambda-sns.arn
}
not75743not75743

Lambda関数周辺リソースの作成

長いので折りたたみます

lambda.tf
resource "aws_lambda_function" "eventbridge-lambda-sns" {
  function_name    = "eventbridge-lambda-sns"
  handler          = "main.lambda_handler"
  runtime          = "python3.10"
  filename         = data.archive_file.example_zip.output_path
  source_code_hash = data.archive_file.example_zip.output_base64sha256

  role = aws_iam_role.lambda_role.arn
  environment {
    variables = {
      SNS_TOPIC = aws_sns_topic.topic.arn
    }
  }
}

resource "aws_iam_role" "lambda_role" {
  name = "example-lambda-role"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
  managed_policy_arns = [
    "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
    aws_iam_policy.lambda_sns_publish.arn
  ]
}

resource "aws_iam_policy" "lambda_sns_publish" {
  name        = "lambda_sns_publish"
  path        = "/"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sns:Publish",
      "Resource": "${aws_sns_topic.topic.arn}"
    }
  ]
}
EOF
}

resource "aws_cloudwatch_log_group" "example_log_group" {
  name = "/aws/lambda/${aws_lambda_function.eventbridge-lambda-sns.function_name}"
  retention_in_days = 30
}

ポイントは

  • Lambdaのログを格納するロググループを作成する
  • 指定したSNSへpublish出来るようにIAMポリシーを作成する
  • SNSトピックの指定には環境変数を用いる

ことです

not75743not75743

Lambdaを操作する権限をEventBridgeに与える

aws_lambda_permissionを使うことで、EventBridgeがLambdaを呼び出せるようにします。
リソースポリシーを使用する、というやつです。

https://dev.classmethod.jp/articles/policies-for-lambda/
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/access-control-resource-based.html

resource "aws_lambda_permission" "allow_eventbridge" {
  statement_id  = "allow_eventbridge"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.eventbridge-lambda-sns.function_name
  principal     = "events.amazonaws.com"
  source_arn    = aws_cloudwatch_event_rule.spot-interruption-rule.arn
}
not75743not75743

Lambda関数コード

言語はpythonです。長いので折りたたみます

main.py
import json
import os
from datetime import datetime, timedelta, timezone

import boto3


def lambda_handler(event, context):
    sns_topic_arn = os.environ.get('SNS_TOPIC')

    detail = event['detail']
    instance_id = detail['instance-id']

    # Parse the termination time and convert it to JST
    termination_time_utc = datetime.strptime(event['time'], '%Y-%m-%dT%H:%M:%SZ')
    termination_time_jst = termination_time_utc.replace(tzinfo=timezone.utc).astimezone(timezone(timedelta(hours=9)))

    # Format the received time without timezone
    received_time = termination_time_jst.strftime('%Y-%m-%d %H:%M:%S')

    # Add 2 minutes to the termination time
    termination_time_jst += timedelta(minutes=2)

    # Format the termination time without timezone
    termination_time = termination_time_jst.strftime('%Y-%m-%d %H:%M:%S')

    # Combine instance ID, received time, and termination time in one message
    message = f'Instance ID: {instance_id}\nSpot Interruption Notice: {received_time}\nTermination Time: {termination_time}'

    sns = boto3.client('sns')
    sns.publish(
        TopicArn=sns_topic_arn,
        Message=message,
        Subject='Spot Instance Interruption Warning'
    )

    return {
        'statusCode': 200,
        'body': json.dumps('Success!')
    }

ポイントは

  • 環境変数でSNSトピックのArnを受け取る
  • スポットインスタンス停止通知イベントからインスタンスIDと通知受領時間を受け取る
  • pythonのstrftimeでフォーマットを整える
  • pythonのtimedeltaで2分後の停止予定時刻を作成する
  • 取得・作成した情報から文面を作成し、SNSでメール通知する
このスクラップは2023/06/25にクローズされました