はじめに
こんにちは!トモニテで開発を行っている吉田です。 今回は Serverless Framework で作成した Lambda 関数を lambroll に移行しようとしたことについて書きます!
移行検討の背景
昨年、Serverless Framework の v4 がリリースされました。 v4 からはライセンス形態が変更されて、収益の閾値を満たす、あるいは超える組織では有料でサブスクリプションを購入する必要があります。また v3 は 2024 年までのサポートで、クリティカルなセキュリティ問題やバグにしか対応しません。 他にもランタイムのアップデートにも対応していないため、今は大丈夫でもいずれ AWS Lambda のランタイムサポートが切れるため、v3 から v4 へのバージョンアップが必要になります。 www.serverless.com
そこで Serverless Framework v3 を v4 に上げる以外の方法について検討しました。
Serverless Framework からの移行先候補について
1. Pulumi
- 概要: Go や TypeScript などの汎用プログラミング言語で利用できるマルチクラウド対応の IaC ツール
- メリット:
- Go, TypeScript, Python などで記述できる
- ユニットテストが書ける
- 関連リソースもデプロイ可能
- デメリット:
- 料金が発生する可能性あり。規模によっては無料枠に収まるが、料金体系が変更された場合には今回と同様に移行先の検討が必要になる
2. AWS CDK (AWS Cloud Development Kit)
- 概要: Pulumi と同様に汎用プログラミング言語で利用できる AWS 向けの IaC ツール。AWS CloudFormation を通じてインフラストラクチャのリソースをデプロイ。Serverless Framework でデプロイしたスタックから移行できる
cdk migrate
というツールはあるが、懸念事項あり。 - メリット:
- Go, TypeScript, Python などで記述できる
- 関連リソースもデプロイ可能
- 無償で利用可能
- デメリット:
cdk migrate
で移行した場合、構造が最適化されない可能性がある。- 上記のこともあり移行工数多め
3. AWS SAM (AWS Serverless Application Model)
- 概要: Serverless Framework と同様に yaml ベースでインフラ定義を記述して、CLI から操作するツール。AWS CloudFormation を通じてインフラストラクチャのリソースをデプロイする。
- メリット:
- Serverless Framework と同じく yaml ベースでの定義設定
- 関連リソースもデプロイ可能
- 無償で利用可能
- デメリット:
- Serverless Framework よりもプラグインは少なくなる
4. fujiwara/lambroll
- 概要: Lambda 関数をデプロイすることに特化したツール。
- メリット:
- tfstate を参照して連携できる。
- CD の用意あり
- 無償で利用可能
- 社内での利用実績がある。
- デメリット:
- 関連リソースは Terraform で管理する必要がある
5. Terraform + AWS CLI
- 概要: 既存の Terraform でのインフラ管理に便乗するプレーンな手段
- メリット:
- インフラ管理ツールを 1 つにまとめられる(弊社的都合)
- 学習コストは低い
- 無償で利用可能
- デメリット:
- 自動デプロイなどの CD に関してフローを整理する必要がある
学習コストや運用実績などを鑑み今回は fujiwara/lambroll(以下 lambroll)で移行が可能なのか調査を行いました。 (もし移行できたとしても CloudFormation で作成したものを途中で別のツールへ移行して不具合が起きないのか等と懸念事項はありますが今回はその点は考慮せず一旦ライトに実験しました)
Serverless Framework と lambroll の違い
移行にあたり両者の違いは理解しておく必要があります。 Serverless Framework の特徴としては以下が挙げられます。
- Lambda をメインとするインフラリソースをデプロイする
- デプロイは CloudFormation を使用して行われる
一方 lambroll は Lambda 関数のデプロイのみを行い Lambda 関数に関連したリソースをデプロイすることはできません。
lambroll does not,
- Manage resources related to the Lambda function.
- For example, IAM Role, function triggers, API Gateway, and etc.
- Only the function URLs can be managed by lambroll if you want.
- Build native binaries or extensions for Linux (AWS Lambda running environment).
(https://github.com/fujiwara/lambroll より)
移行できるか試してみる
config ファイルを lambroll で作成しそれ以外は変更せずデプロイ
既存関数のダウンロード(LATEST で動作している zip をダウンロードできる)
$ lambroll init --download
ダウンロードすると Lambda 関数の定義となる function.json が作成されるので設定値を調整
デプロイ(ログを詳細に確認したかったので log-level オプションを設定)
$ lambroll deploy --envfile=<環境別の設定ファイル> --log-level=debug
デプロイ時のログを確認すると tag の設定に失敗していました。
2025/02/20 17:14:29 [info] lambroll v1.1.3 2025/02/20 17:14:29 [debug] {"Src":".","Publish":true,"AliasName":"current","AliasToLatest":false,"DryRun":false,"SkipArchive":false,"KeepVersions":0,"Ignore":"","FunctionURL":"","SkipFunction":false,"ExcludeFile":".Lambdaignore","KeepSymlink":false} 2025/02/20 17:14:29 [info] starting deploy function <関数名> 2025/02/20 17:14:30 [info] creating zip archive from . (一部省略) 2025/02/20 17:14:30 [info] updating function configuration ... 2025/02/20 17:14:30 [info] State:Active LastUpdateStatus:Successful 2025/02/20 17:14:31 [info] updating function configuration accepted. waiting for LastUpdateStatus to be successful. 2025/02/20 17:14:31 [info] State:Active LastUpdateStatus:InProgress 2025/02/20 17:14:31 [info] waiting for LastUpdateStatus Successful 2025/02/20 17:14:32 [info] State:Active LastUpdateStatus:InProgress 2025/02/20 17:14:32 [info] waiting for LastUpdateStatus Successful 2025/02/20 17:14:34 [info] State:Active LastUpdateStatus:Successful 2025/02/20 17:14:34 [info] updating function configuration successfully 2025/02/20 17:14:34 [debug] 7 tags found 2025/02/20 17:14:34 [debug] remove tag cloudformation:<tag名> 2025/02/20 17:14:34 [debug] remove tag cloudformation:<tag名> 2025/02/20 17:14:34 [debug] remove tag cloudformation:<tag名> 2025/02/20 17:14:34 [debug] remove tag aws:cloudformation:<tag名> 2025/02/20 17:14:34 [debug] remove tag aws:cloudformation:<tag名> 2025/02/20 17:14:34 [debug] remove tag aws:cloudformation:<tag名> 2025/02/20 17:14:34 [info] removing 6 tags 2025/02/20 17:14:34 [error] FAILED. failed to untag resource: operation error Lambda: UntagResource, https response error StatusCode: 400, RequestID: 6798028d-f699-4508-b000-0ba7b5eab222, InvalidParameterValueException: One or more of your tags had a problem, please ensure none of your tag names start with "aws:", none are empty, and there are no duplicate tags
ただ config の更新は成功していそうです。
2025/02/20 17:14:34 [info] updating function configuration successfully
実際にコンソールで確認すると、S3 に zip ファイルはアップロードされ、Lambda 関数が動作することも確認できました。 ただ、デプロイされたファイルのサイズは Serverless でアップロードしたものより大きくなってしまっていたので、この辺りはちゃんと見直す必要がありそうです。
上記で config ファイルがデプロイできるのが確認できたので試しにランタイムの更新ができるか試したところこちらも問題なくできました。
Lambda 関数の処理内容を変更
config は設定できたので処理内容を変更してみました。ログは先ほどと同様にタグの設定でエラーが出ました。
2025/02/20 18:04:02 [error] FAILED. failed to tag resource: operation error Lambda: TagResource, https response error StatusCode: 400, RequestID: 7e16baf5-4b77-4248-a3c9-5f3d75d13fa0, InvalidParameterValueException: One or more of your tags had a problem, please ensure none of your tag names start with "aws:", none are empty, and there are no duplicate tags
コンソールで確認したみたところ確かに aws:
で始まるタグがありました。タグに関わらず設定値は基本的に既存リソースの設定をダウンロードしたものだったので特に変更はしていませんでしたが aws:
で始まるのがダメならそうじゃないようにすればいいかタグ名を変更した上デプロイしたりタグを設定せずにデプロイしてみましたが、変わらずタグ操作で失敗しデプロイできず...(すでに設定された aws:~
のタグを外すこともできませんでした)
一応 AWS CLI で untag-resource コマンドを実行してみましたがこちらでもタグの変更はできませんでした。
$ aws lambda untag-resource \ --resource arn:aws:Lambda:<region>:<アカウントID>:function:<関数名> \ --tag-keys aws:cloudformation:stack-name \ --tag-keys aws:cloudformation:stack-id \ --tag-keys aws:cloudformation:logical-id An error occurred (InvalidParameterValueException) when calling the UntagResource operation: One or more of your tags had a problem, please ensure none of your tag names start with "aws:", none are empty, and there are no duplicate tags
リソースの serverless.yml を見ても tag を明示的に指定しているところがなかったので調べたところ、 CloudFormation ではプレフィックスaws:
が付いた以下のようなスタックレベルのタグを自動的に作成するとのことでした。
- aws:cloudformation:logical-id
- aws:cloudformation:stack-id
- aws:cloudformation:stack-name
さらに以下の記述もありました。
aws:
プレフィックスは AWS 用に限定されています。このプレフィックスでは、大文字と小文字は区別されません。Key または Value プロパティでこのプレフィックスを使用すると、タグを更新または削除することはできません。
タグのエラーが出る原因が分かりました。 今回の調査では、CloudFormation によって自動的に付与された aws: プレフィックスのタグが原因で、lambroll からのタグ操作が失敗し、Serverless Framework で作成した Lambda 関数を lambroll に移行することは難しいという結論に至りました。
終わりに
Serverless Framework で作成した Lambda 関数を lambroll に移行することはできませんでした。 もし Serverless Framework から lambroll へ乗り換える場合には以下の手順で作業を行う必要がありそうです。
- 既存関数のダウンロード(
$ lambroll init --download
) - 既存の関数と同等の関数ができるように function.json の設定値を調整
- Serverless で作成したリソースを削除
- lambroll で Lambda 関数デプロイ
lambroll は既存の Lambda 関数をダウンロードすることができるので、移行する時のハードルはそこまで高くないのかなと感じました。また lambroll では関連リソースが作成されないため、これについては terraform に移行するなど別で検討が必要になります。 最後まで読んでいただきありがとうございました!