AWS CloudFormationスタックの削除時、削除に失敗する(DELETE_FAILEDになる)リソースは手動で対応しないとスタックの削除ができないのが面倒ですよね。
そんなリソースを含むスタックでも1コマンドでまるごと楽々削除できるCLIツール『delstack』を、OSSで公開しました。

目次
概要
ざっくり言うと以下のようなツールになります。
- 削除に失敗する(DELETE_FAILEDになる)リソースを含むスタックも
- そうでない普通のスタックも
- すべてのリソース含め、1コマンドでスタックまるごと削除できる
↓GitHubリポジトリにスターなど頂けたら泣いて喜びます!
2024年5月にCloudFormationから出た強制削除機能(FORCE_DELETE_STACK)ではスタックを削除するだけで、失敗したリソースはDELETE_SKIPPEDになり残ってしまいますが、delstackではこれらのリソースも含めてスタックを丸ごと削除します。
また、AWS CDK、AWS Amplify、AWS SAM、Serverless Frameworkなど、CloudFormationを内部で使用するIaCツールであれば、どれにも便利に使えます!
特にCDKプロジェクトでは delstack cdk コマンドを叩くだけで、CDKアプリの全スタック(リージョン横断)を、依存関係を考慮しつつ並列削除できます。
特徴
主な特徴を挙げると以下のような機能が揃っています。
- 削除失敗リソース(DELETE_FAILED)を含む、スタック丸ごと強制削除
- スタック間の依存関係を考慮した複数スタックの並列削除
- 対話モードでのスタック検索
- 削除保護リソース・スタックの強制削除
- RETAINリソースの強制削除
- 削除パフォーマンスの最適化(VPC LambdaのVPCデタッチ/ENIの削除など)
- GitHub Actionsサポート
- AWS CDK統合 (CDKリポジトリで
delstack cdkコマンドで全スタック削除)
機能の詳細
強制削除対応リソース
以下は、通常のCloudFormation削除に失敗するリソースでも強制削除出来るリソース一覧です。通常の削除に失敗しないリソースは全てそのまま削除出来ます。
もし未対応リソースがあれば、GitHubにissueを立ててくださると嬉しいです!
| リソース | 詳細 |
|---|---|
| AWS::S3::Bucket | 空でない、またはバージョニングオンのものも含む。 |
| AWS::S3Express::DirectoryBucket | 空でないものも含む、S3 Express One Zone用のディレクトリバケット。 |
| AWS::S3Tables::TableBucket | ネームスペースやテーブルを含む、S3 Tablesのテーブルバケット。 |
| AWS::S3Tables::Namespace | テーブルを含む、S3 Tablesのネームスペース。 |
| AWS::S3Vectors::VectorBucket | インデックスを含む、S3 Vectorsのベクトルバケット。 |
| AWS::IAM::Group | スタック外部のIAMユーザーがアタッチされたものも含む。その場合は、IAMユーザーをデタッチしてIAMグループを削除する(IAMユーザー自体の削除はしない)。 |
| AWS::ECR::Repository | すでにイメージが登録されているもの、EmptyOnDeleteがtrueでないものも含む。 |
| AWS::Backup::BackupVault | すでにバックアップが取得されているものも含む。 |
| AWS::Athena::WorkGroup | 名前付きクエリやPrepared Statementsが登録されているものも含む. |
| AWS::Lambda::Function | Lambda@Edgeのレプリカを含む。Lambda@Edgeのレプリカの削除には時間がかかるため、自動的に削除されるのを待ちます。 |
| AWS::CloudFormation::Stack | これらのリソースを子スタックが持つことで削除に失敗したネスト(子)スタック。子スタック内のDELETE_FAILEDリソースも自動で削除されます。 |
| AWS::CloudFormation::CustomResource | カスタムリソース (AWS::CloudFormation::CustomResource)。SUCCESSを返さないものも含む。 |
| Custom::Xxx | カスタムリソース (Custom::Xxx)。SUCCESSを返さないものも含む。 |
削除前処理
CloudFormation の削除を開始する前に、以下の処理を自動的に行います。
削除保護のチェック
スタック削除が走る前に、リソースごとの削除保護設定を確認します。
-f オプションなしの場合: 削除保護リソースが見つかると終了します。
-f オプションありの場合: 削除保護を自動的に解除して、それらのリソースを含むスタック削除を実行します。
| リソースタイプ |
|---|
| AWS::EC2::Instance |
| AWS::RDS::DBInstance |
| AWS::RDS::DBCluster |
| AWS::Cognito::UserPool |
| AWS::Logs::LogGroup |
| AWS::ElasticLoadBalancingV2::LoadBalancer |
パフォーマンス最適化
スタック内のリソースのうち、通常の削除では失敗しないものの、スムーズな削除のために事前に処理しておくべきリソースがあります。
| リソースタイプ | 詳細 |
|---|---|
| AWS::Lambda::Function | Lambda 関数から VPC 設定を自動的にデタッチし、関連する ENI を並列で削除します。これにより、ENI の削除の際の待ち時間がなくなります。 |
対話モード
対話モード(-i, --interactive)では、対話フローの中でスタックの検索・指定が可能です。また、大文字小文字の区別はしないのでより手軽に検索できます。
まずはスタック名を絞るキーワードを入力します。空でも大丈夫です(全スタックが返ります)。

するとキーワードに一致するスタック一覧が出力されるので、削除したいスタックを選択します。

また、以下のスタックは表示されません。
- ネストスタック: 親スタックは通常、全体として削除されます。子スタックを直接削除する必要がある場合は、対話モードを使用するのではなく、
-sオプションでその名前を指定してください。 - XXX_IN_PROGRESS状態のスタック (例:
ROLLBACK_IN_PROGRESS): 複数のCloudFormation操作を同じスタックで同時に実行しないでください。 - 削除保護スタック:
-fオプションがないと表示されません。-fオプションを付けると、*の接頭辞付きで表示されます。
Force モード
-f, --force オプションを使用すると、通常は削除がブロックされるスタックも削除できるようになります。
- Retain/RetainExceptOnCreate 削除ポリシー: これらのポリシーを持つリソースも強制的に削除されます。
- 削除保護リソース (EC2, RDS, Cognito など): 削除開始前に、削除保護が自動的に無効になります。
- 削除保護スタック: 確認プロンプトの後、削除保護が無効になり、スタックが削除されます。
delstack -f -s dev-goto-01-TestStack
大きなテンプレートの処理
RETAIN リソースを含むスタックで強制モードを使用する際、テンプレートが大きい場合(CloudFormation の直接テンプレートサイズ制限である 51,200 バイトを超える場合)、delstack は自動的に以下を行います:
- アカウント内に一時的な S3 バケットを作成
- 変更されたテンプレートをバケットにアップロード
- S3 テンプレート URL 経由でスタックを更新
- 操作完了後に一時的な S3 バケットを削除
スタック間の依存関係を自動解決する並列削除
複数のスタックを指定した場合、delstackは自動的にCloudFormationスタックの依存関係(OutputとImport経由)を分析し、依存関係に沿ってスタックを並列削除します。
つまり、基本は全てのスタックが並列で削除されますが、依存関係のあるスタック間のみ直列で削除し、依存先のスタック削除が完了したら自動的に依存元のスタックの削除が開始されます。
例: スタック A, B, C, D, E, F と依存関係: C → A (CはAに依存) D → A E → B F → C, D, E 削除順序(逆依存関係): ステップ1: Fを削除(どのスタックもFに依存していない) ステップ2: C, D, Eを並列削除(F完了後) ステップ3: Bを削除(E完了後) ステップ4: Aを削除(CとDの両方が完了後)
CDK統合
delstack cdkサブコマンドは、CDKアプリを合成(または既存のcdk.outを読み込み)し、検出されたすべてのスタックを削除します。Cloud Assemblyのマニフェストを解析し、スタック名・リージョン・依存関係を特定します。
クロスリージョン削除
CDKアプリが複数リージョンにスタックをデプロイしている場合(例: CloudFront用のus-east-1 + メインアプリ用のap-northeast-1)、delstack cdkは自動的に以下を行います:
- Cloud Assemblyマニフェストの
environmentフィールドから各スタックのリージョンを検出 - リージョンごとにスタックをグルーピングし、個別のAWSセッションを作成
- クロスリージョンの依存関係を解決し、正しい順序で削除
- 独立したリージョン同士は並列で削除
環境(environment)が未指定のスタック(マニフェスト上でunknown-region)の場合は、-rオプションまたはデフォルトのAWS設定のリージョンが使用されます。
CDK版対話モード
-i オプションを使うと、CDKアプリ内で検出されたすべてのスタックの中から、削除したいスタックを選択できます。選択されたスタックは、依存関係を解決しながら並行して削除されます。また、-f オプションを併用することで、削除保護や保持ポリシーが削除前に自動的に無効化されます。
GitHub Actions
GitHub Actions(カスタムアクション)でも使うことができます。複数スタックを一括で削除するには、"stack-name"にスタック名をカンマ区切りで指定してください。
また、CI/CDでは確認プロンプトをスキップできるよう、--yesオプションがデフォルトで有効になっています。
jobs: delstack: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v3 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v3 with: role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role # Or specify access keys. # aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} # aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: us-east-1 - name: Delete stack uses: go-to-k/delstack@main # Or specify the version instead of main with: stack-name: YourStack # stack-name: YourStack1, YourStack2, YourStack3 # To delete multiple stacks (deleted in parallel by default) force: true # Force Mode to delete stacks including resources with the deletion policy Retain or RetainExceptOnCreate (default: false) # yes: true # Skip confirmation prompts (default: true in GitHub Actions) concurrency-number: 4 # Number of parallel stack deletions (default: unlimited) region: us-east-1
CDKアプリのスタックを削除するには、cdk: trueを設定します。cdk synthが実行され、検出されたすべてのスタックを削除します。CDKコンテキスト値の指定や、既存のcdk.outディレクトリの指定も可能です。
jobs: delstack: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v3 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v3 with: role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role aws-region: us-east-1 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: "22" - name: Install CDK run: npm install -g aws-cdk - name: Delete CDK stacks uses: go-to-k/delstack@main with: cdk: true # cdk-app: ./cdk.out # Use existing cdk.out (skip synthesis) # cdk-context: env=dev,foo=bar # CDK context values (comma separated) force: true # yes: true # default: true in GitHub Actions
さらにインストールだけして、生のコマンドを実行することも可能です。
jobs: delstack: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v3 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v3 with: role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role # Or specify access keys. # aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} # aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: us-east-1 - name: Install delstack uses: go-to-k/delstack@main # Or specify the version instead of main - name: Run delstack run: | echo "delstack" delstack -v delstack -s YourStack1 -s YourStack2 -r us-east-1
補足
削除に失敗するリソースがない場合
もちろんこのコマンド一発で同様に削除可能です。
削除失敗リソースがある・ないを意識せず、スタック削除はこのコマンド投げておけばいいみたいな使い方をしています。
対応外の削除失敗リソースがある場合
その旨のメッセージを出力して、削除を終了します。(削除失敗リソースはそのスタックごと残ります。)
スタック外から参照されている場合
他のスタック・リソースで使われていることで削除に失敗するリソース、つまりスタック外から参照(依存)されているものがあるリソースの削除は対象外としています。
あくまでそのスタック内で完結するリソースの強制削除を対象としています。
しかし、それらの依存関係にあるスタックを全て1回のdelstack実行で指定した場合は、それらのスタックを全て削除できます。
おわりに
CloudFormation使いの方、はたまたCDK使いの方などにもかなり便利なんじゃないかなと思います。よかったらぜひ使ってみてください!