エラーの内容
The stack is in an UPDATE_ROLLBACK_FAILED state and can not be updated.
CloudFormationのアップデートをプッシュしたところ、途中で失敗しました。CloudFormationはロールバックを試みましたが、そのロールバックも失敗しました。スタックが凍結状態になり、更新も、クリーンな削除もできず、デプロイを試みるたびに同じエラーが発生します。本番環境が部分的に壊れているか、深夜2時に半分だけ更新されたスタックを前に途方に暮れているかのどちらかでしょう。
発生原因
スタックの更新が失敗すると、CloudFormationは自動的にロールバックを試みます。以下のような場合、そのロールバック自体が失敗することがあります:
- CloudFormation管理外でリソースが手動変更された — スタックは以前の状態に戻そうとするが、現在の状態が一致しない
- ロールバック前にスタック外でリソースが削除された
- 処理の途中でIAM権限が削除され、CloudFormationがリソースを元に戻せなくなった
- 別サービスの依存リソースが遷移状態にある(例:RDSインスタンスが
modifyingステータスのまま)
根本的な原因は常に同じです:CloudFormationがあなたの助けなしにスタックを以前の状態に安全に復元できないのです。
手順を追った修正方法
手順1 — 失敗したリソースを特定する
まず、ロールバック失敗の原因となったリソースを特定します。AWSコンソール → CloudFormation → 対象スタック → イベントタブを開き、最新のUPDATE_ROLLBACK_FAILEDまたはUPDATE_FAILEDイベントを見つけて、そのリソースの論理IDを確認します。
CLIを使う場合は以下を実行してください:
aws cloudformation describe-stack-events \
--stack-name YOUR_STACK_NAME \
--query 'StackEvents[?ResourceStatus==`UPDATE_ROLLBACK_FAILED`].[LogicalResourceId,ResourceStatusReason]' \
--output table
このコマンドで、失敗したリソースとその理由が正確にわかります。典型的な出力例:
MyBucket | Resource does not exist
MyFunction | IAM role not found
手順2 — リソースをスキップしてContinueUpdateRollbackを使用する
ContinueUpdateRollbackは停止したロールバックを再開します。ポイントは--resources-to-skipフラグで、これによりCloudFormationに壊れたリソースをスキップさせ、他のリソースのロールバックをクリーンに完了させることができます。
aws cloudformation continue-update-rollback \
--stack-name YOUR_STACK_NAME \
--resources-to-skip LogicalResourceId1 LogicalResourceId2
手順1で確認した論理IDを使用します。複数のリソースはスペース区切りで指定します。
実際の使用例:
aws cloudformation continue-update-rollback \
--stack-name my-prod-stack \
--resources-to-skip MyS3Bucket MyLambdaFunction
何をスキップすべきか不明な場合は、まずフラグなしで実行してみてください:
aws cloudformation continue-update-rollback \
--stack-name YOUR_STACK_NAME
これにより完全なロールバックを最初からやり直します。ただし、根本的な問題をすでに修正済みの場合のみ有効です(例:コマンド実行前に手動で削除されたリソースを復元した場合)。
手順3 — スキップしたリソースを手動で修正する
リソースをスキップしても元の状態には戻りません。CloudFormationは単にロールバック済みとしてマークして処理を進めるだけです。AWS上のリソースの実際の状態はテンプレートと完全に乖離している可能性があり、それはあなた自身が解決すべき問題です。
対処方法は状況によって異なります:
- スタック外でリソースが削除された場合:AWSで手動再作成し、スタックインポートまたはドリフト検出を使って再同期する。
- スタック外でリソースが変更された場合:手動変更を元に戻すか、現在の実際の状態を反映するようにCloudFormationテンプレートを更新して新しいスタック更新をプッシュする。
- リソースが不要になった場合:次の更新でテンプレートから削除する。
手順4 — 復旧後にドリフトを確認する
ロールバックが完了したら、他の操作を行う前にドリフト検出を実行します:
aws cloudformation detect-stack-drift \
--stack-name YOUR_STACK_NAME
次に結果をポーリングします(検出には通常30〜60秒かかります):
aws cloudformation describe-stack-drift-detection-status \
--stack-drift-detection-id DETECTION_ID
次のデプロイ前にドリフトしたリソースを修正してください。このステップをスキップすると、1週間後に同じ失敗ループに陥ることになります。
ContinueUpdateRollbackが繰り返し失敗する場合
スタックが壊れすぎて段階的な復旧ができない場合があります。そのような場合は削除して再デプロイします。スタックに保持したいリソース(S3バケット、RDSインスタンスなど)が含まれている場合は、事前に保護してください:
# 削除する代わりに特定のリソースをデタッチする
aws cloudformation delete-stack \
--stack-name YOUR_STACK_NAME \
--retain-resources MyS3Bucket MyRDSInstance
--retain-resourcesに指定したリソースは削除されずに残ります。スタックから切り離されるだけです。クリーンなテンプレートで再デプロイした後、保持したリソースを新しいスタックにインポートしてください。
修正の確認
ContinueUpdateRollback実行後、スタックのステータスを確認します:
aws cloudformation describe-stacks \
--stack-name YOUR_STACK_NAME \
--query 'Stacks[0].StackStatus'
UPDATE_ROLLBACK_COMPLETEと表示されれば成功です — スタックは更新前の安定した状態に戻り、新しいデプロイの準備ができています。
まだUPDATE_ROLLBACK_FAILEDが表示されている場合は、手順1に戻ってください。イベントログに、スキップが必要な別のリソースがある可能性があります。
予防策
- **CloudFormationが管理するリソースをコンソールで直接変更しないでください。**手動変更はこのエラーの最大の原因です。何かテストする必要がある場合は、スタック経由で行ってください。
- 本番スタックには削除保護を有効にしてください:
aws cloudformation update-termination-protection --stack-name YOUR_STACK --enable-termination-protection - 更新のたびにチェンジセットを使用してください。
aws cloudformation create-change-setを使えば、実際に変更が実行される前に、置換・削除・変更の内容を正確に確認できます。 - スタックポリシーを追加して、RDSインスタンスやS3バケットなどのステートフルリソースが誤って置換されないよう保護してください。
- **CI/CDで各デプロイ前に
detect-stack-driftを実行してください。**パイプラインのチェック中にドリフトしたリソースを検出するのに数分しかかかりませんが、深夜2時のロールバック失敗中に検出すると数時間かかることになります。

