TL; DR
Graviton2 FargateでFargate Spotを使おうとして失敗した後に、テンプレートファイルを元に戻した状態で再度スタック更新しようとすると発生します。
内容
AWSにおけるCloudFormationで、ECSサービスとタスク定義のリソースをGraviton2 Fargateにより作成していました。
その際に発生したエラーと解決策です。
問題
次のようなCloudFormationテンプレートをデプロイしていました。
内容は、ECSサービスとタスク定義をGraviron2 Fargateで起動する、というものです。
Resources:
# 説明に必要な項目のみ抜粋
ECSTaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
RuntimePlatform:
CpuArchitecture: ARM64 # Graviton2であることを表す
RequiresCompatibilities:
- FARGATE # Fargateであることを表す
NetworkMode: awsvpc
MinecraftECSService:
Type: AWS::ECS::Service
Properties:
LaunchType: FARGATE # Fargateであることを表す
TaskDefinition: !Ref ECSTaskDefinition
その後、Fargateの料金対策として全コンテナにFargate Spotを利用してみようと、次のように書換えてデプロイ処理を実行しました1。
Resources:
# 説明に必要な項目のみ抜粋
ECSTaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
RuntimePlatform:
CpuArchitecture: ARM64 # Graviton2であることを表す
RequiresCompatibilities:
- FARGATE # Fargateであることを表す
NetworkMode: awsvpc
MinecraftECSService:
Type: AWS::ECS::Service
Properties:
LaunchType: FARGATE # Fargateであることを表す
TaskDefinition: !Ref ECSTaskDefinition
CapacityProviderStrategy:
+ - CapacityProvider: FARGATE_SPOT
しかし、デプロイがなんか時間がかかるなと思って調査した結果、Graviton2 (ARM64) ではFargate Spotの利用はできないということが判明しました。
Fargate スポットキャパシティープロバイダーは ARM64 アーキテクチャを使用した Linux タスクではサポートされていません。Fargate スポットは X86_64 アーキテクチャの Linux タスクのみサポートします。
AWS Fargate キャパシティープロバイダー - Amazon Elastic Container Service
ということで、デプロイ処理を中断し、最初のファイルに戻して再度デプロイ処理を実行したのですが、ECS Serviceリソースが変更中となったまま、いつまで経ってもデプロイ処理が完了しませんでした。
ECS Serviceの方を見ると、次のようなエラーメッセージが出ていました。
service ${SERVICE_NAME} was unable to place a task.
Reason: Capacity is unavailable at this time.
Please try again later or in a different availability zone.
For more information, see the Troubleshooting section of the Amazon ECS Developer Guide.
なお、リンク先のページを見ても、ドンピシャな解決策はありません。
エラー文を訳せば「デプロイ先リージョンのAZ上でキャパシティーが一時的に確保できない」と読めるため、Fargate用リソースが枯渇したのかな?と判断しました(そんなことあるのか?とも思いましたが)。
しかし、翌日も時間をずらしても、同じエラー文が出てくるだけでした。
Fargate Spot挑戦前のテンプレートファイルとの差分は無く、デプロイ処理の中断後はテンプレートファイルも元に戻っています。
また、タグなどリソースの中身には殆ど関係のない設定を追加してデプロイしようとしても、同様のエラー文で前に進めませんでした。
原因
AWSコンソール上でのECSのページを確認すると、なんとキャパシティーユニットには FARGATE_SPOT
と書かれていました。
なんと、CloudFormationでは消していたはずの設定が残ったままでした。
CloudFormationでは、既定値の設定を上書きしてデプロイ処理を実行した後、元に戻しても既定値が反映されず、上書きされた値でデプロイ処理を実行しようとする挙動が時々見られます(Elastic Beanstalkのオプションとか......)。
しかし今回については、デプロイ処理が完了していないにも関わらず、既にECS側ではリソース設定更新が完了されたために、既定値 (FARGATE) が上書き (FARGATE_SPOT) されてしまい、その後のデプロイも上書きされた値でデプロイ処理を実行しようとしていたのでした。
解決策
次のようにファイルを変更しデプロイしました。
Resources:
# 説明に必要な項目のみ抜粋
ECSTaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
RuntimePlatform:
CpuArchitecture: ARM64 # Graviton2であることを表す
RequiresCompatibilities:
- FARGATE # Fargateであることを表す
NetworkMode: awsvpc
MinecraftECSService:
Type: AWS::ECS::Service
Properties:
LaunchType: FARGATE # Fargateであることを表す
TaskDefinition: !Ref ECSTaskDefinition
CapacityProviderStrategy:
+ - CapacityProvider: FARGATE
これにより、全コンテナをFargateでデプロイするように設定を上書きしました。
その後、ファイルを元に戻して再度デプロイしたら、無事にデプロイが完了しました。
まとめ
エラーにおけるキャパシティーというのは、キャパシティーユニットのことだったのかもしれません。
どちらにせよ、エラー文だけでは判断できませんでしたね。
設定を変更したと思ったら、AWSコンソールで設定値を確認しておくと幸せになれることがあるかもしれません。
-
AWS-SAMを利用していたため、
sam deploy
コマンドを実行したというのが正確なのですが、今回の問題とは直接関係ないため省略しています。 ↩