AWS CloudFormationを触ってみる #2 EventBridge Lambda SNS
もくじ
はじめに
こんにちは 中村です!
前回 CloudFormationをとりあえず触ってみる記事を書きました
今回はそれより少し複雑な構成をデプロイしてみようと思います
構成
以下のような構成となります。
EventBridgeが2分おきにLambdaを発火し、Lambda、SNSを通じてメールを飛ばすという内容です。

テンプレート
以下のテンプレートファイルをローカルに保存してください
template.yml
AWSTemplateFormatVersion: 2010-09-09
Parameters:
ResourceName:
Type: String
Email:
Type: String
Resources:
LambdaFunction:
Type: AWS::Lambda::Function
Properties:
Handler: index.lambda_handler
Code:
ZipFile: !Sub |
import boto3
import os
import datetime
client = boto3.client('sns')
topic_arn = os.environ['TopicArn']
def lambda_handler(event, context):
dt_now = datetime.datetime.now().strftime('%Y年%m月%d日 %H:%M:%S')
params = {
'TopicArn': topic_arn,
'Subject': 'Lambda SNS メール送信 '+ str(dt_now),
'Message': 'Message\n\nLambda -> SNSでメール送ったよ\n届いた?\n' + str(dt_now)
}
client.publish(**params)
FunctionName: !Sub ${ResourceName}-function
Runtime: python3.9
Environment:
Variables:
TopicArn : !Sub arn:aws:sns:${AWS::Region}:${AWS::AccountId}:${ResourceName}-sns
Role: !GetAtt
- LambdaExecutionRole
- Arn
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${ResourceName}-function-execution-role
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: !Sub ${ResourceName}-function-policy
PolicyDocument:
Version: 2012-10-17
Statement:
- Resource: !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${ResourceName}-function:*
Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
- logs:CreateExportTask
- s3:GetBucketAcl
- s3:PutObject
- PolicyName: !Sub ${ResourceName}-function-nsn-policy
PolicyDocument:
Version: 2012-10-17
Statement:
- Resource: !Sub arn:aws:sns:${AWS::Region}:${AWS::AccountId}:${ResourceName}-sns
Effect: Allow
Action:
- sns:Publish
SnsTopic:
Type: AWS::SNS::Topic
Properties:
DisplayName: !Sub ${ResourceName}-sns
FifoTopic: false
TopicName: !Sub ${ResourceName}-sns
Subscription:
- Endpoint: !Ref Email
Protocol: email
EventBridgeRule:
Type: AWS::Events::Rule
Properties:
EventBusName: default
Name: !Sub ${ResourceName}-eventbridge-rule
ScheduleExpression: cron(0/2 * * * ? *)
State: ENABLED
Targets:
- Arn: !GetAtt LambdaFunction.Arn
Id: LambdaFunction
PermissionForEventsToInvokeLambda:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !Ref LambdaFunction
Action: lambda:InvokeFunction
Principal: events.amazonaws.com
SourceArn: !GetAtt 'EventBridgeRule.Arn'
CloudFormationを実行
上記テンプレートをローカルに保存した上で、
こちらを参考にCloudFormationを作成してください
今回は2つのパラメータを指定します
- ResourceName

テンプレートファイルに以下のように記述する事で、作成時に自由に値を指定できるパラメータを設定することができます
Parameters:
ResourceName:
Type: String
Email:
Type: String
無事にスタックが作成されました

作成されたリソースを確認
リソースがちゃんと作成されたか確認します
- EventBridgeルール

- Lambda関数

- SNSトピック

ちゃんと作成されていますね!(^^)b
スタックのパラメータで指定したメールアドレスにSNSからサブスクリプション承認のメールがきているので、リンクをクリックして承認します。(これでSNSからメールが受け取れるようになります)

動作確認
作成したリソースがちゃんと意図した通り動いているか確認します。
指定した頻度でメールが届いています

メール本文もLambdaで指定した通りですね!

リソース削除
さて、2分おきに迷惑メールが来てウザいのでw リソース削除しちゃいます。
それぞれのリソースを削除することも可能ですが、CloudFormationスタックで作ったものはCloudFormationスタックごと削除する方が無難かと思います。
対象のスタックを選択して「削除」をクリックします

テンプレートを作成するにあたって
CloudFormationユーザーガイド
基本的にはAWS公式のCloudFormationユーザーガイドと睨めっこしながら作成していきます
左メニューのテンプレートリファレンス
→リソースおよびプロファイルのリファレンス
を開くと、AWSサービス毎のテンプレートの書き方が解説されています

エラーでコケまくる
筆者は何度もエラーでコケまくり、テラテイルで質問してみたり、Twitterで教えて頂いたりしました
皆様ありがとうございます!!
Lambdaソースコードはどうするのか
CloudFormaitonでLambdaを作成する場合はソースコードはファイルをzip化してS3に保存しなければいけないと言う旨の記事が多かったのですが、そんなの面倒くせぇ!絶対嫌だ!
と言うことでテンプレートファイルに直接コードを書く方法が無いか探しました。
ありました。さすがクラメソさんですね。
CloudFormationでCloudWatchEvents→Lambdaの環境を作るときに気をつけたいこと(クラスメソッド)
終わりに
yaml形式で書くのは初めてだった為、なかなか苦労しました。
当たり前かもですが、テンプレートを作成するのが時間がかかりますが、作っちゃえばそれを使いまわせるのがいいですね。
さらにリソース名や設定値をパラメータを使ってデプロイ時にカスタマイズできるので、自由度が高いと感じました
今後もっと活用していきたいと思います!
ここまで読んで頂きありがとうございました!