のべラボ.blog

謙虚に、臆せず、さぼらずにブログを書く

AWS CloudFormation でスタック作成時 Rate exceeded が出て困った話

先日、Cloud9 の環境を複数作成する必要があったので、AWS CloudFormation のテンプレートを作成してスタックを作成しました。

次のテンプレートはあくまで抜粋ですが、実際使ったテンプレートでは 13 個もの AWS Cloud9 の環境を作成しました。

  Cloud901:
    Type: AWS::Cloud9::EnvironmentEC2
    Properties:
      Name: Cloud9box01
      ImageId: amazonlinux-2-x86_64
      InstanceType: t3.small
      OwnerArn: !GetAtt User01.Arn

  Cloud902:
    Type: AWS::Cloud9::EnvironmentEC2
    Properties:
      Name: Cloud9box02
      ImageId: amazonlinux-2-x86_64
      InstanceType: t3.small
      OwnerArn: !GetAtt User02.Arn

  Cloud903:
    Type: AWS::Cloud9::EnvironmentEC2
    Properties:
      Name: Cloud9box03
      ImageId: amazonlinux-2-x86_64
      InstanceType: t3.small
      OwnerArn: !GetAtt User03.Arn

テンプレート作成後、テストでスタック作成行い、問題がない事を確認したのですが、いざ本番環境で必要な時にスタックを作成してみると、Rate exceeded エラーが出てスタック作成に失敗してしまい、大いに慌ててしまうことになりました。

AWS CloudFormation を使用して多くのリソースを作成時に Rate exceeded エラーが出ることは確かにありうることで、次のドキュメントにも記載があります。

aws.amazon.com

このドキュメントにはいくつかの対処策が記載されていますが、今回は DependsOn 属性を使うことで対処しました。

DependsOn 属性は、本来はリソース間の依存性を考慮し、リソース作成の順番を制御するためのものですが、これを活用すれば スタック作成時に、一気にリソース作成の API を発行せず、順番に作成を行うことで、スロットリングによるRate exceeded エラーを回避できそうです。

docs.aws.amazon.com

また、この方法であればテンプレートの記述の変更だけで対処できます。

まずは、1つ1つ順番に作成するように記載してみました。

  Cloud901:
    Type: AWS::Cloud9::EnvironmentEC2
    Properties:
      Name: Cloud9box01
      ImageId: amazonlinux-2-x86_64
      InstanceType: t3.small
      OwnerArn: !GetAtt User01.Arn

  Cloud902:
    Type: AWS::Cloud9::EnvironmentEC2
    Properties:
      Name: Cloud9box02
      ImageId: amazonlinux-2-x86_64
      InstanceType: t3.small
      OwnerArn: !GetAtt User02.Arn
   DependsOn: Cloud901

  Cloud903:
    Type: AWS::Cloud9::EnvironmentEC2
    Properties:
      Name: Cloud9box03
      ImageId: amazonlinux-2-x86_64
      InstanceType: t3.small
      OwnerArn: !GetAtt User03.Arn
   DependsOn: Cloud902

これにより、Cloud9 の作成は完全に1つづつ行われるので、スロットリングによるRate exceeded エラーは確実に回避できそうです。

しかし、1つづつしか作成できないため、スタック作成が完了するまで時間もかかります。DependsOn 属性はスタック作成時だけでなく、削除時もその順番が考慮されるため、削除も1つづつ行われ、かなり時間がかかってしまいました。

私がテストしたところ、13個の Cloud9 の環境を作成するのに約14分、削除するのに 約20分かかりました。

そこで、DependsOn 属性の指定方法を次のように変更しました。

  Cloud901:
    Type: AWS::Cloud9::EnvironmentEC2
    Properties:
      Name: Cloud9box01
      ImageId: amazonlinux-2-x86_64
      InstanceType: t3.small
      OwnerArn: !GetAtt User01.Arn

  Cloud902:
    Type: AWS::Cloud9::EnvironmentEC2
    Properties:
      Name: Cloud9box02
      ImageId: amazonlinux-2-x86_64
      InstanceType: t3.small
      OwnerArn: !GetAtt User02.Arn

  Cloud903:
    Type: AWS::Cloud9::EnvironmentEC2
    Properties:
      Name: Cloud9box03
      ImageId: amazonlinux-2-x86_64
      InstanceType: t3.small
      OwnerArn: !GetAtt User03.Arn
   DependsOn: Cloud902

要するに、同時に2つづつ作成するように、DependsOn 属性の指定の方法を変えました。

こうすることで、スタック作成の時間は約 7分、削除の時間は約 9分に短縮することができ、現実的な運用として使用できることになりました。

時間短縮を目的に同時並行で作成する数を増やしていくと、またスロットリングによるRate exceeded エラーを引き起こす可能性があるため、同時並行作成数の決定には注意する必要がありますね。

また、並行して CloudTrail で証跡を S3 バケットに保存し、スロットリングのエラー発生後、その API コールの情報を Athenaで検索できるようにしました。機会があれば、その辺りについても、記事にしたいと思います。