Serverless FrameworkでLambda + ALBを使う


はじめに

API Gatewayを利用するのであればfunctionsに記載するだけであったが
ALBをLambdaのトリガーとする場合別途ALBを作成する必要がありそうだったのでやってみた

サービス構成

ALB -> Lambda

Lambdaは引数をそのままレスポンスとして返すだけのものを作成。
ALBは2つのパスでのルーティングをそれぞれ同じLambdaへ、それ以外を404とするものを作成。

※事前に用意したもの
- LambdaにつけるIAMロール
- ALBにつけるVPC(のサブネットID2つとセキュリティグループID)

フォルダ構成

.
├── handler.js
└── serverless.yml

Lambdaソースコード

コードは内容には特に関係ないので別になんでもよい

handler.js
module.exports.main = async (event) => {
    return response = {
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(event),
        statusCode: 200
    }
}

serverless.yml

API Gatewayと若干書き方は変わるが
単純にALBをLambdaのAPIとしての口としたいだけなら
ALBとリスナーをresourcesで作成して
functionsでそれに紐づけるだけでよさそう。

serverless.yml
service: alb-lambda-example

provider:
  name: aws
  runtime: nodejs10.x
  region: ap-northeast-1

functions:
  echo:
    handler: handler.main
    role: arn:aws:iam::00000000000:role/iam_role # IAMロールのARN
    events:
      - alb:
          listenerArn: 
            Ref: exampleLoadBalancerListener
          priority: 2
          conditions:
            path: /hello
      - alb:
          listenerArn: 
            Ref: exampleLoadBalancerListener
          priority: 1
          conditions:
            path: /world

resources:
  Resources:
    exampleLoadBalancer:
      Type: AWS::ElasticLoadBalancingV2::LoadBalancer
      Properties:
        Name: alb-lambda-example-alb
        Scheme: internet-facing
        Subnets:
          - subnet-XXXXXXXXXXXXX # サブネットID
          - subnet-YYYYYYYYYYYYY # サブネットID
        SecurityGroups:
          - sg-ZZZZZZZZZZZZZZ # セキュリティグループID
    exampleLoadBalancerListener:
      Type: "AWS::ElasticLoadBalancingV2::Listener"
      Properties:
        DefaultActions:
          - Type: fixed-response
            FixedResponseConfig: 
              ContentType: text/html
              MessageBody: <h1>Not Found</h1>
              StatusCode: 404
        LoadBalancerArn: 
          Ref: exampleLoadBalancer
        Port: 80
        Protocol: HTTP

結果

AWSコンソール上のALBの振り分けルール

作成されたALBのDNSにブラウザでアクセスすると/hello/worldではJSONがレスポンスされそれ以外ではNot Foundページが表示された。

トラブルシュート

sls deployに成功するがLambdaがALBと関連付けられてない

serverless をアップデートすると治るかも