AWS Lambda Layersのアップデート手順を確認してみた #reinvent

AWS Lambda Layersのアップデート時の更新手順を確認しました。AWS Lambda Layersの狙い通り、Lambda関数本体のコード修正は不要で、Layerの更新を行なうだけで作業は完了します。
2018.12.13

はじめに

re:Invent 2018で発表されたLambda Layersを利用すると、複数のLambda関数が利用するような共通ライブラリを外出しして管理出来ます。

Lambda関数の運用フェーズでLambda Layerをアップデートしたい時、どのような作業が発生するのか確認してみました。

結論からいえば

  1. Lambda Layerをアップデートし
  2. Lambda関数に紐づくLambda Layerを新しいバージョンに付け替える

だけの想定通りの手順です。

作業の流れ

Lambda のランタイムには Python 3.7 を利用し、Lambda Layer には requests ライブラリを利用します。

以下の流れでLambda Layerで管理する requests ライブラリを 2.20.0 から 2.21.0 にアップデートします

  1. Lambda Layerの登録
  2. Layerを利用するLambda関数を作成
  3. Lambda Layerをアップデート
  4. Lambda関数が利用するLayerを更新
  5. リリース済み Lambda 関数を確認

1. Lambda Layerの登録

まずはrequestsライブラリをLambda Layerとして登録します。

今回はバージョンアップが狙いのため、pip コマンド実行時にバージョンを指定し、バージョン情報をlayerのdescriptionに付与します。

$ pip install -t python requests==2.20.0
$ zip -r requests-2.20.0.zip python
$ aws lambda publish-layer-version \
  --layer-name requests \
  --description "requests 2.20.0" \
  --zip-file fileb://requests-2.20.0.zip \
  --compatible-runtimes python3.6 python3.7
{
    "Content": {
        "Location": "https://awslambda-eu-west-1-layers.s3.eu-west-1.amazonaws.com/snapshots/...",
        "CodeSha256": "rt/94UDWVgczkLtumF8gvSTJAyFT/a/6LFrGcvH/oz4=",
        "CodeSize": 906027
    },
    "LayerArn": "arn:aws:lambda:eu-west-1:123456789012:layer:requests",
    "LayerVersionArn": "arn:aws:lambda:eu-west-1:123456789012:layer:requests:1",
    "Description": "requests 2.20.0",
    "CreatedDate": "2018-12-12T17:58:35.237+0000",
    "Version": 1,
    "CompatibleRuntimes": [
        "python3.6",
        "python3.7"
    ]
}

Lambda関数からLambda Layerを利用する際には、LayerVersionArnを利用します。 このARNを控えておいてください。

2. Layerを利用するLambda関数を作成

このLayerを利用するLambda関数を作成します。

requestsライブラリのバージョンを表示するだけのシンプルな関数です。

test.py

def lambda_handler(event, context):
    import requests
    return requests.__version__

requests Layerを利用するようにLambda関数を登録します。

--layers引数に Layer の ARN を指定します。

$ zip test.zip test.py
...
$ aws lambda create-function \
    --function-name test \
    --runtime python3.7 \
    --role arn:aws:iam::123456789012:role/lambda_basic_execution \
    --handler test.lambda_handler \
    --zip-file fileb://test.zip \
    --layers arn:aws:lambda:eu-west-1:123456789012:layer:requests:1 --region eu-west-1
{
    "FunctionName": "test",
    ...
    "Layers": [
        {
            "Arn": "arn:aws:lambda:eu-west-1:123456789012:layer:requests:1",
            "CodeSize": 906027
        }
    ]
}

動作確認

動作確認します。

$ aws lambda invoke --function-name test output.txt
{
    "StatusCode": 200,
    "ExecutedVersion": "$LATEST"
}
$ cat output.txt
"2.20.0"

期待通り、Layer でパッケージングした requests のバージョンが返ってきています。

リリース

動作確認ができたため、lambda:PublishVersion API でLambda関数をリリースします。

$ aws lambda publish-version --function-name test
{
    "FunctionName": "test",
    "FunctionArn": "arn:aws:lambda:eu-west-1:123456789012:function:test:1",
    …
    "Version": "1",
    …
    "Layers": [
        {
            "Arn": "arn:aws:lambda:eu-west-1:123456789012:layer:requests:1",
            "CodeSize": 906027
        }
    ]
}

初回リリースのため、Version:1 となっています。

3. Lambda Layerをアップデート

ステップ1と同じ要領で requests ライブラリをLayerとしてリリースします。

requests のバージョンを 2.20.0 から 2.21.0 に更新します。

なお Layer リリース時には、新規・更新関係なく lambda:PublishLayerVersion API を利用します。 Layer名をキーにバージョンがインクリメントされます。

$ pip install -t python requests==2.21.0
$ zip -r requests-2.21.0.zip python
...
$ aws lambda publish-layer-version \
  --layer-name requests \
  --description "requests 2.21.0" \
  --zip-file fileb://requests-2.21.0.zip \
  --compatible-runtimes python3.6 python3.7 --region eu-west-1
{
    ...
    "LayerArn": "arn:aws:lambda:eu-west-1:123456789012:layer:requests",
    "LayerVersionArn": "arn:aws:lambda:eu-west-1:123456789012:layer:requests:2",
    "Description": "requests 2.21.0",
    "CreatedDate": "2018-12-12T18:10:34.609+0000",
    "Version": 2,
    "CompatibleRuntimes": [
        "python3.6",
        "python3.7"
    ]
}

Version が 2 に増えています。

lambda:ListLayerVersions API を利用すると、レイヤーのバージョン一覧を確認出来ます。

$ aws lambda list-layer-versions --layer-name requests
{
    "LayerVersions": [
        {
            "LayerVersionArn": "arn:aws:lambda:eu-west-1:123456789012:layer:requests:2",
            "Version": 2,
            "Description": "requests 2.21.0",
            "CreatedDate": "2018-12-12T18:10:34.609+0000",
            "CompatibleRuntimes": [
                "python3.6",
                "python3.7"
            ]
        },
        {
            "LayerVersionArn": "arn:aws:lambda:eu-west-1:123456789012:layer:requests:1",
            "Version": 1,
            "Description": "requests 2.20.0",
            "CreatedDate": "2018-12-12T17:58:35.237+0000",
            "CompatibleRuntimes": [
                "python3.6",
                "python3.7"
            ]
        }
    ]
}

4. Lambda関数が利用するLayerを更新

Lambda 関数本体のコードは変更せず、Layer を先程リリースしたものに更新します。

$ aws lambda update-function-configuration \
  --function-name test \
  --layers arn:aws:lambda:eu-west-1:123456789012:layer:requests:2
{
    "FunctionName": "test",
    …
    "Layers": [
        {
            "Arn": "arn:aws:lambda:eu-west-1:123456789012:layer:requests:2",
            "CodeSize": 903488
        }
    ]
}

動作確認

動作確認します。

$ aws lambda invoke --function-name test output.txt
{
    "StatusCode": 200,
    "ExecutedVersion": "$LATEST"
}
$ cat output.txt
"2.21.0

期待通り、アップデートした Layer のバージョンが返ってきています。

リリース

動作確認ができたため、lambda:PublishVersion API でリリースします。

$ aws lambda publish-version --function-name test
{
    "FunctionName": "test",
    "FunctionArn": "arn:aws:lambda:eu-west-1:123456789012:function:test:2",
    ...
    "Version": "2",
    ...
    "Layers": [
        {
            "Arn": "arn:aws:lambda:eu-west-1:123456789012:layer:requests:2",
            "CodeSize": 903488
        }
    ]
}

アップデート完了です。

5. リリース済み Lambda 関数を確認

Lambda 関数のバージョン一覧を確認

最後に、test 関数のバージョン一覧を確認します。

$ aws lambda list-versions-by-function --function-name test
{
    "Versions": [
        {
            "FunctionName": "test",
            "FunctionArn": "arn:aws:lambda:eu-west-1:123456789012:function:test:$LATEST",
            …
            "Version": "$LATEST",
            …
            "Layers": [
                {
                    "Arn": "arn:aws:lambda:eu-west-1:123456789012:layer:requests:2",
                    "CodeSize": 903488
                }
            ]
        },
        {
            "FunctionName": "test",
            "FunctionArn": "arn:aws:lambda:eu-west-1:123456789012:function:test:1",
            …
            "Version": "1",
            …
            "Layers": [
                {
                    "Arn": "arn:aws:lambda:eu-west-1:123456789012:layer:requests:1",
                    "CodeSize": 906027
                }
            ]
        },
        {
            "FunctionName": "test",
            "FunctionArn": "arn:aws:lambda:eu-west-1:123456789012:function:test:2",
            …
            "Version": "2",
            …
            "Layers": [
                {
                    "Arn": "arn:aws:lambda:eu-west-1:123456789012:layer:requests:2",
                    "CodeSize": 903488
                }
            ]
        }
    ]
}

Lambda関数のバージョンとして

  • $LATEST
  • 1
  • 2

を確認出来ます。

また、Lambda関数のバージョン 1&2 には、それぞれ個別の Layer バージョンが紐付いています。

Lambda関数のそれぞれのバージョンで実行してみます。

Version 1 で実行

$ aws lambda invoke --function-name 123456789012:function:test:1 output.txt
{
    "StatusCode": 200,
    "ExecutedVersion": "1"
}

$ cat output.txt
"2.20.0"

Version 2 で実行

$ aws lambda invoke --function-name 123456789012:function:test:2 output.txt
{
    "StatusCode": 200,
    "ExecutedVersion": "2"
}

$ cat output.txt
"2.21.0"

Layers のバージョンに紐付いたレスポンスがかえってきています。 成功です。

注意事項

Layerリリース時の API

Layer リリース時には、新規・更新関係なく lambda:PublishLayerVersion API を利用します。 Layer名をキーにバージョンがインクリメントします。

バージョン番号

全バージョンを削除したあとで、同じ名前でLayer登録しても、バージョンは1から始まりません。 バージョン3まで利用済みだった場合、バージョン4というように、過去の延長上で採番されます。

Layer の権限設定

Layerはアカウント共有することが可能です。 そのような権限設定はLayerのバージョンに紐付いています。

Layerに権限を設定している場合は、Layer更新時に権限情報も合わせて更新してください。

最後に

Lambda関数の運用フェーズでLambda Layerをアップデートしたい時、どのような作業が発生するのか確認してみました。

AWS Lambda Layersの狙い通り、Lambda 関数本体のコード修正は不要で、以下の様に Layer の更新を行なうだけで作業は完了します。

  1. Layer を更新
  2. (option)Layer の権限を更新
  3. Lambda 関数のLayerを更新
  4. Lambda 関数をpublish

それでは。

参考