

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 自动删除 AWS CloudFormation 堆栈和相关资源
<a name="automate-deletion-cloudformation-stacks-associated-resources"></a>

*SANDEEP SINGH 和 James Jacob，Amazon Web Services*

## Summary
<a name="automate-deletion-cloudformation-stacks-associated-resources-summary"></a>

[AWS CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html) 是一项广泛使用的服务，用于管理云基础设施即代码（IaC）。使用时 CloudFormation，您可以将相关资源作为一个称为*堆栈*的单元进行管理。您可通过创建、更新和删除堆栈来创建、更新和删除一组资源。

有时，您不再需要 CloudFormation 堆栈中的资源。根据资源及其配置，删除堆栈及其关联资源可能很复杂。在现实世界的生产系统中，由于相互冲突的条件或 CloudFormation 无法超越的限制，删除有时会失败或需要很长时间。可能需要仔细地计划和执行，以确保以高效、一致的方式正确删除所有资源。此模式描述了如何设置一个框架，以帮助您管理涉及以下复杂性的 CloudFormation 堆栈的删除：
+ **具有删除保护的资源** – 某些资源可能启用了删除保护。常见的示例是 [Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html) 表和 [Amazon Simple Storage Service（Amazon S3）](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html)存储桶。删除保护可防止自动删除，例如通过删除 CloudFormation。如果要删除这些资源，则必须手动或以编程方式覆盖或暂时禁用删除保护。在继续操作之前，您应该仔细考虑删除这些资源的影响。
+ **具有保留策略的资源** — 某些资源，例如 AWS Key Management Service (AWS KMS) 密钥和 Amazon S3 存储桶，可能有保留策略，规定在请求删除后应保留多长时间。您应在清理策略中考虑这些政策，以始终符合组织策略和监管要求。
+ **延迟删除附加到 VPC 的 Lambda 函数** – 删除附加到虚拟私有云（VPC）的 [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) 函数可能需要 5-40 分钟，具体取决于该流程中涉及的多个相互关联的依赖项。如果您在删除堆栈之前将函数从 VPC 分离，则可以将此延迟减少到 1 分钟以内。
+ **非直接创建的资源 CloudFormation** — 在某些应用程序设计中，资源可能由应用程序本身或通过 CloudFormation 堆栈置备的资源在原始堆栈之外创建。下面是两个示例：
  + CloudFormation 可能会预配置一个运行用户数据脚本的[亚马逊弹性计算云 (Amazon EC2)](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/concepts.html) 实例。然后，此脚本可能会创建一个 [AWS Systems Manager](https://docs.aws.amazon.com/systems-manager/latest/userguide/what-is-systems-manager.html) 参数来存储与应用程序相关的数据。此参数不是通过管理的 CloudFormation。
  + CloudFormation 可能会配置一个 Lambda 函数，该函数会自动生成用于存储[ CloudWatch 日志的 Amazon 日志](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html)组。此日志组不是通过管理的 CloudFormation。

  尽管这些资源不是由直接管理的 CloudFormation，但在删除堆栈时通常需要清理它们。如果不加管理，它们可能变成孤立资源，导致不必要的资源消耗。

尽管这些护栏可能会增加复杂性，但它们是有意为之且至关重要的。 CloudFormation 在许多情况下，允许超越所有限制和不分青红皂白地删除资源可能会导致不利和不可预见的后果。但是，作为 DevOps 负责管理环境的云工程师，有时可能需要克服这些限制，尤其是在开发、测试或暂存环境中。

**目标业务成果**

通过实施此框架，您可以获得以下优势：
+ **成本管理** — 定期高效地清理临时环境，例如 end-to-end或用户验收测试环境，有助于防止资源的运行时间超过必要的时间。这可显著降低成本。
+ **安全** — 自动清理过时或未使用的资源可减少攻击面并有助于维护安全的 AWS 环境。
+ **运营效率** – 定期和自动清理可以带来以下运营优势：
  + 删除旧日志组或空 Amazon S3 存储桶的自动脚本可以通过保持环境整洁和可管理来提高运营效率。
  + 快速删除和重新创建堆栈支持设计和实现的快速迭代，由此实现更强大、更具弹性的架构。
  + 定期删除和重建环境可以帮助您识别和修复潜在的问题。这可以帮助您确保基础设施能够承受现实场景。

## 先决条件和限制
<a name="automate-deletion-cloudformation-stacks-associated-resources-prereqs"></a>

**先决条件**
+ 活跃的 AWS 账户
+ Python 3.6 或更高版本，[已安装](https://www.python.org/downloads/)
+ AWS Command Line Interface (AWS CLI)，[已安装](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)并[配置](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html)

**限制**
+ 命名约定用于标识应删除的资源。此模式中的示例代码使用资源名称的前缀，但您可以定义自己的命名约定。不使用此命名约定的资源将不会被识别或随后删除。

## 架构
<a name="automate-deletion-cloudformation-stacks-associated-resources-architecture"></a>

下图显示了此框架如何识别目标 CloudFormation 堆栈以及与之相关的额外资源。

![\[发现、处理和删除 CloudFormation 堆栈及其相关资源的阶段。\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/images/pattern-img/ab7c3b56-3476-41a3-8ece-68915605a546/images/a7fceb1c-d624-47b3-957d-f910ef2f44d7.png)


下图显示了如下工作流：

1. **收集资源** — 自动化框架使用命名约定返回所有相关的 CloudFormation 堆栈、Amazon Elastic Container Registry (Amazon ECR) Registry 存储库、DynamoDB 表和 Amazon S3 存储桶。
**注意**  
此阶段的函数使用[分页工具](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/paginators.html)，这是 Boto3 中的一项功能，它抽象了对截断的 API 结果集进行迭代的过程。这样可以确保所有资源都得到处理。要进一步优化性能，请考虑应用[服务器端](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/paginators.html#filtering-results)筛选或考虑使用 JMESPath 来执行[客户端](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/paginators.html#filtering-results-with-jmespath)筛选。

1. **预处理** — 自动化框架识别并解决了必须覆盖的服务限制， CloudFormation 才能允许删除资源。例如，它将 DynamoDB 表的 `DeletionProtectionEnabled` 设置更改为 `False`。在命令行界面中，对于每种资源，您都会收到一条提示，询问是否要覆盖该约束条件。

1. **删除堆栈**-自动化框架删除 CloudFormation 堆栈。在命令行界面中，您会收到一条提示，询问您是否要删除该堆栈。

1. **后处理** — 自动化框架会删除所有未 CloudFormation 作为堆栈一部分直接配置的相关资源。这些资源类型的示例包括 Systems Manager 参数和 CloudWatch 日志组。单独的函数收集这些资源，对其进行预处理，然后将其删除。在命令行界面中，对于每种资源，您都会收到一条提示，询问您是否要删除该资源。
**注意**  
此阶段的函数使用[分页工具](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/paginators.html)，这是 Boto3 中的一项功能，它抽象了对截断的 API 结果集进行迭代的过程。这样可以确保所有资源都得到处理。要进一步优化性能，请考虑应用[服务器端](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/paginators.html#filtering-results)筛选或考虑使用 JMESPath 来执行[客户端](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/paginators.html#filtering-results-with-jmespath)筛选。

**自动化和扩展**

如果您的 CloudFormation 堆栈包含示例代码中未包含的其他资源，或者堆栈存在此模式中未解决的约束条件，则可以根据自己的用例调整自动化框架。按照相同的方法收集资源、进行预处理、删除堆栈，然后进行后处理。

## 工具
<a name="automate-deletion-cloudformation-stacks-associated-resources-tools"></a>

**AWS 服务**
+ [AWS CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html)帮助您设置 AWS 资源，快速一致地配置资源，并在和的整个 AWS 账户 生命周期中对其进行管理 AWS 区域。
+ [CloudFormation 命令行界面 (CFN-CLI)](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/what-is-cloudformation-cli.html) 是一款开源工具，可帮助您开发 AWS 和测试第三方扩展，然后注册它们以在中使用。 CloudFormation
+ [适用于 Python (Boto3) 的 AWS SDK](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html)是一个软件开发套件，可帮助您将 Python 应用程序、库或脚本与集成 AWS 服务。

**其他工具**
+ [Click](https://click.palletsprojects.com/en/stable/) 是一款 Python 工具，可帮助您创建命令行界面。
+ [Poetry](https://python-poetry.org/docs/) 是 Python 中用于管理和打包依赖项的工具。
+ [Pyenv](https://github.com/pyenv/pyenv) 是一款可以帮助您管理 Python 以及在其版本之间切换的工具。
+ [Python](https://www.python.org/) 是通用的计算机编程语言。

**代码存储库**

此模式的代码可在 GitHub [cloudformation-stack-cleanup](https://github.com/aws-samples/cloudformation-stack-cleanup/)存储库中找到。

## 最佳实践
<a name="automate-deletion-cloudformation-stacks-associated-resources-best-practices"></a>
+ **标记资源以便于识别** – 实施[标记策略](https://aws.amazon.com/solutions/guidance/tagging-on-aws/)以识别针对不同环境和用途创建的资源。标签可以帮助您根据标签筛选资源，从而简化清理过程。
+ **设置资源生命周期** – 定义资源生命周期，以便在特定时间后自动删除资源。这种做法可帮助您确保临时环境不会成为永久性的成本负担。

## 操作说明
<a name="automate-deletion-cloudformation-stacks-associated-resources-epics"></a>

### 安装工具
<a name="install-tools"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 克隆存储库。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/automate-deletion-cloudformation-stacks-associated-resources.html) | DevOps 工程师 | 
| 安装 Poetry。 | 按照[说明](https://python-poetry.org/docs/)（Poetry 文档）在目标虚拟环境中安装 Poetry。 | DevOps 工程师 | 
| 安装依赖项。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/automate-deletion-cloudformation-stacks-associated-resources.html) | DevOps 工程师 | 
| （可选）安装 Pyenv。 | 按照[说明](https://github.com/pyenv/pyenv#installation) (GitHub) 安装 Pyenv。 | DevOps 工程师 | 

### （可选）自定义框架
<a name="optional-customize-the-framework"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 创建用于收集、预处理和删除目标资源的函数。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/automate-deletion-cloudformation-stacks-associated-resources.html) | DevOps 工程师，Python | 

### 创建示例资源
<a name="create-sample-resources"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 创建堆 CloudFormation 栈。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/automate-deletion-cloudformation-stacks-associated-resources.html) | AWS DevOps | 
| 创建 Systems Manager 参数。 | 输入以下命令来创建未通过 CloudFormation配置的 Systems Manager 参数：<pre>aws ssm put-parameter \<br />  --name "/sampleforcleanup/database/password" \<br />  --value "your_db_password" \<br />  --type "SecureString" \<br />  --description "Database password for my app" \<br />  --tier "Standard" \<br />  --region "us-east-1"</pre> | AWS DevOps | 
| 创建 Amazon S3 存储桶。 | 输入以下命令以创建未通过 CloudFormation配置的 Amazon S3 存储桶：<pre>aws s3api create-bucket \<br />  --bucket samplesorcleanup-unmanagedbucket-<UniqueIdentifier> \<br />  --region us-east-1 \<br />  --create-bucket-configuration LocationConstraint=us-east-1</pre> | AWS DevOps | 

### 删除示例资源
<a name="delete-the-sample-resources"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 删除 CloudFormation 堆栈。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/automate-deletion-cloudformation-stacks-associated-resources.html) | AWS DevOps | 
| 验证资源删除。 | 在输出中，确认所有示例资源均已删除。有关示例查询，请参阅此模式的[其他资源](#automate-deletion-cloudformation-stacks-associated-resources-additional)部分。 | AWS DevOps | 

## 相关资源
<a name="automate-deletion-cloudformation-stacks-associated-resources-resources"></a>
+ [删除堆栈](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-console-delete-stack.html)（CloudFormation 文档）
+ [故障排除 CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/troubleshooting.html)（CloudFormation 文档）
+ [授予 Lambda 函数访问 Amazon VPC 中资源的权限](https://docs.aws.amazon.com/lambda/latest/dg/configuration-vpc.html)（Lambda 文档）
+ [如何删除停留在 DELETE\$1FAILED 状态的 AWS CloudFormation 堆栈？](https://repost.aws/knowledge-center/cloudformation-stack-delete-failed) （AWS 知识中心）

## 附加信息
<a name="automate-deletion-cloudformation-stacks-associated-resources-additional"></a>

下面是 `cfncli` 命令的示例输出：

```
cfncli --region aus-east-1  dev cleanup-env --prefix-list sampleforcleanup                                                                                                                              
https://sts.us-east-1.amazonaws.com
Cleaning up: ['sampleforcleanup'] in xxxxxxxxxx:us-east-1
Do you want to proceed? [Y/n]: Y
No S3 buckets
No ECR repositories
No Lambda functions in VPC
The following DynamoDB tables will have their deletion protection removed:
sampleforcleanup-MyDynamoDBTable
Do you want to proceed with removing deletion protection from these tables? [Y/n]: Y
Deletion protection disabled for DynamoDB table 'sampleforcleanup-MyDynamoDBTable'.
The following CloudFormation stacks will be deleted:
sampleforcleanup-Stack
Do you want to proceed with deleting these CloudFormation stacks? [Y/n]: Y
Initiated deletion of CloudFormation stack: `sampleforcleanup-Stack`
Waiting for stack `sampleforcleanup-Stack` to be deleted...
CloudFormation stack `sampleforcleanup-Stack` deleted successfully.
The following ssm_params will be deleted:
/sampleforcleanup/database/password
Do you want to proceed with deleting these ssm_params? [Y/n]: Y
Deleted SSM Parameter: /sampleforcleanup/database/password
Cleaned up: ['sampleforcleanup']
```