Lambdaをコンテナイメージで実行するメリット
従来のLambdaではZIPファイルをアップロードする形でZIPパッケージは解凍後に250Mが上限というような制限がありました。
コンテナイメージを使えるようになったことで、Lambda関数を最大10GBのコンテナイメージとしてパッケージ化し、デプロイできるようになりました。
またローカルで動かしたものをそのままLambda上で動かせるというのもメリットだと思います。
事前に大容量ファイルをコンテナイメージ内に含めることができるというのも良い点です。
私が今回コンテナイメージのLambdaを使ったのもこれが実現できることが理由でした。
詰まったポイント
コンテナイメージでLayer(Extension)を使う
通常LambdaではLayerを使用する際にコンソール画面から選択したりすることで簡単に指定することができましたが、コンテナイメージを使った場合にはこのような方法では実現できません。
使用するLayerのバイナリをコンテナイメージの/opt/extensions
配下に含めることで実現できます。
Lambda は
コンテナイメージ内でLambda レイヤーと拡張機能を動作させる/opt/extensions
ディレクトリを検索し、見つかった全ての拡張機能の初期化を開始します。拡張機能は、バイナリまたはスクリプトとして実行可能である必要があります。関数コードディレクトリは読み取り専用であるため、拡張機能は関数コードを変更できません。
Parameter and Secret Lambda Extensionを使う場合を考えます。
まずはExtensionのバイナリを取得します。
Parameter and Secret Lambda ExtensionのARNは公式ドキュメントに記載されており、東京リージョンは以下になります。
arn:aws:lambda:ap-northeast-1:133490724326:layer:AWS-Parameters-and-Secrets-Lambda-Extension:4
arn:aws:lambda:ap-northeast-1:133490724326:layer:AWS-Parameters-and-Secrets-Lambda-Extension-Arm64:4
以下のコマンドでzip形式のファイルをダウンロードします。
今回はarm64のLambdaを使うためArm64の方をダウンロードします。
curl $(aws lambda get-layer-version-by-arn --arn arn:aws:lambda:ap-northeast-1:133490724326:layer:AWS-Parameters-and-Secrets-Lambda-Extension-Arm64:4 --query 'Content.Location' --output text) --output layer.zip
ダウンロードしたzipを使ってDockerfileでコンテナイメージを作成します。
FROM public.ecr.aws/lambda/python:3.9 as layer
RUN yum install -y unzip
RUN mkdir -p /opt
ADD layer.zip ./
RUN unzip layer.zip -d /opt
###############################################
FROM public.ecr.aws/lambda/python:3.9
COPY ./requirements.txt ${LAMBDA_TASK_ROOT}
ENV HNSWLIB_NO_NATIVE=1
RUN pip install -r requirements.txt
WORKDIR /opt/extensions
COPY --from=layer /opt/extensions .
WORKDIR ${LAMBDA_TASK_ROOT}
COPY app.py ${LAMBDA_TASK_ROOT}
CMD ["app.lambda_handler"]
まずLayer用のステージでダウンロードしたParameter and Secret Lambda Extensionのバイナリのzipを/opt
に展開します。
そして最終的に作成されるイメージの/opt/extensions
にlayerステージで展開した/opt/extensions
をコピーします。
これでParameter and Secret Lambda Extensionが使えるようになったのであとはLambda関数の中で実際にSecret Managerの値を取得します。
サンプルコード
def get_secrets():
end_point = 'http://localhost:2773/secretsmanager/get'
secret_key = os.environ['SECRET_KEY']
url = f'{end_point}?secretId={secret_key}'
headers = {
'X-Aws-Parameters-Secrets-Token': os.environ['AWS_SESSION_TOKEN']
}
res = requests.get(url, headers=headers)
res.raise_for_status()
secret_string = json.loads(res.text)['SecretString']
SAMで複数関数のデプロイ
SAMで複数のLambda関数をデプロイする際に、テンプレートでImageUri
を指定しているのに1つのリポジトリ(ECR)にプッシュされてしまいました。
原因としてはSAMの理解が浅かったというところになりますが、samconfig.toml
のimage_repositories
に各関数のプッシュ先のリポジトリを指定してあげることで解決しました。
samconfig.toml
とはAWS SAM CLIの設定ファイルであり、samコマンドを使用する際の設定が定義されたファイルです。
sam deploy --guided
コマンドを使用した際にプロジェクトのルートディレクトリに自動生成されます。
以下のようにどのような値を設定するかを聞いてくるので適切な値を設定します。
以下のような内容のファイルが生成されます。
version = 0.1
[default.deploy]
[default.deploy.parameters]
stack_name = "lambda-default"
s3_bucket = "aws-sam-cli-managed-bucket"
s3_prefix = "lambda-default"
region = "ap-northeast-1"
capabilities = "CAPABILITY_NAMED_IAM"
image_repositories = []
ここのimage_repositoriesに各関数名と格納するリポジトリを紐づけてあげます。
image_repositories = [
"Lambda1={accountId}.dkr.ecr.ap-northeast-1.amazonaws.com/{repositoryName1}",
"Lambda2={accountId}.dkr.ecr.ap-northeast-1.amazonaws.com/{repositoryName2}",
]
このように設定した上で改めてsam deploy
をするとsamconfig.toml
の内容を元にデプロイされるため、各リポジトリに対して関数がデプロイされます。
コメント