Open16

SES のメール受信に連動する Lambda の開発フローについて考えるスレ

snakasnaka

モチベーション

SES でメールを受信して、バックエンドの Rails アプリケーションに処理を依頼するような構成を考えている。

https://docs.aws.amazon.com/ja_jp/ses/latest/dg/receiving-email-concepts.html#receiving-email-consider-use-case

このような Lambda 関数をどのように開発・テスト・デプロイを含めた開発フローはどのように行うのが良いか?

背景

  • Rails サーバまわりのインフラは Terraform で構築している。
    • リポジトリ構成として、アプリケーションとインフラは分かれている
    • しかし、インフラの中で SES に限っては、たまたま Terraform の管理から外れている
  • チームの構成として、インフラとアプリケーションと分担している状況で、アプリケーションエンジニアのスキル側にはTerraform,AWSにはさほど習熟していない
snakasnaka

ツール・フレームワークの選定

ローカルでのテスト

  • AWS SAM
  • LocalStack
  • Serverless Framework
  • Lambda Runtime Interface Emulator (RIE)

デプロイ

  • AWS SAM
  • AWS CDK
  • Serverless Framework
  • Terraform
  • AWS CLI
snakasnaka

ローカルでのテストについて、環境構築の手軽さから行くと

  1. AWS SAM, Serverless Framework
  2. LocalStack
  3. Lambda RIE

という順番になりそう

手軽さという点では SAM と Serverless Framework は並びそうだけど、最近の Serverless Framework の有料化などの動きを見ると SAM を選択しておいたほうが無難かもしれない。

snakasnaka

デプロイについて

  1. AWS SAM, Serverless Framework
  2. AWS CDK
  3. Terraform
  4. AWS CLI

この順番かな?

AWS CLI は位置からスクリプト組むのが面倒すぎるので、除外

Terraform もインフラとアプリケーションのリポジトリを分けている点や、Lambda 関数のデプロイ自体をアプリケーションエンジニア側にお願いする点からも扱いにくいので除外

Serverless Framework は前述の懸念から除外

残るは AWS SAM と CDK のいずれか

snakasnaka

AWS SAM と AWS CDK を組み合わせた Lambda アプリケーション開発を試す

https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-cdk-getting-started.html

snakasnaka

Bootstraping?

https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping.html

CDK が利用する IAM Role や S3 Bucket などを準備することを Bootstrapping と呼んでいる。

cdk bootstrap aws://{AWS_ACCOUNT}/ap-northeast-1

実行すると CloudFormation に CDKToolkit という stack ができている

含まれるリソースの種類は以下

AWS::SSM::Parameter
AWS::IAM::Role
AWS::IAM::Policy
AWS::ECR::Repository
AWS::S3::Bucket
AWS::S3::BucketPolicy
snakasnaka

CDK アプリケーション

cdk-sam-example ディレクトリを用意して cdk の初期化を行う

cdk init app --language typescript

lib に以下のファイルを用意する

lib/cdk-sam-example-stack.ts
import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';

export class CdkSamExampleStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    new lambda.Function(this, 'MyFunction', {
      runtime: lambda.Runtime.PYTHON_3_9,
      handler: 'app.lambda_handler',
      code: lambda.Code.fromAsset('./my_function'),
    });
  }
}

my_function ディレクトリにLambda 関数本体を用意する (Python)

my_function/app.py
def lambda_handler(event, context):
    return "Hello from SAM and the CDK!"
snakasnaka

Lambda アプリケーションをローカルでテストする

CDK で CloudFormation テンプレートを生成する

cdk synth --no-staging

実行すると以下のような出力が得られる

  MyFunctionXXXXXXXX:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        S3Bucket:
          Fn::Sub: cdk-xxxxxxxx-assets-${AWS::AccountId}-${AWS::Region}
        S3Key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.zip
      Handler: app.lambda_handler
      Role:
        Fn::GetAtt:
          - MyFunctionServiceRoleXXXXXXXX
          - Arn
      Runtime: python3.9
    DependsOn:
      - MyFunctionServiceRoleXXXXXXXX

以下で実行する

sam local invoke MyFunction --no-event -t ./cdk.out/CdkSamExampleStack.template.json
実行結果
$ sam local invoke MyFunction --no-event -t ./cdk.out/CdkSamExampleStack.template.json

        SAM CLI now collects telemetry to better understand customer needs.

        You can OPT OUT and disable telemetry collection by setting the
        environment variable SAM_CLI_TELEMETRY=0 in your shell.
        Thanks for your help!

        Learn More: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-telemetry.html

Invoking app.lambda_handler (python3.9)
Local image was not found.
Removing rapid images for repo public.ecr.aws/sam/emulation-python3.9
Building image.....................................................................................................................................................................................................................................................................................................................................................................
Using local image: public.ecr.aws/lambda/python:3.9-rapid-x86_64.

Mounting /Users/xxxx/xxxx/cdk-test/cdk-sam-example/my_function as /var/task:ro,delegated, inside runtime container
START RequestId: 1ef0893e-8535-4c65-80a9-a764d40d1d92 Version: $LATEST
END RequestId: f983e161-68f8-4551-af98-b3d6ccb20977
REPORT RequestId: f983e161-68f8-4551-af98-b3d6ccb20977  Init Duration: 0.28 ms  Duration: 190.13 ms     Billed Duration: 191 ms Memory Size: 128 MB     Max Memory Used: 128 MB
"Hello from SAM and the CDK!"
snakasnaka

ローカル環境におけるバックエンド(Rails)との連携方法を考える

(TBD)

snakasnaka
snakasnaka

プロジェクトの作成 ( 対象のディレクトリで )

cdk init app --language typescript

Stack の確認

cdk ls

Construct を編集 -> lib/xxx.ts

Cloudformatin テンプレートの作成

cdk synth

差分の確認

cdk diff

デプロイ

cdk deploy