Chalice を CDK でデプロイする際に Stage ごとの Lambda の設定ができなくて困った話
December 21, 2022
先日、Chalice と CDK を使って開発を行ないました。 本記事では、Chalice とは何かという話を簡単に記載して、実際に開発する上で躓いた箇所とその解決策を記載します。
Chalice とは
AWS Chalice とは、AWS によって開発されている AWS 上でサーバーレスアプリケーションを作成するためのオープンソース Python 製フレームワークです。
いくつか思いついた特徴などを箇条書きしてみます。
- AWS Lambda と API Gateway が利用される
- インフラのことをあまり意識せずにアプリケーションの開発に集中できるため、開発期間を短縮できる
- 実際には、Chalice が裏で何を行なっているかや、利用されているインフラを理解していないと、難しい部分はある
- コマンドラインインターフェースから簡単にビルドやデプロイができる
- Terraform や CDK との統合をサポートしている
やりたかったこと
CDK を利用してデプロイする際に、ステージごとの AWS Lambda 関数のメモリサイズやタイムアウトを設定をしようとしました。
CDK でデプロイする際の方法は、以下のドキュメントに記載があります。
https://aws.github.io/chalice/tutorials/cdk.html
stage_config
を指定することで、./runtime/.chalice/config.json
に記載されている設定と統合されると記載があります。
class ChaliceApp(cdk.Stack):def __init__(self, scope: cdk.Construct, id: str, **kwargs) -> None:super().__init__(scope, id, **kwargs)self.dynamodb_table = self._create_ddb_table()self.chalice = Chalice(self, 'ChaliceApp', source_dir=RUNTIME_SOURCE_DIR,stage_config={'environment_variables': {'APP_TABLE_NAME': self.dynamodb_table.table_name}})self.dynamodb_table.grant_read_write_data(self.chalice.get_role('DefaultRole'))
stage_config (dict) – Chalice stage configuration. The configuration object should have the same structure as Chalice JSON stage configuration.
ref: chalice.cdk api doc
困ったこと
Chalice では API ハンドラー以外にも Cloudwatch Events によるスケジュールされた非同期処理を作成できます。
作成した特定の Lambda 関数のタイムアウトとメモリサイズを指定しようとしましたが、以下の設定では反映されませんでした。
アプリケーションのコードのサンプルは下記です。
@app.schedule(Cron(0, 16, "L", "*", "?", "*"))def foo(event, context):print("hello world")
CDK のコードでは下記のように設定しました。
class ChaliceApp(cdk.Stack):def __init__(self, scope, id, **kwargs):super().__init__(scope, id, **kwargs)self.dynamodb_table = self._create_ddb_table()self.chalice = Chalice(self,"ChaliceApp",source_dir=RUNTIME_SOURCE_DIR,stage_config={"environment_variables": {"APP_TABLE_NAME": self.dynamodb_table.table_name},"lambda_functions": {"foo": {"lambda_timeout": 600,"lambda_memory_size": 256,"environment_variables": {"HELLO": "world"},}},},)self.dynamodb_table.grant_read_write_data(self.chalice.get_role("DefaultRole"))
デプロイ後に作成された Lambda を確認すると、設定値ではなくデフォルト値 (timeout: 60 sec, memory size: 128 MB) になっていました。
このあたりは、以下の issue にも記載しました。
Lambda Specific Configuration does not work with CDK · Issue #1998 · aws/chalice
解決方法
ソースコードを確認したところ、どうやら CDK でデプロイする際には、このステージ毎の Lambda 設定が読み込まれていないようでした。
CDK 側で設定できないので、CDK でデプロイされるステージ名で ./runtime/.chalice/config.json
にステージ毎の Lambda 設定を書けば、設定がデプロイ時に反映されます。
例えば、CDK 側で cdkdemo
のアプリ名でデプロイされる場合、下記のようにします。
{"version": "2.0","app_name": "cdkdemo","stages": {"cdkdemo": {"lambda_functions": {"foo": {"lambda_timeout": 200,"lambda_memory_size": 256,"environment_variables": {"HELLO": "world2"}}}}}}
上記、ステージ毎に Lambda の設定を変える必要がない場合は、./runtime/.chalice/config.json
に下記のように記載しておけば、全てのステージに対して設定が適用されます。従って、CDK 側のコードでは Lambda 関数毎に設定することが想定されていない可能性も考えられます (現時点で issue に回答をもらえていないので、真相は不明)。
{"version": "2.0","app_name": "cdkdemo","lambda_functions": {"foo": {"lambda_timeout": 200,"lambda_memory_size": 256}}}
その他コメント
- Chalice 便利ですが、RDS などの他の AWS リソースと連携しようと思った時に IAM Policy など設定する必要があって、Chalice が内部で何をやっているか分かりづらくて、設定で躓きました
- Chalice の commit 履歴 見ると、最近あまり更新されていないので、開発はそんなに活発でなさそうです (2022-12-18 現在、last commit は 2022-09-02)
- サクッと Python でサーバーレスなアプリケーションを開発したい時には Chalice はオススメできます