LoginSignup
7
3

More than 5 years have passed since last update.

AWS LambdaのCI環境について ~表参道.rb #24~

Last updated at Posted at 2017-07-06

自己紹介

@ebihara99999


ところで

私事ですが明日結婚します。
めでたいLTです



発表すること

  • AWS Summit 2017でのt_wadaさんの講演がすごく参考になったので、AWS Lambdaで自動テストを行う仕組みを導入した
  • その際の知見やハマりどころを発表する

t_wadaさんの講演?

Testable Lambda: Working Effectively with Legacy Lambda

公式Lambdaチュートリアルを例として扱い、Lambda開発で自動テストを導入していくお話

スライド:
https://speakerdeck.com/twada/testable-lambda-working-effectively-with-legacy-lambda

動画: https://www.youtube.com/watch?v=C0zNc4bdWhY


t_wadaさんの講演?

拙記事もご覧ください(ご本人にはてぶして頂いて嬉しい)。


講演内容

AWS公式のLambdaチュートリアルのコードをリファクタリングしながらテストを書いていく

  • ローカル環境でのテスト
    localstack超便利
  • 本番環境相当のテスト AWS SAMを利用したCI環境の構築 ← 今日はこれについて
  • production環境でのサービス間のテスト

題材

構成としては、本家のLambdaチュートリアルと同様。

srcBucketにファイルが格納されたら何らかの処理を行い、結果をdestBucketに吐き出す。

lambda-flow.png

引用: http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/with-s3-example.html


SAM(Serverless Application Model)とは

  • サーバレスアーキテクチャ構築フレームワーク
  • CloudFormationの拡張
  • サーバーレスアプリケーションのリソースに最適化された専用のリソースタイプを定義できる
  • 本家にサンプル色々ある

AWS Summit 2017での吉田さんの講演がとても参考になります
動画: https://www.youtube.com/watch?v=ZDvcCY8QRWA

参考:
https://aws.amazon.com/jp/about-aws/whats-new/2016/11/introducing-the-aws-serverless-application-model/
http://dev.classmethod.jp/cloud/aws/aws-serverless-application-model/


実現したいCI環境

push後ブランチごとに実際のAWSサービスを利用した環境を立ち上げて、テストが終わったら使用した環境を削除したい(CircleCI使用)。

  • スタック名をブランチを含む形にしたい
  • テストで使用するリソース(今回はS3のバケット)も、ブランチ名を含む命名規則とし、想定可能な名称にしたい

リソースの名称を指定しないと下記のようにユニークな値を振ってくれるが、それではテストで利用できない(「hogeバケットにファイルが存在すること」など)。

例
arn:aws:iam:*******:role/lambda-tutorial-ProcessorFunctionRole-1GFMCGG1ORHNM

実現したいCI環境

例として、

  • CloudFormationスタック名
    ${プロジェクト名}-${ブランチ}
例: lambda-tutorial-develop
  • Sourceバケット名
    ${プロジェクト名}-\${ブランチ}-source
例: lambda-tutorial-develop-source

などなど


実現したいCI環境

後掃除もしっかり

  • S3のバケットはオブジェクト(ファイル)が存在している場合は消せないので、delete-stackを実行する前にs3バケット内のオブジェクトを削除しておく必要がある

具体的な設定(CircleCI編)

CircleCIの環境変数

  • PROJECT_NAME: lambda-tutorial
  • REGION
  • S3_BUCKET: CloudFormationのソース置き場
  • CIRCLE_BRANCH: CircleCIで保持している環境変数。ブランチ名を格納している

具体的な設定(CircleCI編)

circle.yml

machine:
  timezone: Asia/Tokyo
  node:
    version: 6.1.0
dependencies:
  override:
    - sudo pip install awscli
    - npm install
  post:
    - aws configure set region $REGION
test:
  pre:
    - aws cloudformation package --template-file app-spec.yml --output-template-file app-spec.deploy --s3-bucket $S3_BUCKET_NAME
    - aws cloudformation deploy --template-file app-spec.deploy --stack-name "${PROJECT_NAME}-${CIRCLE_BRANCH}" --capabilities CAPABILITY_NAMED_IAM 
  override: 
    - mocha test/large/index-test.js --timeout 10000
  post:
    - aws s3 rm --recursive s3://"${PROJECT_NAME}-${CIRCLE_BRANCH}"-source
    - aws s3 rm --recursive s3://"${PROJECT_NAME}-${CIRCLE_BRANCH}"-dest
    - aws cloudformation delete-stack --stack-name "${PROJECT_NAME}-${CIRCLE_BRANCH}"
deployment:
  production:
    branch: master
    commands:
      - aws cloudformation package --template-file app-spec.yml --output-template-file app-spec.deploy --s3-bucket $S3_BUCKET_NAME
      - aws cloudformation deploy --template-file app-spec.deploy --stack-name "${PROJECT_NAME}" --capabilities CAPABILITY_NAMED_IAM

ポイント(CircleCI編)

  • --capabilities CAPABILITY_NAMED_IAMつけないとダメ
  • CloudFormationへデプロイ時に--stack-name "${PROJECT_NAME}-${CIRCLE_BRANCH}"のように、stack名にブランチ名を含めてしまうこと

SAM(CloudFormation)のテンプレートでブランチ名を取得するよりCircleCIで取得する方がはるかに楽。

test:
  pre:
    - aws cloudformation package --template-file app-spec.yml --output-template-file app-spec.deploy --s3-bucket $S3_BUCKET_NAME
    - aws cloudformation deploy --template-file app-spec.deploy --stack-name "${PROJECT_NAME}-${CIRCLE_BRANCH}" --capabilities CAPABILITY_NAMED_IAM

ポイント(CircleCI編)

  • S3バケット内にオブジェクトが残っているとdelete-stackできないので、先にオブジェクトを削除しておく
post:
    - aws s3 rm --recursive s3://"${PROJECT_NAME}-${CIRCLE_BRANCH}"-source
    - aws s3 rm --recursive s3://"${PROJECT_NAME}-${CIRCLE_BRANCH}"-dest
    - aws cloudformation delete-stack --stack-name "${PROJECT_NAME}-${CIRCLE_BRANCH}"

設定(SAM編)

app-spec.yml

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: A function that is triggered off an upload to a bucket. It does something to the uploaded file and put the proccessed file to another bucket. 
Resources:
  ProcessorFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: nodejs6.10
      CodeUri: ./
      Timeout: 40
      Policies: AmazonS3FullAccess
      Environment:
        Variables:
          STACK_NAME: !Sub "${AWS::StackName}"
      Events:
        ImgUpload:
          Type: S3
          Properties:
            Bucket: !Ref SourceBucket
            Events: s3:ObjectCreated:*
  SourceBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub "${AWS::StackName}-source"
  DestinationBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub "${AWS::StackName}-dest"

ポイント(SAM編)

  • スタック名の取得 CloudFormationの擬似パラメータで、!Sub "${AWS::StackName}"でスタック名を取得できるので、こちらを利用する。

デプロイ時にスタック名にブランチ名も含めて渡しているのでapp-spec.ymlではブランチ名について考慮する必要はない。


その他はまりどころ

  • ブランチ名はハイフンを使うこと

CloudFormationのスタック名はアンダーバーを使えない。
スタック名: lambda-tutorial-update_sam_configurationはinvalidになってしまう


触れられなかったお役立ち資料

SAMの概要から好ましいディレクトリ構成、CIパイプラインの構築まで幅広く非常に詳しく説明されています。 

私の設定ではディレクトリ構成やLambdaパッケージに含むファイルの選別が雑なところがあるので、こちらを参考にして直していきたいと思います。


最後に

ご清聴ありがとうございました

7
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3