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 エラーが出ることは確かにありうることで、次のドキュメントにも記載があります。
このドキュメントにはいくつかの対処策が記載されていますが、今回は DependsOn 属性を使うことで対処しました。
DependsOn 属性は、本来はリソース間の依存性を考慮し、リソース作成の順番を制御するためのものですが、これを活用すれば スタック作成時に、一気にリソース作成の API を発行せず、順番に作成を行うことで、スロットリングによるRate exceeded エラーを回避できそうです。
また、この方法であればテンプレートの記述の変更だけで対処できます。
まずは、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で検索できるようにしました。機会があれば、その辺りについても、記事にしたいと思います。