Lambdaで実行するaws-sdkのバージョンをLayer機能を使って変更する

Lambdaの実行環境での利用できるaws-sdkのバージョンは、
Javascriptで「AWS SDK for JavaScript – 2.290.0」となっています。

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/current-supported-versions.html

例えば、新しいsdkの機能を使いたい場合、上記のバージョンでは対応していない場合など、
aws-sdkのバージョンを上げたり、バージョンを固定したいときがあると思います。

今回は、Serverless Framework と AWS Lambda の Layer機能を使って実現させます。

### 前提

- Serverlessがインストールされている

```sh
sls --version
  # 1.35.0
```
- `serverless config credentials` または `aws configure` でAWSアカウントの設定済み

```sh
cat ~/.aws/credentials
  # [default]
  # aws_access_key_id = A******************A
  # aws_secret_access_key = c**************************************V
```

- AWSアカウントに適切な権限があること

### Lambda関数の作成

バージョンを確認するためのアプリケーションを作成したいので、serverlessで雛型を作成します。

```sh
sls create -t aws-nodejs -p sample-serverless-app
  # Serverless: Generating boilerplate...
  # Serverless: Generating boilerplate in "/home/ec2-user/sample-serverless-app"
  #  _______                             __
  # |   _   .-----.----.--.--.-----.----|  .-----.-----.-----.
  # |   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --|
  # |____   |_____|__|  \___/|_____|__| |__|_____|_____|_____|
  # |   |   |             The Serverless Application Framework
  # |       |                           serverless.com, v1.35.0
  #  -------'
  # 
  # Serverless: Successfully generated boilerplate for template: "aws-nodejs"
cd sample-serverless-app
```

今回は期待したaws-sdkバージョンが使えることが確認出来ればいいので、
handler.js をaws-sdkのバージョンを返すだけのものに変更します。

```js
'use strict';

const AWS = require('aws-sdk');

module.exports.hello = async (event, context) => {
  return AWS.VERSION;
};
```

serverless.ymlはとりあえずデフォルトのままでOKです。

```serverless.yml
service: sample-serverless-app

provider:
  name: aws
  runtime: nodejs8.10

functions:
  hello:
    handler: handler.hello
```

ではデプロイ。

```sh
sls deploy
  # ...
  # service: sample-serverless-app
  # stage: dev
  # region: us-east-1
  # stack: sample-serverless-app-dev
  # api keys:
  #   None
  # endpoints:
  #   None
  # functions:
  #   hello: sample-serverless-app-dev-hello
  # layers:
  #   None
```

デプロイが終わったら実行。

```sh
sls invoke -f hello
  # "2.290.0"
```

デフォルトのままなので、aws-sdkのバージョンは `2.290.0` を返しています。

### aws-sdkをインストール

以下のディレクトリを作成し、aws-sdkをインストールします。
現時点での最新は 2.3.8 なのでこれを使います。
指定のバージョンを使いたい場合は、`npm install` 時に指定してください。

```sh
mkdir -p layer/nodejs
(cd layer/nodejs; npm install aws-sdk)
  # ...
  # + aws-sdk@2.382.0
  # ...
```

2.3.8がインストールされました。
また、インストール前にディレクトリを作成しましたが、

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-layers.html

の *Including Library Dependencies in a Layer* に制約があるためです。

serverless.ymlも以下のように変更します。

```yml:serverless.yml
service: sample-serverless-app

provider:
  name: aws
  runtime: nodejs8.10

layers:
  sample:
    path: layer

functions:
  hello:
    handler: handler.hello
    layers:
      - {Ref: SampleLambdaLayer}
```

変更点

- layerでlayer名(sample)と、どのディレクトリ配下をlayer機能とするかを指定
- helloファンクションで読み込むlayerを指定
- Refで指定している `SampleLamdaLayer` の命名については、以下を参照
  - https://serverless.com/framework/docs/providers/aws/guide/layers/#using-your-layers

変更が完了したら再度デプロイ。

```sh
sls deploy
  # ...
  # Service Information
  # service: sample-serverless-app
  # stage: dev
  # region: us-east-1
  # stack: sample-serverless-app-dev
  # api keys:
  #   None
  # endpoints:
  #   None
  # functions:
  #   hello: sample-serverless-app-dev-hello
  # layers:
  #   sample: arn:aws:lambda:us-east-1:172612068623:layer:sample:1
```

デプロイが終わったら再度実行。

```sh
sls invoke -f hello
  # "2.382.0"
```

これで期待されたaws-sdkのバージョンが使用できます。
また新しい機能が欲しいので、aws-sdkのバージョンを上げたい！などということがあれば、aws-sdkをアップグレードして、デプロイし直せばいいです。

---

Layer機能で実装してみました。
Layerを使えばLambda関数から切り離し、関数自体の軽量化。複数の関数の共通コードとして利用できます。
是非お試しあれ。