Serverless Framework

Page content

Serverless Framework はAWSやAzure, GCPなど各種クラウドプロバイダのサーバーレスコンポーネントのデプロイを管理するOSSのフレームワークです。 例えばAWSではCloudFormationで頑張るよりはるかに学習コストが低く、開発・デプロイ・運用を軽緑化してくれます。 開発も盛んで新機能への追随も早く、プラグインという形で機能が add-on されることもあります。 また、一部プラグインを活用すれば、オフラインでのエミュレーションも可能になり、実際のクラウドへのデプロイをする前に様々なテストを行うこともできます。

serverless framework を試す

AWS 開発環境

  • secret 等を web console で確認
  • ~/.aws 配下に credentials を置く

Node.js の環境整備

project_dir で, node.js, ndenv のインストール (mac 確認済, win, linux 未確認)

cd /path/to/project_dir/
ndenv install v6.10.3
ndenv local v6.10.3
npm install

Serverless Framework の導入

  • npm install -g serverless
    • shell コマンド使うのでパスが通れば良い (上記のような global install, homedirに入れる, project dir に入れて package.json で頑張る, etc.)
  • cd project_dir

DynamoDB Local, Serverless Offline を使ったローカル開発

  • DynamoDB Local の初回インストール. sls dynamodb install --region <region> --profile <profile> --stage <stage>
  • DynamoDB Local の起動 sls dynamodb start --region <region> --profile <profile> --stage <stage>
    • 起動しっぱなしにしておく必要がある
    • なお、起動のたびに seed (= 初期登録用データ) が登録される. seed は migrations/***.json に記述するようにしてる
  • Serverless Offline の起動 sls offline --region <region> --profile <profile> --stage <stage>
    • 起動しっぱなしにしておく必要がある

この状態で好き勝手に localhost:3000 がAPI Gateway相当になるので、好き勝手 POST,GET,DELETE して開発できるze!

serverless offline 環境特有の注意点

  • region, profile, stage オプションに注意してデプロイしましょう。 local 開発環境だけであれば本来これらオプションは不要なのですが、商用へのデプロイの際にオプション変えるだけで同じようにデプロイできる利便性を考えた結果、都度オプション指定が必要になっちゃいました。 (default 値も指定可能だがオプション値を意識付けするためあえてやってない)

  • sls offline が Lambda にリクエストを転送する時, event.isOffline: true が付与される。これでいろいろ条件分岐しています

    • recursive request を抑制する
    • ログ出力関数も抑制する
  • recursive request や log の確認をしたい場合は、この辺の条件分岐を一時変更するようにしてください。 recursive request 先をどこにするかも要注意。

  • sls remove して sls deploy すると、新しいAPIGWリソースになるため URL が変わる

  • DynamoDB のスキーマに関わるような変更を加えた場合、 table を削除してから作り直す必要がある場合があります

offline の Lambda が本物の AWS サービスと連携する際の credentials profile の注意点 (2019/09/13)

  • deploy された Lambda は serverless.ymliamRoleStatements セクションを見る

  • しかし、 offline ではローカルの default AWS profile を見る!

    However, serverless offline makes use of your local AWS profile credentials to run the lambda functions and that might result in a different set of permissions. By default, the aws-sdk would load credentials for you default AWS profile specified in your configuration file.

  • 対策は2択:

    1. 環境変数 AWS_PROFILE を宣言 (しばらくはこれやるしか無いなぁ)
      AWS_PROFILE=<profile> serverless offline
      
    2. 何かしらコードに書く
  • この issue で、 sls deploy みたく --profile オプション作ってそこから読み込んでほしいという要望が上がっているので僅かな望みをかけて watching: Support for AWS credential profiles

test, coverage

test framework は mocha を採用しています. カバレッジの計測には istanbul を使っています. 個人的に Ruby でなれた rspec, simple-cov に似ているから使ってるって感じです。

  • package.json に以下のように script として登録している

    "scripts": {
      "test": "mocha -R spec test/index.test.js",
      "test-watch": "mocha -wR spec test/index.test.js",
      "test-cov": "istanbul cover --print both _mocha -- test/index.test.js"
    }
    
  • 実行コマンド: scripts に登録しているので簡単

    npm run test ※単発実行
    npm run test-watch ※変更が保存されるたびに実行
    npm run test-cov ※カバレッジ計測
    
  • 常にテストを走らせながら開発できるので -w (watch) は非常に便利ですね。

  • テストの内容

    • api を叩いているというより、直接 Lambda 関数の入出力をテストしています。 APIを実際に叩く形式にしてもいいかも。
  • カバレッジ

    • index.html が生成されるのでそれをブラウザで開けば大丈夫

AWS へのデプロイ: APIGW, Lambda, DynamoDB, CloudWatch

  • その前に: IAM 設定

    • cloudFormation 使うがそのままだと権限が足りない。以下のカスタムポリシーをJSONから作って user に割り当てる (ちなみに反映から数秒は待ちが必要). なお、 serverless.yml に書き込めばいいとも思ったが、 sls deploy 自体が CloudFormation 経由だからだめ.
      {
          "Version": "2012-10-17",
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": [
                      "cloudformation:DescribeStacks",
                      "cloudformation:DescribeStackEvents",
                      "cloudformation:DescribeStackResource",
                      "cloudformation:DescribeStackResources",
                      "cloudformation:CreateStack",
                      "cloudformation:ValidateTemplate",
                      "cloudformation:UpdateStack",
                      "cloudformation:GetStackPolicy",
                      "cloudformation:ListChangeSets",
                      "cloudformation:ListStacks",
                      "cloudformation:DeleteStack"
                  ],
                  "Resource": "*"
              }
          ]
      }
      
  • いよいよデプロイ。 region, profile, stage オプションに注意してデプロイしましょう。

    sls deploy --region <region> --profile <profile> --stage <stage>
    
  • CloudFront を使うなら、 origin として指定する APIGW の URL を, デプロイしたものに。

DynamoDB のオートスケーリング

serverless frameworkではデフォルトでは autoscaling を disable してしまう! DynamoDB コンソールから設定していたときは default enabled だったから油断していた…

  • 対策: serverless framework でオートスケーリングを有効化する
    • serverless-dynamodb-autoscaling を導入する. 公式読めばかんたーん. npm install と serverless.yml の設定だけ。

Lambda の timeout

Lambda 関数の実行タイムアウトはデフォルトでは 6秒. serverless では 2018/06月時点では 3 秒がデフォルト. serverless.yaml で設定可能!

sls rollback

  • sls deploy list で戻りたい deployment の timestamp を確認し、 sls rollback -t <timestamp> で rollback する。過去に戻ってしまった後も、そこより新しい deployment は維持されるから心配なく行き来できます。
  • 完全削除: CloudFormation web console からスタックの削除は、せず、 sls remove コマンドから消すが吉

API-Gateway のロギング

forum でも盛り上がっていて 、 sls の標準対応が望まれる声が募りつつケース close されていない。 暫定?としてプラグインを書いてくれている人がいるので、それを有りがたく使わせてもらう。

  • 手順
    • AWS アカウント x リージョンごとに必要な Web コンソールからの設定
      • Webコンソールにログイン > リージョン選択 > API Gateway 選択 > 設定
      • CloudWatch ログのロール ARN を埋めて 保存
    • serverless.yml で必要な設定

デプロイされたサービスの情報を参照 (sls info)

  • sls info コマンドで一発やで!

    $ serverless info
    
    Service Information
    service: my-serverless-service
    stage: dev
    region: us-east-1
    api keys:
    myKey: some123valid456api789key1011for1213api1415gateway
    endpoints:
    GET - https://dxaynpuzd4.execute-api.us-east-1.amazonaws.com/dev/users
    functions:
    my-serverless-service-dev-hello
    
  • sls info -v だと Stack Outputs もついてくるよ

    $ serverless info --verbose
    
    Service Information
    service: my-serverless-service
    stage: dev
    region: us-east-1
    api keys:
    myKey: some123valid456api789key1011for1213api1415gateway
    endpoints:
    GET - https://dxaynpuzd4.execute-api.us-east-1.amazonaws.com/dev/users
    functions:
    my-serverless-service-dev-hello
    
    Stack Outputs
    CloudFrontUrl: d2d10e2tyk1pei.cloudfront.net
    ScreenshotBucket: dev-svdgraaf-screenshots
    ServiceEndpoint: https://12341jc801.execute-api.us-east-1.amazonaws.com/dev
    ServerlessDeploymentBucketName: lambda-screenshots-dev-serverlessdeploymentbucket-15b7pkc04f98a
    

API-Gateway の URL 確認

  • sls info みろ

  • sls 使ってるなら sls info 見るのが一番だけど、 CloudFormation 管理のものはそちらの API を使っても良い。

    • ベーシックなコマンド: aws cloudformation describe-stacks --profile hogehoge --region fugafuga
    • endpoint url だけを抽出するには jq コマンドで絞る: aws cloudformation describe-stacks --profile hogehoge --region fugafuga | jq '.Stacks[].Outputs[] | select(.OutputKey == "ServiceEndpoint") | .OutputValue'
  • apigateway を直接見る方法: get-rest-apis を打って id を確認すれば類推できる。

    • https://{id}.execute-api.{region}.amazonaws.com/{stage}

Lambda のみデプロイする

AWS CloudFormation を通さず Lambda のデプロイのみを行う。 CloudFormation スタックが示す zip ファイルを単純にスワップするだけらしい。

注意

  • アップロードは速いが、結局 CloudFormation にとっては整合性が取れなくなってしまうため、商用ではおすすめできない。
  • とにかく開発中に早く動かすことを目的とするだけなら有効、という感じらしい… serverless-offline を駆使すればあまり必要なさそうだな。

使い方

  • コマンド

    serverless deploy function -f functionName
    
  • オプション

    • --update-config or -u: Lambda 関連の設定のみをプッシュする (handler, timeout or memorySize, etc.)