🙆

【2022年】とりあえず始めるAWSでLambda開発する時のSAMの設定公開

2022/04/29に公開約6,300字

AWS SAMの設定

どうもみなさん、jey_desun
今回は、Lambdaを開発する時のsamの設定などについて公開したいと思います。
全然高尚なものではないので、とりあえず始めたいみたいな方に使ってもらって各々アップデートしていってもらえたらなと思います。

https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html

さっそくtemplate.yml

https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/sam-specification-template-anatomy.html
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  関数の説明
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 300
Parameters:
  Env:
    Type: String
    AllowedValues:
      - local
      - develop
      - staging
      - production
    Default: local
  MemorySize:
    Type: Number
    AllowedValues:
      - 128
      - 256
      - 512
      - 1024
    Default: 128

Mappings:
  Config:
    dev:
      LogRetentionInDays: 3
      securityGroupIds:
        - sg-xxxx
      subnetIds:
        - subnet-xxxx
        - subnet-yyyy
    stg:
      LogRetentionInDays: 7
      securityGroupIds:
        - sg-xxxx
      subnetIds:
        - subnet-xxxx
        - subnet-yyyy
    prd:
      LogRetentionInDays: 180
      securityGroupIds:
        - sg-xxxx
      subnetIds:
        - subnet-xxxx
        - subnet-yyyy

Resources:
  LambdaFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      FunctionName: !Sub 'FUNCTION_NAME-${Env}'
      Policies:
        - AmazonSSMReadOnlyAccess
        - KMSDecryptPolicy:
            KeyId: "xxxx-yyyy-zzzz"
      MemorySize: !Ref MemorySize
      Tags:
        Name: !Sub "FUNCTION_NAME-${Env}"
        Env: !Ref Env
      Environment:
        Variables:
          SMV_ENV: !Ref Env
          TZ: "Asia/Tokyo"
      VpcConfig:
        SecurityGroupIds: !FindInMap [ Config, !Ref Env, securityGroupIds ]
        SubnetIds: !FindInMap [ Config, !Ref Env, subnetIds ]
      CodeUri: ./
      Handler: ./src/index.handler
      Runtime: nodejs14.x
  LambdaConfig:
    Type: AWS::Lambda::EventInvokeConfig
    Properties:
      FunctionName: !Ref LambdaFunction
      MaximumEventAgeInSeconds: 300
      MaximumRetryAttempts: 0
      Qualifier: $LATEST
  LambdaLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub '/aws/lambda/${LambdaFunction}'
      RetentionInDays: !FindInMap [ Config, !Ref Env, LogRetentionInDays ]
    DependsOn: LambdaFunction
  LambdaLogGroupPermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Sub
        - error-log-notify:${Env}
        - {Env: !Ref Env}
      Action: lambda:InvokeFunction
      Principal: logs.ap-northeast-1.amazonaws.com
      SourceAccount: 'xxxxxxxx'
      SourceArn: !GetAtt LambdaLogGroup.Arn
    DependsOn: LambdaLogGroup
  LambdaLogGroupSubscription:
    Type: AWS::Logs::SubscriptionFilter
    Properties:
      DestinationArn: !Sub
        - エラーログ通知用LambdaのArn:${Env}
        - {Env: !Ref Env}
      FilterPattern: 'ERROR'
      LogGroupName: !Sub '/aws/lambda/${LambdaFunction}'
    DependsOn: LambdaLogGroupPermission

以降、特徴的なところだけ説明します

Parameters

ここには、デプロイする時に可変する値を設定しています。
と言っても結局後にでてくるtomlファイルを環境毎に作ってるので変わることもないんですが
環境が何かと、メモリーサイズくらい

Mappings

ここでは主に環境ごとで不変的な値を設定できるようにしています。
!FindInMap [ Config, !Ref Env, subnetIds ]こんな感じで値を取得することができます。
LogRetentionInDaysは、ログの保持期間をどれくらいにするかです。

Resources

Policies

Policies:
        - AmazonSSMReadOnlyAccess
        - KMSDecryptPolicy:
            KeyId: "xxxx-yyyy-zzzz"

SSMのパラメーターに、DBなどの接続情報を置いてあるので、それを取得できるようにread権限を付与するのと、暗号化して置いてあるので、複合化できるようにKeyIdを設定してあります。

LambdaConfig

LambdaConfig:
    Type: AWS::Lambda::EventInvokeConfig
    Properties:
      FunctionName: !Ref LambdaFunction
      MaximumEventAgeInSeconds: 300
      MaximumRetryAttempts: 0
      Qualifier: $LATEST

↓にもでてくるリトライなどの設定についてです。リトライを想定して作られていない場合は0にしておくのがおすすめです

https://zenn.dev/jey_desun/articles/cd798742414113

LambdaLogGroup

ここからログについてです。Lambdaの関数を作成した後、1回でも実行すればCloudWatchにログが作成されますが、エラー検知やログの保持期間など自分で設定したいと思います。

LambdaLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub '/aws/lambda/${LambdaFunction}'
      RetentionInDays: !FindInMap [ Config, !Ref Env, LogRetentionInDays ]
    DependsOn: LambdaFunction

LambdaLogGroupPermission

  LambdaLogGroupPermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Sub
        - error-log-notify:${Env}
        - {Env: !Ref Env}
      Action: lambda:InvokeFunction
      Principal: logs.ap-northeast-1.amazonaws.com
      SourceAccount: 'xxxxxxxx'
      SourceArn: !GetAtt LambdaLogGroup.Arn
    DependsOn: LambdaLogGroup

LambdaLogGroupSubscription

ここで検知する文字を指定して、通知用のlambdaに通知する
通知用のLambdaも一緒にtemplat.ymlの中に置くことができますが、そうすると別のLambdaを作成する時にややこしくなるので、別出しにしています。

LambdaLogGroupSubscription:
    Type: AWS::Logs::SubscriptionFilter
    Properties:
      DestinationArn: !Sub
        - エラーログ通知用LambdaのArn:${Env}
        - {Env: !Ref Env}
      FilterPattern: 'ERROR'
      LogGroupName: !Sub '/aws/lambda/${LambdaFunction}'
    DependsOn: LambdaLogGroupPermission

Tomlファイル

$sam deployをする時に、デプロイ設定としてtomlファイルを使用します。初回なければ作られますが、僕は環境毎にファイルをあらかじめ作ってます。

例: samconfig.develop.toml

version = 0.1
[default]
[default.deploy]
[default.deploy.parameters]
stack_name = "FUNCTION_NAME-develop"
s3_bucket = "lambda.deploys"
s3_prefix = "ap-northeast-1/develop/"
region = "ap-northeast-1"
profile = "default"
confirm_changeset = true
capabilities = "CAPABILITY_IAM"
parameter_overrides = [
    "Env=develop",
    "MemorySize=128"
]

これをdevelopのところを変えたり、MemorySizeを変えたりしてtomlファイルを環境分作成しています。
そしてデプロイする時は$sam deploy --config-file samconfig.develop.tomlみたいに、選ぶtomlファイルを変えて各環境にデプロイを行なっています。
デプロイもブランチにコミットしたらCircleCIを使って自動でデプロイするようにするように自動化を進めている最中です。

parameter_overrides

parameter_overrides = [
    "Env=develop",
    "MemorySize=128"
]

ここの部分は、template.ymlのParametersの値になります。

結論

ここまであれば、VPC内に置くことができ、エラー検知もしてくれるLambdaを作ることができます。
あとはレイヤーとかを上手く使えるように設定していきたい

Lambdaで開発する時に気を付けることをつらつらと書いてるので参考になれば幸いです。

https://zenn.dev/jey_desun/articles/a50d991c9e012d

Discussion

ログインするとコメントできます