

# 选择预置资源时如何处理失败
<a name="stack-failure-options"></a>

如果堆栈操作失败，您无需每次都回滚已成功预置的资源并从头开始。相反，您可以对处于 `CREATE_FAILED` 或 `UPDATE_FAILED` 状态的资源进行问题排查，然后出现问题的位置恢复预置。

要执行操作，必须启用“保留已成功预置的资源”选项。此选项适用于所有堆栈部署和更改集操作。
+ 对于堆栈创建，如果您选择**保留已成功预置的资源**选项，CloudFormation 将保留已成功创建的资源的状态，并将失败的资源保持在失败状态，直到执行下一次更新操作为止。
+ 在更新和更改集操作过程中，选择**保留已成功预置的资源**将保留已成功资源的状态，同时将失败的资源回滚到上一个已知的稳定状态。失败的资源将处于 `UPDATE_FAILED` 状态。没有上一个已知稳定状态的资源将在下一次堆栈操作时删除。

**Topics**
+ [堆栈故障选项概述](#stack-failure-options-overview)
+ [暂停堆栈回滚的必需条件](#stack-failure-options-conditions)
+ [保留成功预置的资源（控制台）](#stack-failure-options-console)
+ [保留成功预置的资源（AWS CLI）](#stack-failure-options-cli)

## 堆栈故障选项概述
<a name="stack-failure-options-overview"></a>

在从 CloudFormation 控制台、API 或 AWS CLI 发出操作之前，请指定预置资源失败时的行为。然后，继续进行资源的部署过程，无需进行任何其他修改。如果发生操作故障，CloudFormation 会在每条独立预置路径中的第一个故障处停止。CloudFormation 识别资源之间的依赖关系以并行处理独立的预置操作。然后继续在每条独立的预置路径上预置资源，直到遇到故障。一条路径中的故障不会影响其他预置路径。CloudFormation 将继续预置资源，直到完成或因其他故障而停止。

修复任何问题以继续部署过程。CloudFormation 在对之前无法成功预置的资源重试预置操作之前执行必要的更新。您可以通过提交 **Retry**（重试）、**Update**（更新）或 **Roll back**（回滚）操作来修复问题。例如，如果您预置 Amazon EC2 实例并且 EC2 实例在创建操作期间失败，您可能想要调查错误，而不是立即回滚失败的资源。您可以查看系统状态检查和实例状态检查，然后在问题解决后选择 **Retry**（重试）操作。

如果堆栈操作失败，并且您已从 **Stack failure options**（堆栈故障选项）菜单中指定 **Preserve successfully provisioned resources**（保留成功预置的资源），您可以选择以下选项。
+ **Retry**（重试）- 重试失败资源的预置操作并继续预置模板，直到堆栈操作成功完成或下一次失败。如果资源由于不需要修改模板的问题（例如 AWS Identity and Access Management（IAM）权限）而无法预置，请选择此选项。
+ **Update**（更新）- 已预置的资源在模板更新时进行更新。将重试未能创建或更新的资源。如果由于模板错误而无法预置资源，并且您已修改模板，请选择此选项。更新处于 `FAILED` 状态的堆栈时，必须为 **Stack failure options**（堆栈故障选项）选择 **Preserve successfully provisioned resources**（保留成功预置的资源）才能继续更新您的堆栈。
+ **Roll back**（回滚）- CloudFormation 将堆栈回滚到上一个已知的稳定状态。

## 暂停堆栈回滚的必需条件
<a name="stack-failure-options-conditions"></a>

要阻止 CloudFormation 自动回滚和删除已成功创建的资源，必须满足以下条件。

1. 创建或更新堆栈时，必须选择**保留已成功预置的资源**选项。该选项会告诉 CloudFormation 不要删除已成功创建的资源，即使整个堆栈操作失败。

1. 堆栈操作必须已经失败，这意味着堆栈状态为 `CREATE_FAILED` 或 `UPDATE_FAILED`。

**注意**  
不支持不可变的更新类型。

## 保留成功预置的资源（控制台）
<a name="stack-failure-options-console"></a>

------
#### [ Create stack ]

**在创建堆栈操作期间保留成功预置的资源**

1. 登录到 AWS 管理控制台 并打开 CloudFormation 控制台 [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/)。

1. 在**堆栈**页面，选择右上角的**创建堆栈**，然后选择**使用新资源（标准）**。

1. 在**先决条件 – 准备模板**中，选择**选择现有模板**。

1. 在 **Specify template (指定模板)** 下，选择指定包含堆栈模板的 S3 存储桶的 URL，或者上传堆栈模板文件。然后选择**下一步**。

1. 在 **Specify stack details**（指定堆栈详细信息）页面上，在 **Stack name**（堆栈名称）框中输入堆栈名称。

1. 在 **Parameters**（参数）部分中，指定在堆栈模板中定义的参数。

   您可使用或更改带默认值的任何参数。

1. 如果对参数值满意，选择 **Next**（下一步）。

1. 在 **Configure stack options**（配置堆栈选项）页面上，可以设置堆栈的其他选项。

1. 对于 **Stack failure options**（堆栈故障选项），选择 **Preserve successfully provisioned resources**（保留成功预置的资源）。

1. 如果对堆栈选项满意，选择 **Next**（下一步）。

1. 在 **Review**（审核）页面上查看堆栈，然后选择 **Create stack**（创建堆栈）。

*结果*：创建失败的资源将堆栈状态转换为 `CREATE_FAILED`，以防止堆栈操作遇到故障时堆栈回滚。成功预置的资源处于 `CREATE_COMPLETE` 状态。您可在 **Stack events**（堆栈事件）选项卡中监控堆栈。

------
#### [ Update stack ]

**在更新堆栈操作期间保留成功预置的资源**

1. 登录到 AWS 管理控制台 并打开 CloudFormation 控制台 [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/)。

1. 选择要更新的堆栈，然后选择 **Update**（更新）。

1. 在 **Update stack**（更新堆栈）页面上，使用以下选项之一选择堆栈模板：
   + **使用现有模板**
   + **替换当前模板**
   + **在基础设施编辑器中编辑模板**

   接受您的设置并选择 **Next**（下一步）。

1. 在 **Specify stack details**（指定堆栈详细信息）页面上，指定在堆栈模板中定义的参数。

   您可使用或更改带默认值的任何参数。

1. 如果对参数值满意，选择 **Next**（下一步）。

1. 在 **Configure stack options**（配置堆栈选项）页面上，可以设置堆栈的其他选项。

1. 对于 **Behavior on provisioning failure**（预置失败时的行为），选择 **Preserve successfully provisioned resources**（保留成功预置的资源）。

1. 如果对堆栈选项满意，选择 **Next**（下一步）。

1. 在 **Review**（查看）页面上查看堆栈，然后选择 **Update stack**（更新堆栈）。

*结果*：更新失败的资源将堆栈状态转换为 `UPDATE_FAILED`，并回滚到上一个已知的稳定状态。没有上一个已知稳定状态的资源将在下一次堆栈操作时被 CloudFormation 删除。成功预置的资源处于 `CREATE_COMPLETE` 或 `UPDATE_COMPLETE` 状态。您可在 **Stack events**（堆栈事件）选项卡中监控堆栈。

------
#### [ Change set ]

**注意**  
您可以为状态为 `CREATE_FAILED` 或 `UPDATE_FAILED` 的堆栈启动更改集，但不能为状态为 `UPDATE_ROLLBACK_FAILED` 的堆栈启动更改集。

**在更改集操作期间保留成功预置的资源**

1. 登录到 AWS 管理控制台 并打开 CloudFormation 控制台 [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/)。

1. 选择包含要启动的更改集的堆栈，然后选择 **Change sets**（更改集）选项卡。

1. 选择更改集，然后选择 **Execute**（执行）。

1. 对于 **Execute change set**（执行更改集），选择 **Preserve successfully provisioned resources**（保留成功预置的资源）选项。

1. 选择 **Execute change set**（执行更改集）。

*结果*：更新失败的资源将堆栈状态转换为 `UPDATE_FAILED`，并回滚到上一个已知的稳定状态。没有上一个已知稳定状态的资源将在下一次堆栈操作时被 CloudFormation 删除。成功预置的资源处于 `CREATE_COMPLETE` 或 `UPDATE_COMPLETE` 状态。您可在 **Stack events**（堆栈事件）选项卡中监控堆栈。

------

## 保留成功预置的资源（AWS CLI）
<a name="stack-failure-options-cli"></a>

------
#### [ Create stack ]

**在堆栈创建操作期间保留成功预置的资源**

在 [create-stack](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/create-stack.html) 操作期间指定 `--disable-rollback` 选项或 `on-failure DO_NOTHING` 枚举。

1. 为 **create-stack** 命令提供堆栈名称和模板并采用 `--disable-rollback` 选项。

   ```
   aws cloudformation create-stack --stack-name myteststack \
       --template-body file://template.yaml \
       --disable-rollback
   ```

   该命令将返回以下输出。

   ```
   {
       "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/myteststack/466df9e0-0dff-08e3-8e2f-5088487c4896"
   }
   ```

1. 使用 **describe-stacks** 命令描述堆栈状态。

   ```
   aws cloudformation describe-stacks --stack-name myteststack
   ```

   该命令将返回以下输出。

   ```
   {
       "Stacks":  [
           {
               "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/myteststack/466df9e0-0dff-08e3-8e2f-5088487c4896",
               "Description": "AWS CloudFormation Sample Template",
               "Tags": [],
               "Outputs": [],
               "StackStatusReason": “The following resource(s) failed to create: [MyBucket]”,
               "CreationTime": "2013-08-23T01:02:15.422Z",
               "Capabilities": [],
               "StackName": "myteststack",
               "StackStatus": "CREATE_FAILED",
               "DisableRollback": true
           }
       ]
   }
   ```

------
#### [ Update stack ]

**在堆栈更新操作期间保留成功预置的资源**

1. 为 **update-stack** 命令提供现有堆栈名称和模板并采用 `--disable-rollback` 选项。

   ```
   aws cloudformation update-stack --stack-name myteststack \
       --template-url https://s3.amazonaws.com/amzn-s3-demo-bucket/updated.template --disable-rollback
   ```

   该命令将返回以下输出。

   ```
   {
       "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/myteststack/466df9e0-0dff-08e3-8e2f-5088487c4896"
   }
   ```

1. 使用 **describe-stacks** 或 **describe-stack-events** 命令描述堆栈状态。

   ```
   aws cloudformation describe-stacks --stack-name myteststack
   ```

   该命令将返回以下输出。

   ```
   {
       "Stacks":  [
           {
               "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/myteststack/466df9e0-0dff-08e3-8e2f-5088487c4896",
               "Description": "AWS CloudFormation Sample Template",
               "Tags": [],
               "Outputs": [],
               "CreationTime": "2013-08-23T01:02:15.422Z",
               "Capabilities": [],
               "StackName": "myteststack",
               "StackStatus": "UPDATE_COMPLETE",
               "DisableRollback": true
           }
       ]
   }
   ```

------
#### [ Change set ]

**注意**  
您可以为状态为 `CREATE_FAILED` 或 `UPDATE_FAILED` 的堆栈启动更改集，但不能为状态为 `UPDATE_ROLLBACK_FAILED` 的堆栈启动更改集。

**在更改集操作期间保留成功预置的资源**

在 [execute-change-set](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/execute-change-set.html) 操作期间指定 `--disable-rollback` 选项。

1. 为 **execute-change-set** 命令提供堆栈名称和模板并采用 `--disable-rollback` 选项。

   ```
   aws cloudformation execute-change-set --stack-name myteststack \
       --change-set-name my-change-set --template-body file://template.yaml
   ```

   该命令将返回以下输出。

   ```
   {
    "Id": "arn:aws:cloudformation:us-east-1:123456789012:changeSet/my-change-set/bc9555ba-a949-xmpl-bfb8-f41d04ec5784",
    "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/myteststack/466df9e0-0dff-08e3-8e2f-5088487c4896"
   }
   ```

1. 启动更改集并采用 `--disable-rollback` 选项。

   ```
   aws cloudformation execute-change-set --stack-name myteststack \
       --change-set-name my-change-set -–disable-rollback
   ```

1. 使用 **describe-stacks** 或 **describe-stack-events** 命令确定堆栈状态。

   ```
   aws cloudformation describe-stack-events --stack-name myteststack
   ```

   该命令将返回以下输出。

   ```
   {
      "StackEvents": [
        {
           "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/myteststack/466df9e0-0dff-08e3-8e2f-5088487c4896",
           "EventId": "49c966a0-7b74-11ea-8071-024244bb0672",
           "StackName": "myteststack",
           "LogicalResourceId": " MyBucket",
           "PhysicalResourceId": "myteststack-MyBucket-abcdefghijk1",
           "ResourceType": "AWS::S3::Bucket",
           "Timestamp": "2020-04-10T21:43:17.015Z",
           "ResourceStatus": "UPDATE_FAILED"
           "ResourceStatusReason": "User XYZ is not allowed to perform S3::UpdateBucket on MyBucket"
        }
   }
   ```

1. 修复权限错误并重试该操作。

   ```
   aws cloudformation update-stack --stack-name myteststack \
       --use-previous-template --disable-rollback
   ```

   该命令将返回以下输出。

   ```
   {
       "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/myteststack/466df9e0-0dff-08e3-8e2f-5088487c4896"
   }
   ```

1. 使用 **describe-stacks** 或 **describe-stack-events** 命令描述堆栈状态。

   ```
   aws cloudformation describe-stacks --stack-name myteststack
   ```

   该命令将返回以下输出。

   ```
   {
       "Stacks":  [
           {
               "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/myteststack/466df9e0-0dff-08e3-8e2f-5088487c4896",
               "Description": "AWS CloudFormation Sample Template",
               "Tags": [],
               "Outputs": [],
               "CreationTime": "2013-08-23T01:02:15.422Z",
               "Capabilities": [],
               "StackName": "myteststack",
               "StackStatus": "UPDATE_COMPLETE",
               "DisableRollback": true
           }
       ]
   }
   ```

------

### 回滚堆栈
<a name="roll-back-stack-cli"></a>

您可以使用 [rolback-stack](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/rollback-stack.html) 命令将堆栈状态为 `CREATE_FAILED` 或 `UPDATE_FAILED` 的堆栈回滚到上一个稳定状态。

以下 **rollback-stack** 命令将会回滚指定的堆栈。

```
aws cloudformation rollback-stack --stack-name myteststack
```

该命令将返回以下输出。

```
{
    "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/myteststack/466df9e0-0dff-08e3-8e2f-5088487c4896"
}
```

**注意**  
如果堆栈不包含上一个已知的稳定状态，则 **rollback-stack** 操作将删除该堆栈。