Serverless Frameworkで管理しているLambdaのランタイムが(一部)更新されない問題
はじめに
AWS Startup Community主催のイベント「AWS 本当にあった怖い話トーク」に登壇しました。
この記事は、その登壇内容をまとめたものです。
問題
Serverless Framework v3を利用して、AWS LambdaのランタイムをNode.js 18からNode.js 20へ一括更新しようとしました。
しかし、serverless.yml
の provider.runtime
を nodejs20.x
に変更してデプロイしても、一部のLambdaランタイムが更新されないという問題が発生しました。
補足: Serverless Frameworkとは?
Serverless Frameworkは、AWS Lambdaをはじめとするサーバーレスなアプリケーションを簡単に構築、デプロイ、管理するためのオープンソースのツールです。
serverless.yml
または serverless.ts
という単一の設定ファイルにインフラの構成を記述するだけで、フレームワークが裏側でCloudFormationのテンプレートを自動生成し、リソースのプロビジョニングやデプロイを行ってくれます。
Infrastructure as Code (IaC)を実現するツールの一つであり、手動でのインフラ管理の手間を大幅に削減し、開発者がアプリケーションのコードに集中できる環境を提供します。
背景:なぜランタイムが更新されないLambdaが存在したのか
私がこの問題に直面したのは、開発チームで管理している既存のS3バケットにファイルがアップロードされたことをトリガーにして、特定の処理を行うLambda関数を実装する必要があったからです。
Serverless Frameworkでは、serverless.yml
でS3イベントを定義することで、S3とLambdaの連携を簡単に設定できます。
しかし、S3バケットがServerless Frameworkの管理外にあり、すでに存在している場合は、events
の設定に existing: true
というフラグを追加する必要があります。
(参考: https://www.serverless.com/framework/docs/providers/aws/events/s3#using-existing-buckets)
# serverless.yml
functions:
hello:
handler: handler.hello
events:
- s3:
bucket: your-existing-bucket # 既存のバケット名を指定
event: s3:PutObject:*
existing: true # このフラグが重要
このexisting: true
こそが、今回の問題の引き金でした。
このフラグを設定すると、Serverless Frameworkはカスタムリソースと呼ばれる特別なLambda関数を裏側で自動的に生成します。このカスタムリソースは、既存のS3バケットに対して、Lambdaを呼び出すためのイベント通知設定を追加・管理する役割を担っています。
原因
調査を進めた結果、Serverless FrameworkのGitHubリポジトリに同様のissueが報告されていました。
また、このカスタムリソースとして自動生成されるLambdaのランタイムが、Serverless Frameworkのコード内で固定(ハードコード)されていたことも判明しました。
そのため、serverless.yml
のprovider.runtime
でnodejs20.x
を指定しても、他関数のランタイムは更新される一方で、フレームワークが自動生成したカスタムリソースのLambdaは古いランタイムのまま取り残されてしまったのです。
これが、一部のLambdaランタイムが更新されなかった問題の真相です。
解決策
issueにあったコメントを参考にすると、serverless.yml
の resources
セクションで extensions
を使い、影響を受けるカスタムリソースのランタイムを明示的に上書きすることで、この問題を解決できます。
# serverless.yml
service: sls-runtime-test
frameworkVersion: "3"
provider:
name: aws
runtime: nodejs20.x
functions:
hello:
handler: handler.hello
events:
- s3:
bucket: some-bucket
event: s3:PutObject:*
existing: true
resources:
extensions:
CustomDashresourceDashexistingDashs3LambdaFunction:
Properties:
Runtime: nodejs20.x # この指定によりカスタムリソースのランタイムが更新
この設定を適用して再度 serverless package
を実行すると、生成されたCloudFormationテンプレートにおいて、カスタムリソース用Lambdaのランタイムが nodejs20.x
に正しく更新されていることが確認できます。
この状態で再度sls deploy
を実行すると、デプロイは成功し、また問題なく該当Lambdaのランタイムも更新されました。
まとめ
Serverless Frameworkは非常に便利なツールですが、内部的な実装によって意図しない挙動が発生することがあります。
問題が発生した場合は、公式ドキュメントやGitHubのissueを調査することが、迅速な解決に繋がります。
今回の経験を通じて、ツールの内部実装を理解することの重要性を改めて認識しました。