/ #Lambda 

【CDK/Python】LambdaLayerでコンテナを指定してビルドする方法

もくじ

こんばんは sisii です。

年末に GoogleAnalytics をざっと見ていたら、地味に LambdaLayer の記事が結構見られていることがわかりました。 この記事、今読んでみるとかなりアップデートが必要な内容でしたので、ちょっとリメイクしようと思います。

前提

LambdaLayerがどういうものか?というのは飛ばしてコードベースに「こんな感じで実装できるよー」という感じで書いていきます。

では 作っていきましょう 👻

まず cdk のコードです。

import pathlib

import aws_cdk as cdk
from aws_cdk import BundlingOptions, DockerImage
from aws_cdk import aws_lambda as lambda_

app = cdk.App()
stack = cdk.Stack(app, "cdk-lambda-layer-python-stack")

# LambdaLayer(これがメインです)
layer = lambda_.LayerVersion(
    stack,
    "layer",
    code=lambda_.Code.from_asset(
        str(pathlib.Path(__file__).resolve().parent.joinpath("runtime/layer")),
        bundling=BundlingOptions(
            image=DockerImage(image="public.ecr.aws/sam/build-python3.9:latest-x86_64"),  # imageを指定してbuild する
            # image=lambda_.Runtime.PYTHON_3_9.bundling_image, # これでもOK
            user="root",
            command=[
                "bash",
                "-c",
                "&&".join(
                    [
                        "cp -aur . /asset-output",
                        "cd /asset-output/python",
                        "pip install -r requirements.txt -t .",
                    ]
                ),
            ],
        ),
    ),
    compatible_runtimes=[lambda_.Runtime.PYTHON_3_9],
)

# Function(LambdaLayerを利用するサンプルのFunctionです)
lambda_.Function(
    stack,
    "function",
    code=lambda_.Code.from_asset(
        str(pathlib.Path(__file__).resolve().parent.joinpath("runtime/function")),
    ),
    runtime=lambda_.Runtime.PYTHON_3_9,
    architecture=lambda_.Architecture.X86_64,
    handler="index.handler",
    layers=[layer],
)

app.synth()

runtimeのディレクトリ構成の説明

今回は下記な構成になっております。

- runtime
    - function
        - index.py
    - layer
        - python
            - hello.py
            - requirements.txt

各要素の説明です。

index.py は動作確認用の Lambda です。

layerが LambdaLayer を実装していくディレクトリになります。基本的にこのフォルダをzipにまとめてLambdaLayerとしてデプロイするイメージです。中身をみてみます。pythonは python のコードを保存するためのディレクトリです。そのまんまですが、このディレクトリ名は AWS で決まっているので固定です。詳細は公式を参照ください。hello.pyは LambdaLayer のカスタムな関数で、requirements.txtは LambdaLayer にインストールしたいライブラリー軍となっております。

次に各々のファイルの中身を以下のようになっております。

def greeting():
    print("Hello !!")
requests==2.28.1
import hello
import requests

def handler(event, context):
    print(requests.get("https://blog.i-tale.jp/").status_code)
    print(hello.greeting())
    return

LambdaLayer のビルド

以前の記事では専用のビルドスクリプトを作っていました。 しかしCode.from_assetを利用すれば、そのへんすべてCDKで巻き取ってくれます。

Code.from_assetには引数でビルドで利用したい image とビルド対象のコードが入ったディレクトリのパスと、ビルドに必要なコマンドを渡せます。

image は探したりDockerFileで自作したりする必要がありますが、公式で良い感じのものがたくさん用意されているので、それを利用すればほぼ問題ないと思います。

ビルドの仕様ですが、コンテナ中でビルド結果を/asset-outputディレクトリ配下に保存する必要があります。cdk はそこからファイルを持ってきて1つの zip にまとめてデプロイしてくれます。 /asset-outputディレクトリは初め空っぽなので、上記のサンプルのように、cp -aur . /asset-outputruntime/layerの中のコードをコピーして、cd /asset-output/pythonで python のディレクトリへ移動して、pip install -r requirements.txt -t .で必要なライブラリー軍を直下にインストール的なことをして良しなに配置してあげます。

デプロイ

下記コマンドでデプロイします。裏でコンテナをダウンロードするので結構時間かかりますのでゆっくり待ちましょう。

cdk -a "python3 app.py" deploy

デプロイが終わったら動作確認で一緒にデプロイしたLambdaを叩いて見ます。

下記な感じのログが出力されました。もうちょいprintに情報入れればよかったですが、とりあえずLambdaLayerのパッケージが無事使えていることが確認できました。

START RequestId: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Version: $LATEST
200
Hello !!
None
END RequestId: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

以上!!削除コマンドはこちら!

cdk -a "python3 app.py" destroy

まとめ

今回はCDKを利用したLambdaLayerのビルドの方法を更新してみました。

Dockerを使わず(裏で使っているが意識して使わない)にCDKだけでビルド環境を作ってビルドできるので楽だなーと思います。

以上です。最後までお読みいただきありがとうございました!!

今回のリポジトリはこちら

https://github.com/sisi100/cdk-lambda-layer-python

Author

Sisii

インフラが好きなエンジニアぶってるなにか