[[AWSメモ]] > * AWS Lambda Layerで共通処理を作成する [#j54e34c6] #mynavi(AWSメモ) #setlinebreak(on); * 目次 [#fd96ea89] #contents -- 関連 --- [[AWSメモ]] ** 概要 [#k0b36e1d] * 概要 [#k0b36e1d] #html(<div style="padding-left:10px;">) これまでは、複数の Lambda で使用するような共通処理を作成する場合、各 Lambda に共通処理自体含める必要があったが、Lambda Layer として共通処理を外出しする事ができるようになった。 https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-layers.html 以降では Lambda Layer の作成 及び 利用方法を記載する。 ※サンプルでは Lambda Layer 及び 呼び出し側の Lambda作成等は全て aws cli で行っているが、もちろんマネージメントコンソール 及び Cloud Formartion でも同様の事は可能。 #html(</div>) ** 準備 [#kef8e87d] * 準備 [#kef8e87d] #html(<div style="padding-left:10px;">) *** aws cli を最新にしておく [#m8fbe102] ** aws cli を最新にしておく [#m8fbe102] #html(<div style="padding-left:10px;">) #myterm2(){{ pip install awscli --upgrade --user }} #html(</div >) *** 作業用ディレクトリ作成 [#vb20d2be] ** 作業用ディレクトリ作成 [#vb20d2be] #html(<div style="padding-left:10px;">) #myterm2(){{ mkdir -p ~/sample_layer1/python cd ~/sample_layer1 }} Lambda Layerとして提供するモジュールは全て、python 配下に配置していく。 例) boto3 を使用する場合 #myterm2(){{ pip install boto3 -t ./python }} #html(</div >) #html(</div >) ** Lambda Layerの作成 [#naaca781] * Lambda Layerの作成 [#naaca781] #html(<div style="padding-left:10px;">) *** ファイル/フォルダ構成 [#vef0f219] ** ファイル/フォルダ構成 [#vef0f219] #html(<div style="padding-left:10px;">) 提供するモジュールは全て、python 配下に配置する必要がある。 https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-layers.html#configuration-layers-path 登録する Lambda Layer(zip) の中身 #myterm2(){{ . ├ python │   └ module1.py │   └ package1 │      └ moduleA.py │      └ moduleB.py }} ※依存モジュールを pip install する場合も python ディレクトリ配下にインストールする事。 #html(</div >) *** 共通機能の作成 [#l40dc599] ** 共通機能の作成 [#l40dc599] #html(<div style="padding-left:10px;">) python/sample1.py #mycode2(){{ # coding: utf-8 def hello(name): return f"Hello {name}!" }} #html(</div >) *** zipファイル化 [#m867c517] ** zipファイル化 [#m867c517] #html(<div style="padding-left:10px;">) #myterm2(){{ zip -r sample-layer1.zip python }} #html(<br /><div class="red" >注意)解凍した時に、直下に python ディレクトリが含まれるように zip化する事。</div>) #html(<div style="margin:0 0 20px 0; padding:5px 40px 10px 10px; background:#ffeeee; border:1px solid #333; display: inline-block;">.<br/>└ python<br/>    └ sample1.py</div>) #html(</div >) *** Lambda Layerを登録 [#i5d2ea0a] ** Lambda Layerを登録 [#i5d2ea0a] #html(<div style="padding-left:10px;">) #myterm2(){{ aws lambda publish-layer-version --layer-name sample-layer1 --description "Sample layer1" \ --zip-file fileb://sample-layer1.zip --compatible-runtimes python3.6 { "LayerVersionArn": "arn:aws:lambda:ap-northeast-1:123456789012:layer:sample-layer1:1", "Description": "Sample layer1", "CreatedDate": "2019-01-01T01:01:01.123+0000", "LayerArn": "arn:aws:lambda:ap-northeast-1:123456789012:layer:sample-layer1", "Content": { "CodeSize": 8062916, "CodeSha256": "SkPmtNrqQiNCT...", "Location": "https://awslambda-..." }, "Version": 1, "CompatibleRuntimes": [ "python3.6" ] } }} ※自分でバージョンの指定は出来ない模様(自動的に採番される) #html(</div >) *** 登録されたか確認 [#rdc6e332] ** 登録されたか確認 [#rdc6e332] #html(<div style="padding-left:10px;">) #myterm2(){{ aws lambda list-layers --compatible-runtime python3.6 { "Layers": [ { "LayerName": "sample-layer1", "LayerArn": "arn:aws:lambda:ap-northeast-1:123456789012:layer:sample-layer1", "LatestMatchingVersion": { "LayerVersionArn": "arn:aws:lambda:ap-northeast-1:123456789012:layer:sample-layer1:1", "Version": 1, "CompatibleRuntimes": [ "python3.6" ], "Description": "Sample layer1", "CreatedDate": "2019-01-01T01:01:01.123+0000" } } ] } }} #html(</div >) #html(</div >) ** 利用側のLambdaを作成 [#gf1a512c] * 利用側のLambdaを作成 [#gf1a512c] #html(<div style="padding-left:10px;">) *** Lambdaの作成(Layerを使用する側の処理) [#td6d11b7] ** Lambdaの作成(Layerを使用する側の処理) [#td6d11b7] #html(<div style="padding-left:10px;">) #myterm2(){{ mkdir ~/use_lambda_layer1 cd ~/use_lambda_layer1 }} #html(</div >) *** Lambda関数を入力 [#r4774c84] ** Lambda関数を入力 [#r4774c84] #html(<div style="padding-left:10px;">) index.py #mycode2(){{ # coding: utf-8 # 利用側は普通にPythonモジュールとして import するだけ。 import sample1 def handler(event, context): message = sample1.hello('Daisuke') return { 'statusCode': 200, 'body': message } }} #html(</div >) *** zipファイル化 [#y894a5d7] ** zipファイル化 [#y894a5d7] #html(<div style="padding-left:10px;">) #myterm2(){{ zip -r use_lambda_layer1.zip . }} #html(<br /><div class="red" >注意)こっちは、直下に python ディレクトリが含まれていない事に注意。(普通のLambda)</div>) #html(</div >) *** Lambdaを登録 [#b678e202] ** Lambdaを登録 [#b678e202] #html(<div style="padding-left:10px;">) #myterm2(){{ aws lambda create-function \ --function-name use_lambda_layer1 \ --runtime python3.6 \ --role arn:aws:iam::123456789012:role/lambda-role1 \ --handler index.handler \ --zip-file fileb://use_lambda_layer1.zip \ --layers arn:aws:lambda:ap-northeast-1:123456789012:layer:sample-layer1:1 }} ※roleは予め作成しておいたもの ※layersには作成しておいた Lambda Layer の arn と バージョン。※形式: ARN:バージョン #html(</div >) *** テスト実行 [#e5a28760] ** テスト実行 [#e5a28760] #html(<div style="padding-left:10px;">) #myterm2(){{ aws lambda invoke \ --invocation-type RequestResponse \ --function-name use_lambda_layer1 \ --region ap-northeast-1 \ --log-type Tail \ outputfile.txt && cat outputfile.txt && echo "" { "LogResult": "U1RBUlQgUmVxdWVzdElk...", "ExecutedVersion": "$LATEST", "StatusCode": 200 } {"statusCode": 200, "body": "Hello Daisuke!"} }} #html(</div >) #html(</div >) ** 補足 [#n7598e89] * 補足 [#n7598e89] #html(<div style="padding-left:10px;">) ***共通処理(Lambda Layer)のバージョンを上げる [#ba7d74db] ** 共通処理(Lambda Layer)のバージョンを上げる [#ba7d74db] #html(<div style="padding-left:10px;">) 共通処理側は処理を変更して publish-layer-version するだけ。(新規登録時と同じ) #myterm2(){{ aws lambda publish-layer-version --layer-name sample-layer1 --description "Sample layer1" \ --zip-file fileb://sample-layer1.zip --compatible-runtimes python3.6 { "LayerVersionArn": "arn:aws:lambda:ap-northeast-1:123456789012:layer:sample-layer1:<span class="red">2</span>", ... バージョンが 2 に上がっている "Description": "Sample layer1", "CreatedDate": "2019-01-01T01:01:01.123+0000", "LayerArn": "arn:aws:lambda:ap-northeast-1:123456789012:layer:sample-layer1", "Content": { "CodeSize": 8062917, "CodeSha256": "QYKmU04K+3...", "Location": "https://awslambda-..." }, "Version": <span class="red">2</span>, ... バージョンが 2 に上がっている "CompatibleRuntimes": [ "python3.6" ] } }} 利用側のLambdaは update-function-configuration で新しいバージョンを指定するだけでOK #myterm2(){{ aws lambda update-function-configuration --function-name use_lambda_layer1 \ --layers arn:aws:lambda:ap-northeast-1:123456789012:layer:sample-layer1:<span class="red">2</span> }} #html(</div >) *** 恐らくパフォーマンス検証は必要 [#d1816869] ** 恐らくパフォーマンス検証は必要 [#d1816869] #html(<div style="padding-left:10px;">) Lambda Layer の登録(publish-layer-version)時に、以下のように表示されている事からも分かるように、 Lambda Layer として作成した共通処理は aws 上の何処か(S3?)にソースが登録されている。 #myterm2(){{ Location": "https://awslambda-..." }} これを、使用側のLambda実行時に動的に取得してLambda に組み込むような仕組みと思われる為、 この Lambda Layer のコンテンツ取得にかかる遅延がどの程度なのか検証が必要かもしれない。 Clodスタート時のイメージ #html(<div style="padding:10px 5px 5px 5px; border: 1px solid #333; display: inline-block;">) #ref(cold-start-image.png) #html(</div>) &br; #TODO(検証結果) &br; #html(</div >) #html(</div >)