Serverless Framework Functions プロパティ(1)

前回の記事

今回は serverless.yml の Functions プロパティについてまとめてみたいと思います。ここが Serverless Framework で一番大事なところですね(たぶん)。

基本的には以下のドキュメントを読んでまとめ、思うところを徒然に書いていきます。内容の保証はしません、というか間違ってる可能性も多いにあるので鵜呑みにせず一次情報に当たってください。

www.serverless.com

設定方法(全般)

Provider 継承

  1. provider プロパティで設定した値は全ての関数に継承される。
  2. functions プロパティで設定した値が provider と異なる場合、functions の値で上書きされる。

1の例

provider.runtime = nodejs14.x ですが、functions.hello.runtime = python2.7 となっています。

serverless.yml
provider:
  name: aws
  runtime: nodejs14.x

functions:
  hello:
    handler: handler.hello
    name: ${sls:stage}-lambdaName
    runtime: python2.7

2の例

runtime, memorySize がすべての関数に適用されます。

serverless.yml
provider:
  name: aws
  runtime: nodejs14.x
  memorySize: 512

functions:
  functionOne:
    handler: handler.functionOne

関数定義

関数定義と実コードの関係は functions.<function name>.handler = <file name>.<function(module) name> です。

関数定義

serverless.yml
functions:
  hoge:
    handler: handler.fuga

実コード:Python の場合

handler.py
def fuga(event, context):
  return ""

実コード:JavaScript の場合

handler.js
module.exports.fuga = function (event, context, callback) {};

以下の定義方法が可能です。

  1. functions プロパティには複数の関数を定義することができる。
  2. 関数は別ファイルに外出しすることができる。

1の例

serverless.yml
functions:
  functionOne:
    handler: handler.functionOne
    description: optional description for your Lambda
  functionTwo:
    handler: handler.functionTwo
  functionThree:
    handler: handler.functionThree

2の例

serverless.yml
# serverless.yml
functions:
  - ${file(./hoge-functions.yml)}
  - ${file(./fuga-functions.yml)}
hoge-functions.yml
getHoge:
  handler: handler.getHoge
deleteHoge:
  handler: handler.deleteHoge

権限設定

Lambda にアタッチする IAM ロールの設定は provider.iam.role.statements で設定します。

書き方は IAM ポリシーの記載と同じ書き方なのでなじみやすいですね。また、Resources は CloudFormation の組込関数が利用可能です。ただし、serverless deploy 実行時に Serverless Framework として検証されることはなく、CloudFormation 側で解釈されるので適切に設定する必要があります(実行した後にCloudFormation スタックがこけて間違いに気づくということ)。

serverless.yml
provider:
  iam:
    role:
      statements: # このプロパティに権限を設定
        - Effect: Allow
          Action:
            - dynamodb:DescribeTable
            - dynamodb:Query
            - dynamodb:Scan
            - dynamodb:GetItem
            - dynamodb:PutItem
            - dynamodb:UpdateItem
            - dynamodb:DeleteItem
          Resource: 'arn:aws:dynamodb:us-east-1:*:*'

        - Effect: 'Allow'
          Action:
            - 's3:ListBucket'
          # CloudFormation の組込関数が利用可能。ただしバリデーションされることはないため注意。
          Resource: { 'Fn::Join': ['', ['arn:aws:s3:::', { 'Ref': 'ServerlessDeploymentBucket' }]] }

        - Effect: 'Allow'
          Action:
            - 's3:PutObject'
          Resource:
            Fn::Join:
              - ''
              - - 'arn:aws:s3:::'
                - 'Ref': 'ServerlessDeploymentBucket'
                - '/*'

既存の IAM ロールがある場合には、provider.iam.role にARN 指定ができます。

serverless.yml
provider:
  iam:
    role: arn:aws:iam::YourAccountNumber:role/YourIamRole

IAM 権限の詳細については別ページに記載されています。絶対大事ですが、今回はスルーします(余裕があれば別記事で書きます)。

www.serverless.com

関数 URL

これは、AWS Lambda Function URLs を利用するためのプロパティです。Lambda 単体でも HTTP エンドポイントを作成できる機能ですね。

dev.classmethod.jp

dev.classmethod.jp

利用ケースによっていくつかの定義パターンがあります。

serverless.yml
functions:
  func:
    handler: index.handler
    url: true # HTTP エンドポイントが作成される(CORS なし)
serverless.yml
functions:
  func:
    handler: index.handler
    url:
      authorizer: aws_iam # IAM 認証必須(lambda:InvokeFunctionUrl が Allow であるか)
serverless.yml
functions:
  func:
    handler: index.handler
    url:
      cors: true # CORS設定有で HTTP エンドポイントを作成
serverless.yml
functions:
  func:
    handler: index.handler
    url:
      cors: # CORS設定をカスタムしたい場合
        allowedOrigins:
          - https://url1.com
          - https://url2.com
        allowedHeaders:
          - Content-Type
          - Authorization
        allowedMethods:
          - GET
        allowCredentials: true
        exposedResponseHeaders:
          - Special-Response-Header
        maxAge: 6000 # In seconds

プロパティと CORS ヘッダの対応はドキュメント参照

Docker コンテナイメージを利用した関数

直近で利用しなさそうなので軽く目を通す程度に。。。

  • Serverless は ECR リポジトリを作成するが更新管理は行わない。リポジトリは新しいサービスや関数を初めてデプロイするときにのみ作成される。
  • scanOnPush を指定することで CVE スキャンの設定ができる。
  • イメージ URI を直で指定することが可能。
serverless.yml
provider:
  ecr:
    scanOnPush: true
    images:
      baseimage:
        path: ./path/to/context # docker build が走るディレクトリ?
        file: Dockerfile.dev # Dockerfile を明示的に指定する場合
        buildArgs: # --build-arg
          STAGE: ${opt:stage}
        cacheFrom: # --cache-from
          - my-image:latest
        platform: linux/amd64
      anotherimage:
        # イメージを直で指定
        uri: 000000000000.dkr.ecr.sa-east-1.amazonaws.com/test-lambda-docker@sha256:6bb600b4d6e1d7cf521097177dd0c4e9ea373edb91984a505333be8ac9455d38
  • function 側でイメージを直で指定できるが、handler, runtime プロパティは指定できない。

イメージ内にランタイム設定・ソースコードがあるのでそこはいじれないよということでしょう。

serverless.yml
provider:
  name: aws
  ecr:
    images:
      baseimage:
        path: ./path/to/context
        # 他のプロパティの指定がないので、単に docker build が走って Dockerfile を読みに行く?

functions:
  hello:
    image: 000000000000.dkr.ecr.sa-east-1.amazonaws.com/test-lambda-docker@sha256:6bb600b4d6e1d7cf521097177dd0c4e9ea373edb91984a505333be8ac9455d38
  world:
    image: baseimage

serverless.yaml 側で workingDirectory, entryPoint, command は指定可能なようです。

serverless.yml
service: service-name
provider:
  name: aws
  ecr:
    images:
      baseimage:
        path: ./path/to/context

functions:
  hello:
    image:
      uri: 000000000000.dkr.ecr.sa-east-1.amazonaws.com/test-lambda-docker@sha256:6bb600b4d6e1d7cf521097177dd0c4e9ea373edb91984a505333be8ac9455d38
      workingDirectory: /workdir
      command:
        - executable
        - flag
      entryPoint:
        - executable
        - flag
  world:
    image:
      name: baseimage
      command:
        - command
      entryPoint:
        - executable
        - flag

ちょっと長くなってしまったので続きはまた今度。