AWS SAM を用いて複数のlambda関数をコンテナ開発する
はじめに
lambda関数のローカル開発が便利だったので、記事にしてみました。
目的
プロダクトのAWS Lambda関数が増えるとGUIコンソール上で管理するのが難しくなる。一方でプライベートサブネットでのDB接続機能を具備するような関数の場合、コンテナ化すると毎回イメージを更新しないとLambdaのテスト機能を利用できない。dockerイメージに含ませたくない環境変数の場合、手動で設定が面倒&設定ミスの可能性を0にできない
- 1.コンテナ管理
- 2.テスト機能をローカルでも実行可能
- 3.lambda関数自体の設定を自動化(デプロイの自動化)
上記を目指して、AWS SAMを勉強した内容を記録する
やりたいこと(完成系)
- コードをgitで管理
- 環境は同一のdockefile(読者様の求められる要件次第だとは思います。)
- LambdaリソースをcloudFormationテンプレートで管理
- テストはメンバーのローカル環境で実施(sam local invoke)
上記を満たすように、下記ディレクトリ構造を目指す。
.
└── projects/
├── events
├── lambda-function-001/
│ │ └── app.py(lambda_handler関数を含むもの)
│ └── tests
├── lambda-function-002
├── lmabda-function-003
├── ...
├── lib(共通処理)
├── dockerfile
├── requrements.txt
├── samconfig.toml
└── template.yaml
プロジェクトの開始
まずはAWS SAM CLIをインストールする。公式にインストールページが用意されているので、対応のOSにしたがう。公式サイト
インストールが完了したら,sam init
を対象のディレクトリ上で実行する。
対話的に各種設定が可能だが、もちろんオプションを指定可能。
(例:sam init --base-image amazon/python3.11-base
)
複数のlambda関数で統一のdockerfileを使用する
[結論]
dockerfileで気にすることはない。必要なパッケージをインストールする。
# 共通する処理
FROM public.ecr.aws/lambda/python:3.11 as base
COPY requirements.txt ./
RUN python3.11 -m pip install -r requirements.txt -t .
COPY ./* ./
template.yamlに必要な情報
cloudFormationでlambda関数を構成することになるため、cloudFormationテンプレートを記載する。テンプレート全体ではなく、特に利用頻度が高そうな内容に絞って紹介する。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
python3.11
############################################
# 定数宣言
# yamlで参照するときは、!Ref {変数名}の呼び方にする
# 具体のパラメータの値はsamconfig.tomlのparameter_overridesに渡す
# parameter_overrides = ["BUCKETNAME = hoge"]
############################################
Parameters:
BUCKETNAME:
Type: String
Description: "The name of the S3 bucket"
Resources:
samLambdaDebugPractice001:#関数名のエイリアスを宣言
Type: AWS::Serverless::Function
Properties:
PackageType: Image
ImageConfig:
- "lambda-function-001/app.lambda_handler"
Architectures:
- x86_64
Environment: # Environmentプロパティの正しい形式
Variables:
BUCKET_NAME: !Ref BUCKETNAME
Metadata:
Dockerfile: Dockerfile
DockerContext: ./ # yamlテンプレートファイル視点でdockerファイルが置いてあるdir
DockerTag: python3.11-v1
ImageConfigの設定
今回は統一的なdockerfileを使用しているため、各関数のイメージで実行するべきCMDをdockerfile以外で指定する必要がある。実行するべきlambda_handler関数へのパスを指定する必要がある。
ImageConfig:
- "lambda-function-001/app.lambda_handler"
パラメータや環境変数の設定
[結論]
1.環境変数のKeyに関しては、templates.yamlでParametersを指定する。
2.具体のValueはsamconfig.tomlにparameter_overridesを指定する。
[詳細]
例えば共通する環境変数、デプロイする環境ごとの接頭辞(dev,stg,prod)等をまとめて指定することができる。
Parametersで指定した命名(アンダースコア使用不可)をエイリアスとして、!Ref等で参照することができる。
肝心のParametersの指定値だが、samconfig.tomlに記述する。
samconfig.tomlでは環境変数のvalue部分をparameter_overridesをリストで宣言する。
parameter_overridesを
- [dev.deploy.parameters]
- [dev.local_invoke.parameters]
のすべてに記載するようにしよう。(環境ごとに設定分けられるのは便利だね。)
parameter_overrides = ["KEY=VALUE","KEY=VALUE"....]
の形で記載するが、KEYとVALUEの間にスペース入れるとエラー吐くので注意
Parameters:
BUCKETNAME:
Type: String
Description: "The name of the S3 bucket"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Resources:
FunctionName: !Sub "${Prefix}-lambda-function"
Environment: # Environmentプロパティの正しい形式
Variables:
BUCKET_NAME: !Ref BUCKETNAME
[dev.deploy.parameters]
parameter_overrides = ["BUCKETNAME=YOUR BUCKET NAME"]
[dev.local_invoke.parameters]
parameter_overrides = ["BUCKETNAME=YOUR BUCKET NAME"]
環境ごとのパラメータの設定
プロダクト開発において、開発、検証、本番の3環境で運用することが多いと思う。それぞれの環境で求められるパラメータのvalueが異なる場合、samconfig.tomlの接頭辞として、それぞれ設定することができる。
接頭辞の指定はsamコマンド実行時のオプションとして-config-env
を指定する必要がある。
[dev.deploy.parameters]
~~~
[dev.local_invoke.parameters]
~~~
[stg.deploy.parameters]
~~~
[stg.local_invoke.parameters]
~~~
[prod.deploy.parameters]
~~~
[prod.local_invoke.parameters]
~~~
編集したyamlの文法エラーがないかどうか確認する
あまりyamlに書きなれていないと、余計な空白等によるエラーが発生します。
sam validate --lint
で文法チェック可能ですが、不適切な箇所まで指定してくれないので、vscodeのlintツール使いましょう。
AWS Cloudformation用のVSCode設定
作ったSAMテンプレートをベースにビルドする
sam build --debug
でビルドする。
ログを出力してくれるので、デバッグが行いやすい。
buildが完了すると以下が実行可能になる。
- sam local invoke
ローカル環境にAWSリソース(今回だとlambda関数)を作成し、実行結果を出力する。 - sam deploy --guided
新規にデプロイ
SAM local invokeでlambda関数全体としてのテストをする。
sam local invoke {template.yamlで指定した関数のエイリアス名}
でlambda関数としてローカル実行できる。
オプションに関しては一部紹介する
- --profile
- 検証するアカウントを切り替え可能
- -config-env
- samconfig.tomlで指定した環境名を選択できる
- -e
- jsonに保存した内容をリクエストに含めて、lambda関数を検証可能。-eのあとにjsonファイルへのパスを指定する。
例: sam local invoke {template.yamlで指定した関数のエイリアス名} --profile {プロファイル名} --config-env dev
この時タイムアウトエラーが連発するようなら、Docker desktopの「Expose daemon on tcp://localhost:2375 without TLS」が有効になっているか確認すること
SAM deploy
sam deploy --guided
で対話形式にデプロイできる。
1つのリポジトリから複数環境にデプロイも可能なので、下記コマンドでdev,stg,prod環境それぞれへのデプロイも可能である。
sam deploy --profile {YOUR PROFILE NAME} --config-env {指定の環境名}--stack-name {任意のstack名}
SecurityErrorが出る場合
対話形式の際に下記の設問にyで答える必要がある。デフォルト回答Noで回答すると、Error: Security Constraints Not Satisfied!エラーが出る。
samLambdaDebugPractice001 has no authentication. Is this okay? [y/N]
参考
SAMで環境ごとに異なるパラメータを設定してみた
AWS SAM でパラメータを扱う方法
SAM CLI を使ってできるだけローカルでテストしてからデプロイする
Discussion