😊

Serverless FW V3で plugin-split-stacks と iam-roles-per-function が競合した

に公開

Serverless Framework v3を利用したアプリで、デプロイが100%失敗する現象が発生しました。どうやら利用している2つのプラグイン、serverless-plugin-split-stacks と serverless-iam-roles-per-function、に競合が発生する状況が起きていたらしく、その原因と解決方法について紹介します。

発生していた現象

デプロイ失敗率は100%に達しており、最新10回のパイプラインがすべて失敗していました。主なエラー内容は CloudFormation IAM ロールの重複作成エラーという状況でした。

CREATE_FAILED: ExampleIamRoleLambdaExecution (AWS::IAM::Role)
Resource handler returned message: "Resource of type 'AWS::IAM::Role' with identifier 
'example-service-development-example-function-us-east-1-lambdaRole' already exists."

CircleCI MCP を使用してデプロイログを調査する

CircleCI MCP サーバーを使用して、複数の失敗したビルドの詳細なログを段階的に分析しました。まず見つかったエラーは、これらのデータです。

CREATE_FAILED: ExampleLogGroup (AWS::Logs::LogGroup)
User with accountId: [REDACTED] is not authorized to perform CreateLogGroup with Tags. 
An additional permission "logs:TagResource" is required.

この段階では、IAM 権限不足(logs:TagResource)が原因と判断されました。そのため、権限周りの設定を調整したのですが、それでもデプロイエラーが続きました。ログを調査していくと、今度はIAMロールに関するエラーが見つかりました。

CREATE_FAILED: ExampleIamRoleLambdaExecution (AWS::IAM::Role)
Resource handler returned message: "Resource of type 'AWS::IAM::Role' with identifier 
'example-service-development-example-function-us-east-1-lambdaRole' already exists."
(RequestToken: [REDACTED], HandlerErrorCode: AlreadyExists)

IaC ツールで明示的にIAM周りの設定を調整していたわけではないため、この時点でServerless Frameworkのプラグイン、特にCloudFormationスタックの分割やリソースの追加などを行うプラグインが原因である可能性が高いと判断しました。

プラグインの調査を実施する

serverless.yml では、次のような順番でプラグインが設定されていました。

plugins:
  - serverless-plugin-split-stacks    # 1番目
  - serverless-iam-roles-per-function # 2番目

各プラグインのコードとGitHubリポジトリを Cursor に調査させた結果、serverless-plugin-split-stacks の公式 GitHub リポジトリで、まさに同じ問題を報告する Issue #97: Incompatible with iam-roles-per-function plugin が見つかりました。

このIssueによると、以下のような問題が発生しています。

IAM role in root stack gets parameterized because of role inheritance from the nested stack.
With serverless-iam-roles-per-function = 💥, without it = 🌹

The issue is that when you have 80 IAM roles, the root stack becomes bloated and 
the parameterization logic fails.

さらに追いかけていくと、以下のような条件についても言及が見つかりました。

The problem occurs when:
1. serverless-iam-roles-per-function creates individual IAM roles for each function
2. serverless-plugin-split-stacks tries to move resources to nested stacks
3. IAM role references become circular between root and nested stacks
4. CloudFormation fails with "Resource already exists" error

複数のユーザーが回避策を提案しており、その中にはプラグイン順序の変更(今回採用した解決策)、IAM ロールを明示的にルートスタックに保持、カスタム設定で IAM ロールを除外などがあります。

プラグイン作者は問題を認識しているものの、根本的な解決策は提供されていません。これは、両プラグインの設計思想が根本的に競合するためでしょう。

関連する他の Issue の発見

serverless-plugin-split-stacks Issue #68: Circular dependency with IAM rolesserverless-plugin-split-stacks Issue #103: Resource already exists errorsも同様の問題を報告しています。これらの issue も同じような問題を報告しており、プラグイン間の競合が広範囲に影響していることが判明しました。

プラグイン間の競合メカニズム

問題の流れを整理すると、serverless-iam-roles-per-function が関数ごとの IAM ロールを作成し、serverless-plugin-split-stacks がリソースを複数個のネストスタックに分割します。その結果、IAM ロール参照の競合が発生し、同名の IAM ロールが重複作成されることになります。最終的に CloudFormation エラー「Resource already exists」が発生するのです。

プラグインの実行順序の影響

# 問題のある順序(元の設定)
plugins:
  - serverless-plugin-split-stacks    # 先に実行
  - serverless-iam-roles-per-function # 後に実行

この順序により、split-stacks プラグインがリソースを分割した後に、iam-roles-per-function プラグインが IAM ロールを作成しようとして競合が発生していました。

解決策

1. プラグイン実行順序の変更

最も効果的で低リスクな解決策として、プラグインの実行順序を変更しました。

# 修正後の順序
plugins:
  - serverless-iam-roles-per-function # 先に実行
  - serverless-plugin-split-stacks    # 後に実行

既存IAMロールのクリーンアップが必要な場合

プラグインの順序を変更しても、既に作成済みの IAM ロールが残っている場合は、以下のエラーが発生することがあります。

CREATE_FAILED: ExampleIamRoleLambdaExecution (AWS::IAM::Role)
Resource handler returned message: "Resource of type 'AWS::IAM::Role' with identifier 'example-service-development-example-function-us-east-1-lambdaRole' already exists." (RequestToken: [REDACTED], HandlerErrorCode: AlreadyExists)

この場合は、対象の IAM ロールを手動で削除することで解決できます。

# 既存のIAMロールを削除
aws iam delete-role --role-name example-service-development-example-function-us-east-1-lambdaRole

まとめ

今回のケースは、利用しているプラグインの競合という、ある意味開発者エコシステムのあるプロダクトではあるあるの出来事でした。ただ印象的だったのは、ログの調査分析から類似ケースの特定までの作業を、体感として70%くらいが生成 AI や MCP によって実現したことです。

もちろん生成AIが報告した内容から、「この現象であれば、このプラグインが怪しいはずだ」や「(レポートに対して)そんなことは業務フローや開発体制上ありえない。つまり調査の視点かやり方が間違っている」のような判断については自身で行いました。この辺りの生成 AI をどこで・どうやって・どこから活用していくかが、今後の開発生産性や調査の効率化などにつながるのかもしれません。

参考リンク

主要な GitHub Issues

プラグインドキュメント

Serverless Framework 公式ドキュメント

デジタルキューブ

Discussion