Serverless Framework + StepFunctionsの構成でStateMachineを60個以上作ろうとしたらエラーになったので、暫定対応しました。

serverless-step-functions を使ってステートマシンを大量に定義していたら、デプロイできなくなったときの暫定対応
2020.04.06

はじめに

好物はインフラとフロントエンドのかじわらゆたかです。

件名の通りなのですが、Serverless Framework とそのプラグインであるserverless-step-functionsを用いた環境でStatemachineを60個以上つくろうとするとエラーとなります。 プラグインにプルリクエストを出すことも考えたのですが、実際に開発中の案件で使っているのもあったのでPatchファイルで暫定対応をしたので、その内容を記載したいと思います。

再現と原因

今回の検証は以下の環境で行いました。

$ node --version
v13.12.0

$ sls --version
Framework Core: 1.67.0
Plugin: 3.6.4
SDK: 2.3.0
Components: 2.28.0

serverless-step-functions : 2.17.4

以下のようなServerless Frameworkのyamlファイルを用意しデプロイすると再現ができます。

service: serverless-many-statemachine

provider:
  name: aws
  runtime: nodejs12.x
  region: ap-northeast-1

plugins:
  - serverless-step-functions

stepFunctions:
  stateMachines:
    StateMachine1:
      name: TestStateMachine1
      definition:
        StartAt: HelloWorld
        States:
          HelloWorld:
            Type: Succeed
    StateMachine2:
      name: TestStateMachine2
      definition:
        StartAt: HelloWorld
        States:
          HelloWorld:
            Type: Succeed
中略
    StateMachine59:
      name: TestStateMachine59
      definition:
        StartAt: HelloWorld
        States:
          HelloWorld:
            Type: Succeed
    StateMachine60:
      name: TestStateMachine60
      definition:
        StartAt: HelloWorld
        States:
          HelloWorld:
            Type: Succeed

上記をデプロイしようとすると以下ようなエラーが発生します。

$ sls deploy --aws-profile cm-di-div
Serverless: Packaging service...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Validating template...
 
  Error --------------------------------------------------
 
  Error: The CloudFormation template is invalid: Template format error: Outputs count 61 is greater than max allowed 60
以下省略

書いてあるエラーメッセージのとおりなのですが、Serverless Frameworkが作ったCloudFormationのテンプレートがCloudFormationのOutputs の上限に達してしまったため発生したエラーのようです。

こちらはドキュメントにも以下のように記載がされています。

制限 説明
出力 AWS CloudFormation テンプレートで宣言できる出力の最大数。 60 個の出力

AWS CloudFormation の制限 - AWS CloudFormation

ワークアラウンドとしての対応

Serverless Step Functions プラグインでStateMachineの情報をCloudformationのOutputに記載している箇所は以下になります。

_.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Outputs,
          newStateMachineOutPutObject);

Deployすることを目的とするならばハイライトされている行を削除することでデプロイは行えるようになります。 ですが、そのような対応ですと削除した箇所を忘れたり、別の人がデプロイするといった際にその対応を忘れてデプロイが失敗してしまうと言った事になってしまうかもしれません。 そのためこのOutputの抑制を行うPatchを書いて暫定措置とします。

NoOutputStatemachineARN.patch

--- ./compileStateMachines.js   2020-04-04 15:44:30.000000000 +0900
+++ ./compileStateMachines_noOutputs.js 2020-04-04 15:44:22.000000000 +0900
@@ -243,9 +243,6 @@ module.exports = {
           [stateMachineOutputLogicalId]: stateMachineOutPutObject,
         };
 
-        _.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Outputs,
-          newStateMachineOutPutObject);
-
         return BbPromise.resolve();
       });
     }

あとは上記のパッチを以下な感じで適用することで、デプロイが行えるようになります。

patch -u node_modules/serverless-step-functions/lib/deploy/stepFunctions/compileStateMachines.js < NoOutputStatemachineARN.patch

またPatchを戻す場合は以下のような形になります。

patch -R node_modules/serverless-step-functions/lib/deploy/stepFunctions/compileStateMachines.js < NoOutputStatemachineARN.patch

結論

serverless-step-functions を使って大量のステートマシンを書いている際にデプロイできないってケースに遭遇した際に、 ワークアラウンドではありますがこの方法をとることでデプロイが行えるようになります。