この記事は約4分で読めます。
この記事は1年以上前に書かれたものです。
内容が古い可能性がありますのでご注意ください。
はじめに
こんにちは。孔子の80代目子孫兼技術5課の孔です。やっと梅雨が終わりましたね!日光で干した洗濯物の方が気持ちよく着れるので、とても嬉しいですが、ここ3ヶ月間家からほとんど出てないのでそんなに意味なかったな…とダークモードになっています。コロナ終息のために、頑張りましょう!
今日はServerless Framework + SNSというトピックを持ってきました。例えば、CloudWatch Eventsを使ってLambdaを毎日朝9時に走らせるような処理をするとしいて、毎日朝9時にLambdaが正常に起動したかどうか確認しにAWSコンソールを開くのはとても面倒な作業ですね。そこでLambdaが失敗した時にSNSで自動的に通知して、Slackでそのメッセージを受け取るような構成を作れば、毎日確認する作業がなくなってとても楽になります。
そのような構成とサンプルコードを、Serverless Frameworkでデプロイしてみよう!というのが本日のテーマとなります。Serverless FrameworkはAWS上にLambdaを中心にいろいろなAWSリソースをデプロイできるサービスとなります。それでは、実際やってみましょう。
※ Serverless Frameworkを触ったことのある方を対象としているため、基本的な操作については説明を割愛しています。
まずはPythonコード
2つのコードを用意しました。Slackに投稿するためのLambdaコード(notify_to_slack.py)と、SNSにpublishするコード(publisher.py)となります。
# notify_to_slack.pyimport urllib3import jsonhttp = urllib3.PoolManager()def lambda_handler(event, context):url = "https://hooks.slack.com/services/XXXXX...."msg = {"channel": "#slack_channel", # Slackのチャンネル名"username": "Lambdaからのお知らせ", # bot名"text": event['Records'][0]['Sns']['Message'],"icon_emoji": "emoji" # botのアイコン}encoded_msg = json.dumps(msg).encode('utf-8')resp = http.request('POST', url, body=encoded_msg)return {"message": event['Records'][0]['Sns']['Message'],"status_code": resp.status,"response": resp.data}
urlの中には、SlackのWebhookを入力してください。msgの中身のtext以外のものも適切なものに変えてください。
# publisher.pyimport boto3from os import getenvdef lambda_handler(event, context):try:raise Exception('エラー発生!')except:client = boto3.client('sns')TOPIC_ARN = getenv('SNS_TOPIC')msg = 'テストです'subject = 'てすてす'response = client.publish(TopicArn=TOPIC_ARN,Message=msg,Subject=subject)return response
こちらのコードはclientにSNSを指定し、publishというAPIを使っています。publish APIは名前通りSNSのTopicにメッセージをpublishするAPIとなります。
これで、コードの準備は完了です。それではServerless FrameworkでSNSおよびLambda関数をデプロイしてみましょう!
serverless.ymlを記入する
serverless.ymlの中身は以下となります
service: sns-testprovider:name: awsruntime: python3.8stage: devregion: ap-northeast-1functions:publisher:handler: publisher.lambda_handlerenvironment:SNS_TOPIC: !Ref FailureTopicrole: publishToSnsnotify_to_slack:handler: notify_to_slack.lambda_handlerevents:- sns:arn: !Ref FailureTopictopicName: FailureTopicresources:Resources:FailureTopic:Type: AWS::SNS::TopicProperties:TopicName: FailureTopicpublishToSns:Type: AWS::IAM::RoleProperties:RoleName: PublishToSNSRoleAssumeRolePolicyDocument:Version: '2012-10-17'Statement:- Effect: AllowPrincipal:Service:- lambda.amazonaws.comAction: sts:AssumeRolePolicies:- PolicyName: PublishToSNSPolicyPolicyDocument:Version: '2012-10-17'Statement:- Effect: AllowAction:- sns:*Resource:- !Ref FailureTopic
まずfunctionsで先ほど作成した2つのコードをLambdaにデプロイしています。notify_to_slackの方で、eventsの中にSNSを指定していますが、こちらがLambdaのトリガーイベントとなります。
トリガーとして例えばAPIGWやS3イベントがあると思いますが、そのようなトリガーの設定をこちらのeventsから設定します。
また、resourcesの中でSNSトピックを作成しています。Serverless Frameworkを使ってリソースをデプロイする際にはこちらのresources項目を使います。このように作成したSNSトピックをnotify_to_slackのSNSイベント項目に!Ref FailureTopic
として指定することで、Serverless FrameworkがデプロイしたSNSトピックをデプロイされるLambdaが参照できるようになります。
デプロイしてからpublisher.pyをテストなどで起動してみると、無事Slackに指定したチャンネルにメッセージが飛んでくることが確認できるかと思います。
最後に
Serverless Frameworkはとても便利なデプロイツールですのでどんどん使ってみましょう!特に今回触れたeventsは、イベントドリブンで発火することの多いLambdaにとってとても高頻度で使用される機能ですので、覚えておくと役に立つことが多いかと思います。