

# 使用偏移检测功能检测堆栈和资源的非托管配置更改
<a name="using-cfn-stack-drift"></a>

即使您通过 CloudFormation 管理您的资源，用户也可以在 CloudFormation之外更改这些资源。用户可以使用创建资源的底层服务直接编辑资源。例如，您可以使用 Amazon EC2 控制台来更新作为 CloudFormation 堆栈的一部分创建的服务器实例。有些更改可能是偶然的，而有些更改可能会故意响应对时间敏感的操作事件。无论如何，在 CloudFormation 之外进行的更改会导致堆栈更新或删除操作变得复杂。您可以使用偏差检测来识别在 CloudFormation 管理之外进行配置更改的堆栈资源。然后，您可以采取纠正措施，使堆栈资源再次与其在堆栈模板中的定义同步，例如直接更新偏离的资源，以便它们与其模板定义一致。解决偏差有助于确保配置一致性和成功的堆栈操作。

**Topics**
+ [什么是偏差？](#what-is-drift)
+ [偏差检测状态代码](#drift-status-codes)
+ [检测偏差时的注意事项](#drift-considerations)
+ [在整个 CloudFormation 堆栈上检测偏差](detect-drift-stack.md)
+ [在单个堆栈资源上检测偏差](detect-drift-resource.md)
+ [通过导入操作消除偏差](resource-import-resolve-drift.md)

## 什么是偏差？
<a name="what-is-drift"></a>

通过偏离检测，您可以检测堆栈的实际配置是否与其预期配置不同或已经*偏离*。使用 CloudFormation 可在整个堆栈上或在堆栈内的单个资源上检测偏差。如果某个资源的任何实际属性值与预期的属性值不同，则认为该资源已偏离。这包括是否已删除属性或资源。如果堆栈的一个或多个资源已偏离，则认为堆栈已偏离。

为了确定资源是否已偏离，CloudFormation 确定预期的资源属性值（如堆栈模板中所定义）以及任何指定为模板参数的值。然后 CloudFormation 将这些预期值与堆栈中当前存在的资源属性的实际值进行比较。如果资源的一个或多个属性已被删除或其值已更改，则认为该资源已偏离。

CloudFormation 生成有关已偏离的堆栈中每个资源的详细信息。

CloudFormation 在那些支持偏差检测的 AWS 资源上检测偏差。不支持偏差检测的资源会被分配 NOT\$1CHECKED 的偏差状态。有关支持偏差检测的 AWS 资源的列表，请参阅 [资源类型支持](resource-import-supported-resources.md)。

此外，CloudFormation 还支持对*可预置*的私有资源类型（即其预置类型为 `FULLY_MUTABLE` 或 `IMMUTABLE`）进行偏差检测。要对私有资源类型的资源执行偏差检测，您在账户中注册的资源类型的默认版本必须可预置。有关资源预置类型的更多信息，请参阅《AWS CloudFormation API Reference》**中 [https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_DescribeType.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_DescribeType.html) 操作的 `ProvisioningType` 参数和《AWS CLI Command Reference》**中 [https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-type.html](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-type.html) 命令的参数。有关私有资源的更多信息，请参阅 [通过 CloudFormation 注册表管理扩展](registry.md)。

您可以在具有以下状态的堆栈上执行偏差检测：`CREATE_COMPLETE`、`UPDATE_COMPLETE`、`UPDATE_ROLLBACK_COMPLETE` 和 `UPDATE_ROLLBACK_FAILED`。

当在堆栈上检测偏差时，CloudFormation 不在任何属于该堆栈的嵌套堆栈上检测偏差。有关更多信息，请参阅 [使用嵌套堆栈将模板拆分为可重复使用的部分](using-cfn-nested-stacks.md)。相反，您可以直接在嵌套堆栈上启动偏差检测操作。

**注意**  
CloudFormation 仅通过堆栈模板或通过指定模板参数来确定显式设置的属性值的偏差。这不包括资源属性的默认值。要使 CloudFormation 跟踪资源属性以确定偏差，请显式设置属性值，即使您将其设置为默认值也是如此。

## 偏差检测状态代码
<a name="drift-status-codes"></a>

本节中的表描述了偏差检测使用的各种状态类型：
+ **偏差检测操作状态**描述偏差操作的当前状态。
+ **偏差状态** 

  对于堆栈集，它根据属于堆栈集的堆栈实例的偏差状态以描述堆栈集的总体偏差状态。

  对于堆栈实例，它根据堆栈实例的关联堆栈的偏差状态以描述堆栈实例的偏差状态。

  对于堆栈，它根据堆栈资源的偏差状态以描述堆栈的总体偏差状态。
+ **资源偏差状态**描述单个资源的偏差状态。

下表列出了 CloudFormation 分配给堆栈偏差检测操作的状态代码。


| 偏差检测操作状态 | 说明 | 
| --- | --- | 
|  `DETECTION_COMPLETE`  |  已经对支持偏差检测的堆栈中的所有资源成功完成了堆栈偏差检测操作。  | 
|  `DETECTION_FAILED`  |  堆栈偏差检测操作对于堆栈中的至少一个资源失败。结果将可用于 CloudFormation 在其上成功完成偏差检测的资源。  | 
|  `DETECTION_IN_PROGRESS`  |  堆栈偏差检测操作目前正在进行中。  | 

下表列出了 CloudFormation 分配给堆栈的偏差状态代码。


| 偏差状态 | 说明 | 
| --- | --- | 
|  `DRIFTED`  |  对于堆栈：堆栈与其预期模板配置不同或*已偏离*。如果堆栈的一个或多个资源已偏离，则认为堆栈已偏离。 对于堆栈实例：如果与堆栈实例关联的堆栈已偏离，则认为该实例已偏离。 对于堆栈集：如果一个或多个堆栈实例已偏离，则认为堆栈集已偏离。  | 
|  `NOT_CHECKED`  |  CloudFormation 尚未检查堆栈、堆栈集或堆栈实例是否与其预期模板配置不同。  | 
|  `IN_SYNC`  |  每个受支持资源的当前配置与其预期的模板配置相匹配。没有支持偏差检测的资源的堆栈、堆栈集或堆栈实例也具有 IN\$1SYNC 状态。  | 

下表列出了 CloudFormation 分配给堆栈资源的偏差代码。


| 资源偏差状态 | 说明 | 
| --- | --- | 
|  `DELETED`  |  资源与预期的模板配置不同，因为资源已被删除。  | 
|  `MODIFIED`  |  资源与预期的模板配置不同。  | 
|  `NOT_CHECKED`  |  CloudFormation 没有检查资源是否与预期的模板配置不同。  | 
|  `IN_SYNC`  |  资源的当前配置与其预期的模板配置相匹配。  | 

下表列出了 CloudFormation 分配给与预期模板配置不同的资源属性的差异类型状态代码。


| 属性差异类型 | 说明 | 
| --- | --- | 
|  `ADD`  |  已将值添加到数据类型为数组或列表的资源属性。  | 
|  `REMOVE`  |  属性已从当前资源配置中删除。  | 
|  `NOT_EQUAL`  |  当前属性值与堆栈模板中定义的预期值不同。  | 

## 检测偏差时的注意事项
<a name="drift-considerations"></a>

为了在堆栈上成功执行偏差检测，用户必须具有以下权限：
+ 支持在堆栈中包含的偏差检测的每个资源的读取权限。例如，如果堆栈包含 `AWS::EC2::Instance` 资源，则您必须具有 `ec2:DescribeInstances` 权限才能在堆栈上执行偏差检测。
+ `cloudformation:DetectStackDrift`
+ `cloudformation:DetectStackResourceDrift`
+ `cloudformation:BatchDescribeTypeConfigurations`

有关在 CloudFormation 中设置权限的更多信息，请参阅 [使用 AWS Identity and Access Management 控制 CloudFormation 访问权限](control-access-with-iam.md)。

在某些边缘情况下，CloudFormation 可能无法始终返回准确的偏差结果。您应该了解这些边缘情况，以便正确解释您的偏差检测结果。
+ 在某些情况下，属性数组中包含的对象将报告为偏差，而实际上它们是从负责该资源的底层服务提供给属性的默认值。
+ 某些资源与相关资源具有附件关系，使得资源可以实际附加或删除在相同或另一模板中定义的另一资源的属性值。例如，如果 `AWS::EC2::SecurityGroupIngress` 和 `AWS::EC2::SecurityGroupEgress` 资源也可用于连接和删除 `AWS::EC2::SecurityGroup` 资源中的值。在这些情况下，CloudFormation 在执行偏差比较之前分析附件的堆栈模板。但是，CloudFormation 无法跨堆栈执行此分析，因此可能不会返回准确的偏差结果，其中附加的资源驻留在不同的堆栈中。

  支持偏差检测并允许或要求其他资源中的附件的资源包括：    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AWSCloudFormation/latest/UserGuide/using-cfn-stack-drift.html)
+ CloudFormation 不对任何资源的 `KMSKeyId` 属性执行偏差检测。由于 AWS KMS 密钥可以由多个别名引用，因此 CloudFormation 无法保证此属性有一致准确的偏差结果。
+ 您可以在堆栈模板中指定某些资源属性，就其本质而言，CloudFormation 无法将其与生成的堆栈资源中的属性进行比较。因此，这些属性不能包括在偏差检测结果中。这些属性可分为两大类：
  + CloudFormation 无法在堆栈模板中映射回初始资源属性值的属性值。

    例如，CloudFormation 无法将 Lambda 函数的源代码映射回 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-lambda-function.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-lambda-function.html) 资源的 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-lambda-function-code.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-lambda-function-code.html) 属性类型，因此 CloudFormation 无法将其包括在偏差检测结果中。
  + 负责资源的服务不返回的属性值。

    某些属性值被有意设计成永远不会由资源所属的服务返回。这些属性值往往包含机密信息，例如密码或其他不应泄露的敏感数据。例如，IAM 服务永远不会返回 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-iam-user-loginprofile.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-iam-user-loginprofile.html) 属性类型的 `Password` 属性值，因此 CloudFormation 不能将其包含在偏差检测结果中。
  + 数组中的对象实际上可能是服务默认值，而不是在手动添加的偏差。
+ 如果您遇到任何误报，请使用 CloudFormation 控制台中的反馈链接将您的评论发送给我们，或通过 [AWS re:Post](https://repost.aws/) 与我们联系。
+ 某些属性可能有相等但不完全相同的输入值。为避免误报，应确保预期配置与实际配置相匹配。
  + 例如，资源属性的预期配置可能为 1024MB，而同一资源属性的实际配置可能为 1GB。1024MB 和 1GB 相等但不完全相同。

    当在此资源属性上运行偏差检测时，它将发出偏差结果信号。

    为避免误报，请将资源属性的预期配置更改为 1024MB，然后运行偏差检测。

# 在整个 CloudFormation 堆栈上检测偏差
<a name="detect-drift-stack"></a>

在堆栈上执行偏差检测操作会确定堆栈是否已偏离其预期的模板配置，并返回有关支持偏差检测的堆栈中每个资源的偏差状态的详细信息。

**使用 AWS 管理控制台 在整个堆栈上检测偏差**

1. 通过以下网址打开 CloudFormation 控制台：[https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/)。

1. 从堆栈列表中，选择要执行偏差检测的堆栈。在堆栈详细信息窗格中，选择 **Stack actions (堆栈操作)**，然后选择 **Detect drift (检测偏差)**。  
![\[在所选堆栈的“堆栈操作”菜单上选择的“检测当前堆栈的偏差”命令。\]](http://docs.aws.amazon.com/zh_cn/AWSCloudFormation/latest/UserGuide/images/console-stacks-actions-detect-drift-1.png)

   CloudFormation 会显示一个信息栏，指示已为选定堆栈启动偏差检测。

1. 请耐心等待，直到 CloudFormation 完成偏差检测操作。偏差检测操作完成后，CloudFormation 会更新堆栈的**偏差状态**和**上一次偏差检查时间**。这些字段在堆栈详细信息页面上 **Stack info**（堆栈信息）窗格的 **Overview**（概述）部分中列出。

   偏差检测操作可能需要几分钟，具体取决于堆栈中包含的资源数量。您一次只能在给定堆栈上运行一个偏差检测操作。即使您关闭信息栏，CloudFormation 也会继续执行偏差检测操作。

1. 查看堆栈及其资源的偏差检测结果。在选定堆栈的情况下，从 **Stack actions (堆栈操作)** 菜单中选择 **View drift results (查看偏差结果)**。

   CloudFormation 会列出堆栈的整体偏差状态，以及最后一次在堆栈或其任何单个资源上启动偏差检测的时间。如果堆栈的一个或多个资源已偏离，则认为堆栈已偏离。  
![\[所选堆栈的“Drift (偏差)”页面上会显示整体堆栈偏差状态、偏差检测状态，以及最后一次在堆栈或其任何单个资源上启动偏差检测的时间。\]](http://docs.aws.amazon.com/zh_cn/AWSCloudFormation/latest/UserGuide/images/console-stacks-drifts-overview-1.png)

   在 **Resource drift details (资源偏差状态)** 部分中，CloudFormation 会列出每个堆栈资源、其偏差状态，以及最后一次在资源上启动偏差检测的时间。将会显示每个资源的逻辑 ID 和物理 ID，以帮助您识别它们。此外，对于状态为 **MODIFIED (已修改)** 的资源，CloudFormation 会显示资源偏差详细信息。

   您可以使用**偏差状态**列根据资源偏差状态对资源排序。

   1. 查看已修改资源的详细信息。

     1. 选定已修改的资源，选择 **View drift details**（查看偏差详细信息）。

       CloudFormation 会显示该资源的偏差详细信息页面。此页面会列出资源的预期和当前属性值，以及两者之间的任何区别。

       要突出显示区别，请在**区别**部分中选择属性名称。
       + 添加的属性在 **Details**（详细信息）部分的 **Current**（当前）列中以绿色突出显示。
       + 删除的属性在 **Details**（详细信息）部分的 **Expected**（预期）列中以红色突出显示。
       + 其值已更改的属性在 **Expected (预期)** 和 **Current (当前)** 列中以黄色突出显示。  
![\[偏差详细信息页面上的资源偏差状态部分，其中包含堆栈中支持偏差检测的每个资源的偏差信息。详细信息包括偏差状态以及预期的和当前的属性值。\]](http://docs.aws.amazon.com/zh_cn/AWSCloudFormation/latest/UserGuide/images/console-stacks-drifts-drift-details-differences-1.png)

**使用 AWS CLI 在整个堆栈上检测偏差**
**重要**  
查看堆栈的**上次偏差检查时间**，并确认它早于资源偏差结果中显示的时间戳，以防止使用过时的数据。

要使用 AWS CLI 在整个堆栈上检测偏差，请使用以下 AWS CLI 命令：
+ **detect-stack-drift**，用于对堆栈启动偏差检测操作。
+ **describe-stack-drift-detection-status**，用于监控堆栈偏差检测操作的状态。
+ **describe-stack-resource-drifts**，可查看堆栈偏差检测操作的详细信息。

1. 使用 **detect-stack-drift** 可在整个堆栈上检测偏差。指定堆栈名称或 ARN。您还可以指定要用作此偏差检测操作的筛选条件的任何特定资源的逻辑 ID。

   ```
   aws cloudformation detect-stack-drift --stack-name my-stack-with-resource-drift
   ```

   输出：

   ```
   {
       "StackDriftDetectionId": "624af370-311a-11e8-b6b7-500cexample"
   }
   ```

1. 由于堆栈偏差检测操作可能会长时间运行，因此请使用 **describe-stack-drift-detection-status** 来监控偏差操作的状态。此命令获取 **detect-stack-drift** 命令返回的堆栈偏移检测 ID。

   在下面的示例中，我们采用了上面的 **detect-stack-drift** 示例返回的堆栈偏差检测 ID，并将其作为参数传递给 **describe-stack-drift-detection-status**。该参数返回操作详细信息，以显示偏差检测操作已完成，单个堆栈资源已偏离，并且整个堆栈被视为已因此偏离。

   ```
   aws cloudformation describe-stack-drift-detection-status --stack-drift-detection-id 624af370-311a-11e8-b6b7-500cexample
   ```

   输出：

   ```
   {
       "StackId": "arn:aws:cloudformation:us-east-1:099908667365:stack/my-stack-with-resource-drift/489e5570-df85-11e7-a7d9-50example", 
       "StackDriftDetectionId": "624af370-311a-11e8-b6b7-500cexample", 
       "StackDriftStatus": "DRIFTED", 
       "Timestamp": "2018-03-26T17:23:22.279Z", 
       "DetectionStatus": "DETECTION_COMPLETE", 
       "DriftedStackResourceCount": 1
   }
   ```

1. 堆栈偏差检测操作完成后，使用 **describe-stack-resource-drifts** 命令可查看结果，包括已偏离的资源的实际和预期属性值。

   以下示例使用 `--stack-resource-drift-status-filters` 选项来请求已修改或删除的资源的堆栈偏差信息。该请求返回有关一个已修改资源的信息，包括其值已更改的两个属性的详细信息。不会删除任何资源。

   ```
   aws cloudformation describe-stack-resource-drifts --stack-name my-stack-with-resource-drift --stack-resource-drift-status-filters MODIFIED DELETED
   ```

   输出：

   ```
   {
       "StackResourceDrifts": [
           {
               "StackId": "arn:aws:cloudformation:us-east-1:099908667365:stack/my-stack-with-resource-drift/489e5570-df85-11e7-a7d9-50example", 
               "ActualProperties": "{\"ReceiveMessageWaitTimeSeconds\":0,\"DelaySeconds\":120,\"RedrivePolicy\":{\"deadLetterTargetArn\":\"arn:aws:sqs:us-east-1:099908667365:my-stack-with-resource-drift-DLQ-1BCY7HHD5QIM3\",\"maxReceiveCount\":12},\"MessageRetentionPeriod\":345600,\"MaximumMessageSize\":262144,\"VisibilityTimeout\":60,\"QueueName\":\"my-stack-with-resource-drift-Queue-494PBHCO76H4\"}", 
               "ResourceType": "AWS::SQS::Queue", 
               "Timestamp": "2018-03-26T17:23:34.489Z", 
               "PhysicalResourceId": "https://sqs.us-east-1.amazonaws.com/099908667365/my-stack-with-resource-drift-Queue-494PBHCO76H4", 
               "StackResourceDriftStatus": "MODIFIED", 
               "ExpectedProperties": "{\"ReceiveMessageWaitTimeSeconds\":0,\"DelaySeconds\":20,\"RedrivePolicy\":{\"deadLetterTargetArn\":\"arn:aws:sqs:us-east-1:099908667365:my-stack-with-resource-drift-DLQ-1BCY7HHD5QIM3\",\"maxReceiveCount\":10},\"MessageRetentionPeriod\":345600,\"MaximumMessageSize\":262144,\"VisibilityTimeout\":60,\"QueueName\":\"my-stack-with-resource-drift-Queue-494PBHCO76H4\"}", 
               "PropertyDifferences": [
                   {
                       "PropertyPath": "/DelaySeconds", 
                       "ActualValue": "120", 
                       "ExpectedValue": "20", 
                       "DifferenceType": "NOT_EQUAL"
                   }, 
                   {
                       "PropertyPath": "/RedrivePolicy/maxReceiveCount", 
                       "ActualValue": "12", 
                       "ExpectedValue": "10", 
                       "DifferenceType": "NOT_EQUAL"
                   }
               ], 
               "LogicalResourceId": "Queue"
           }
       ]
   }
   ```

# 在单个堆栈资源上检测偏差
<a name="detect-drift-resource"></a>

您可以在堆栈中的特定资源上检测偏差，而不是在整个堆栈上。当您只需要再次确定特定资源现在是否与其预期的模板配置匹配时，这尤其有用。

当在资源上执行偏差检测时，CloudFormation 还会更新整体堆栈偏差状态和**上一次偏差检查时间**（如果适用）。例如，假设堆栈的偏差状态为 `IN_SYNC`。您让 CloudFormation 对该堆栈中包含的一个或多个资源执行偏差检测，CloudFormation 检测到这些资源中的一个或多个已偏离。CloudFormation 将堆栈偏差状态更新为 `DRIFTED`。相反，假设您有一个偏差状态为 `DRIFTED` 的堆栈，因为只有一个偏离的资源。如果您将该资源设置回其预期的属性值，然后再次在该资源上检测偏差，则 CloudFormation 会将资源偏差状态和堆栈偏差状态更新为 `IN_SYNC`，而无需您再次在整个堆栈上检测偏差。

**使用 AWS 管理控制台 在单个资源上检测偏差**

1. 通过以下网址打开 CloudFormation 控制台：[https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/)。

1. 从堆栈列表中，选择包含所需资源的堆栈。CloudFormation 会显示该堆栈的堆栈详细信息。

1. 在左侧导航窗格中的**堆栈**下，选择**堆栈操作**，然后选择**检测偏差**。

1. 在 **Resource drift status (资源偏差状态)** 下面，选择所需资源，然后选择 **Detect drift for resource (检测资源偏差)**。

   CloudFormation 在所选资源上执行偏差检测。如果成功，CloudFormation 会更新资源的偏差状态，并在必要时更新整体堆栈偏差状态。CloudFormation 还会更新上次对资源以及整个堆栈进行偏差检测时的时间戳。如果资源已被修改，则 CloudFormation 会显示有关资源的预期和当前属性值的详细偏差信息。

1. 查看资源的偏差检测结果。

   1. 查看已修改资源的详细信息。

     1. 选定已修改的资源，选择 **View drift details**（查看偏差详细信息）。

       CloudFormation 显示该资源的偏差详细信息，包括资源的预期和当前属性值，以及两者之间的任何区别。

       要突出显示区别，请在**区别**部分中选择属性名称。
       + 添加的属性在 **Details**（详细信息）部分的 **Current**（当前）列中以绿色突出显示。
       + 删除的属性在 **Details**（详细信息）部分的 **Expected**（预期）列中以红色突出显示。
       + 其值已更改的属性在 **Expected (预期)** 和 **Current (当前)** 列中以黄色突出显示。  
![\[偏差详细信息页面上的资源偏差状态部分，其中包含堆栈中支持偏差检测的每个资源的偏差信息。详细信息包括偏差状态以及预期的和当前的属性值。\]](http://docs.aws.amazon.com/zh_cn/AWSCloudFormation/latest/UserGuide/images/console-stacks-drifts-drift-details-differences-1.png)

**使用 AWS CLI 在单个资源上检测偏差**
+ 
**重要**  
查看堆栈资源的**上次偏差检查时间**，并确认它早于资源偏差结果中显示的时间戳，以防止使用过时的数据。

  要在使用 AWS CLI 的单个资源上检测偏差，使用 **detect-stack-resource-drift** 命令。指定资源的逻辑 ID，以及包含它的堆栈。

  以下示例在特定堆栈资源 `my-drifted-resource` 上运行偏差检测操作。该响应返回确认资源已被修改的信息，包括其值已更改的两个属性的详细信息。

  ```
  aws cloudformation detect-stack-resource-drift \
      --stack-name my-stack-with-resource-drift \
      --logical-resource-id my-drifted-resource
  ```

  输出：

  ```
  {
      "StackResourceDrift": {
          "StackId": "arn:aws:cloudformation:us-east-1:099908667365:stack/my-stack-with-resource-drift/489e5570-df85-11e7-a7d9-50example", 
          "ActualProperties": "{\"ReceiveMessageWaitTimeSeconds\":0,\"DelaySeconds\":120,\"RedrivePolicy\":{\"deadLetterTargetArn\":\"arn:aws:sqs:us-east-1:099908667365:my-stack-with-resource-drift-DLQ-1BCY7HHD5QIM3\",\"maxReceiveCount\":12},\"MessageRetentionPeriod\":345600,\"MaximumMessageSize\":262144,\"VisibilityTimeout\":60,\"QueueName\":\"my-stack-with-resource-drift-Queue-494PBHCO76H4\"}", 
          "ResourceType": "AWS::SQS::Queue", 
          "Timestamp": "2018-03-26T18:54:28.462Z", 
          "PhysicalResourceId": "https://sqs.us-east-1.amazonaws.com/099908667365/my-stack-with-resource-drift-Queue-494PBHCO76H4", 
          "StackResourceDriftStatus": "MODIFIED", 
          "ExpectedProperties": "{\"ReceiveMessageWaitTimeSeconds\":0,\"DelaySeconds\":20,\"RedrivePolicy\":{\"deadLetterTargetArn\":\"arn:aws:sqs:us-east-1:099908667365:my-stack-with-resource-drift-DLQ-1BCY7HHD5QIM3\",\"maxReceiveCount\":10},\"MessageRetentionPeriod\":345600,\"MaximumMessageSize\":262144,\"VisibilityTimeout\":60,\"QueueName\":\"my-stack-with-resource-drift-Queue-494PBHCO76H4\"}", 
          "PropertyDifferences": [
              {
                  "PropertyPath": "/DelaySeconds", 
                  "ActualValue": "120", 
                  "ExpectedValue": "20", 
                  "DifferenceType": "NOT_EQUAL"
              }, 
              {
                  "PropertyPath": "/RedrivePolicy/maxReceiveCount", 
                  "ActualValue": "12", 
                  "ExpectedValue": "10", 
                  "DifferenceType": "NOT_EQUAL"
              }
          ], 
          "LogicalResourceId": "my-drifted-resource"
      }
  }
  ```

# 通过导入操作消除偏差
<a name="resource-import-resolve-drift"></a>

在某些情况下，资源的配置可能已偏离其预期配置，而您希望接受新配置作为预期配置。在大多数情况下，您可以通过使用新配置更新堆栈模板中的资源定义来消除偏差结果，然后执行堆栈更新。但是，如果新配置更新了需要替换的资源属性，则在堆栈更新期间将重新创建该资源。如果要保留现有资源，则可以使用资源导入功能来更新资源并消除偏差结果，而不会导致替换资源。

通过导入操作消除资源偏差的过程包括以下基本步骤：
+ [将设置为 Retain 的 DeletionPolicy 属性添加到资源中](#resource-import-resolve-drift-console-step-01-update-stack)。这可确保在从堆栈中移除现有资源时，保留而不是删除该资源。
+ [从模板中移除资源并运行堆栈更新操作](#resource-import-resolve-drift-console-step-02-remove-drift)。这将从堆栈中移除资源，但不会删除它。
+ [描述资源在堆栈模板中的实际状态，然后将现有资源导入回堆栈](#resource-import-resolve-drift-console-step-03-update-template)。这会将资源添加回堆栈中，并消除导致了偏差结果的属性差异。

有关资源导入的更多信息，请参阅[手动将 AWS 资源导入 CloudFormation 堆栈](import-resources-manually.md)。有关支持导入的资源列表，请参阅[资源类型支持](resource-import-supported-resources.md)。

在此示例中，我们使用以下名为 `templateToImport.json` 的模板。

------
#### [ Example JSON ]

```
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "Import test",
    "Resources": {
         "ServiceTable":{
           "Type":"AWS::DynamoDB::Table",
           "Properties":{
              "TableName":"Service",
              "AttributeDefinitions":[
                 {
                    "AttributeName":"key",
                    "AttributeType":"S"
                 }
              ],
              "KeySchema":[
                 {
                    "AttributeName":"key",
                    "KeyType":"HASH"
                 }
              ],
              "BillingMode": "PROVISIONED",
              "ProvisionedThroughput":{
                 "ReadCapacityUnits":5,
                 "WriteCapacityUnits":1
              }
           }
        },
        "GamesTable": {
            "Type": "AWS::DynamoDB::Table",
            "Properties": {
                "TableName": "Games",
                "AttributeDefinitions": [
                    {
                        "AttributeName": "key",
                        "AttributeType": "S"
                    }
                ],
                "KeySchema": [
                    {
                        "AttributeName": "key",
                        "KeyType": "HASH"
                    }
                ],
                "BillingMode": "PROVISIONED",
                "ProvisionedThroughput": {
                    "ReadCapacityUnits": 5,
                    "WriteCapacityUnits": 1
                }
            }
        }
    }
}
```

------
#### [ Example YAML ]

```
AWSTemplateFormatVersion: 2010-09-09
Description: Import test
Resources:
  ServiceTable:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: Service
      AttributeDefinitions:
        - AttributeName: key
          AttributeType: S
      KeySchema:
        - AttributeName: key
          KeyType: HASH
      BillingMode: PROVISIONED
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 1
  GamesTable:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: Games
      AttributeDefinitions:
        - AttributeName: key
          AttributeType: S
      KeySchema:
        - AttributeName: key
          KeyType: HASH
      BillingMode: PROVISIONED
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 1
```

------

在此示例中，我们假设用户更改了 CloudFormation 之外的资源。运行偏差检测后，我们发现 `GamesTable` 的 `BillingMode` 已修改为 `PAY_PER_REQUEST`。有关偏差检测的更多信息，请参阅[使用偏移检测功能检测堆栈和资源的非托管配置更改](using-cfn-stack-drift.md)。

![\[偏差结果在控制台中显示预期结果和实际结果。\]](http://docs.aws.amazon.com/zh_cn/AWSCloudFormation/latest/UserGuide/images/drift-results-gamestable.png)


我们的堆栈现在已经过时，我们的资源处于活动状态，但我们希望保留预期的资源配置。为此，我们可以通过导入操作来消除偏差，而不会中断服务。

## 使用 CloudFormation 控制台通过导入操作消除偏差
<a name="resource-import-resolve-drift-console"></a>

### 步骤 1：使用 Retain 删除策略更新堆栈
<a name="resource-import-resolve-drift-console-step-01-update-stack"></a>

**使用带有 `Retain` 选项的 `DeletionPolicy` 属性更新堆栈**

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

1. 在**堆栈**页面上，选择已偏差的堆栈。

1. 选择**更新**，然后从堆栈详细信息窗格中选择**替换当前模板**。

1. 在**指定模板**页面上，使用下列方法之一提供更新的模板，其中包含带有 `Retain` 选项的 `DeletionPolicy` 属性：
   + 选择 **Amazon S3 URL**，然后在文本框中指定您的模板的 URL。
   + 选择 **Upload a template file (上传模板文件)**，然后浏览您的模板。

   然后选择**下一步**。

1. 查看**指定堆栈详细信息**页面，然后选择**下一步**。

1. 查看**配置堆栈选项**页面，然后选择**下一步**。

1. 在**查看 *stack-name*** 页面上，选择**更新堆栈**。

*结果*：在堆栈的**事件**页面上，状态为 `UPDATE_COMPLETE`。

要在不中断服务的情况下通过导入操作消除偏差，请为要从堆栈中移除的资源指定 `Retain` [DeletionPolicy](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-attribute-deletionpolicy.html)。在以下示例中，我们向 `GamesTable` 资源添加了一个设置为 `Retain` 的 [DeletionPolicy](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-attribute-deletionpolicy.html) 属性。

------
#### [ Example JSON ]

```
    "GamesTable": {
        "Type": "AWS::DynamoDB::Table",
        "DeletionPolicy": "Retain",
        "Properties": {
            "TableName": "Games",
```

------
#### [ Example YAML ]

```
  GamesTable:
    Type: AWS::DynamoDB::Table
    DeletionPolicy: Retain
    Properties:
      TableName: Games
```

------

### 步骤 2：移除偏差的资源、相关参数和输出
<a name="resource-import-resolve-drift-console-step-02-remove-drift"></a>

**移除偏差的资源、相关参数和输出**

1. 选择**更新**，然后从堆栈详细信息窗格中选择**替换当前模板**。

1. 在**指定模板**页面上，使用下列方法之一提供更新的模板，该模板的资源、相关参数和输出已从堆栈模板中移除：
   + 选择 **Amazon S3 URL**，然后在文本框中指定您的模板的 URL。
   + 选择 **Upload a template file (上传模板文件)**，然后浏览您的模板。

   然后选择**下一步**。

1. 查看**指定堆栈详细信息**页面，然后选择**下一步**。

1. 查看**配置堆栈选项**页面，然后选择**下一步**。

1. 在**查看 *stack-name*** 页面上，选择**更新堆栈**。

*结果*：**逻辑 ID** `GamesTable` 在堆栈的**事件**页面上具有状态 `DELETE_SKIPPED`。

等待 CloudFormation 完成堆栈更新操作。堆栈更新操作完成后，从堆栈模板中移除资源、相关参数和输出。然后，导入更新后的模板。完成这些操作后，示例模板现在如下所示。

------
#### [ Example JSON ]

```
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "Import test",
    "Resources": {
         "ServiceTable":{
           "Type":"AWS::DynamoDB::Table",
           "Properties":{
              "TableName":"Service",
              "AttributeDefinitions":[
                 {
                    "AttributeName":"key",
                    "AttributeType":"S"
                 }
              ],
              "KeySchema":[
                 {
                    "AttributeName":"key",
                    "KeyType":"HASH"
                 }
              ],
              "BillingMode": "PROVISIONED",
              "ProvisionedThroughput":{
                 "ReadCapacityUnits":5,
                 "WriteCapacityUnits":1
              }
           }
        }
    }
}
```

------
#### [ Example YAML ]

```
AWSTemplateFormatVersion: 2010-09-09
Description: Import test
Resources:
  ServiceTable:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: Service
      AttributeDefinitions:
        - AttributeName: key
          AttributeType: S
      KeySchema:
        - AttributeName: key
          KeyType: HASH
      BillingMode: PROVISIONED
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 1
```

------

### 步骤 3：更新模板以匹配资源的实时状态
<a name="resource-import-resolve-drift-console-step-03-update-template"></a>

**更新模板以匹配资源的实时状态**

1. 要导入更新后的模板，请选择**堆栈操作**，然后选择**将资源导入到堆栈**。  
![\[控制台中的 Import resources into stack (将资源导入到堆栈) 选项。\]](http://docs.aws.amazon.com/zh_cn/AWSCloudFormation/latest/UserGuide/images/stack-actions-import.png)

1. 在**导入概述**页面上，查看在该操作期间需要提供的内容列表，然后选择**下一步**。

1. 在**指定模板**页面上，使用下列方法之一提供更新的模板：
   + 选择 **Amazon S3 URL**，然后在文本框中指定您的模板的 URL。
   + 选择 **Upload a template file (上传模板文件)**，然后浏览您的模板。

   然后选择**下一步**。

1. 在 **Identify resources**（标识资源）页面上，标识每个目标资源。有关更多信息，请参阅 [资源标识符](import-resources-manually.md#resource-import-identifiers-unique-ids)。

   1. 在 **Identifier property (标识符属性)** 下面，选择资源标识符的类型。例如，`TableName` 属性标识 `AWS::DynamoDB::Table` 资源。

   1. 在**标识符值**下，输入实际属性值。在示例模板中，`GamesTable` 资源的 `TableName` 为 `Games`。

   1. 选择**下一步**。

1. 查看**指定堆栈详细信息**页面，然后选择**下一步**。

1. 在**导入概述**页面上，查看正在导入的资源，然后选择**导入资源**。这会将 `AWS::DynamoDB::Table` 资源类型导入回您的堆栈中。

*结果*：在此示例中，我们通过导入操作消除了资源偏差，而不会中断服务。您可以在 CloudFormation 控制台的“Events (事件)”选项卡中检查导入操作的进度。导入的资源将具有 `IMPORT_COMPLETE` 状态，后跟 `CREATE_COMPLETE` 状态，并且**资源导入完成**作为状态原因。

等待 CloudFormation 完成堆栈更新操作。堆栈更新操作完成后，更新模板以匹配资源的实际偏差状态。例如，`BillingMode` 将设置为 `PAY_PER_REQUEST`，`ReadCapacityUnits` 和 `WriteCapacityUnits` 将设置为 `0`。

------
#### [ Example JSON ]

```
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "Import test",
    "Resources": {
         "ServiceTable":{
           "Type":"AWS::DynamoDB::Table",
           "Properties":{
              "TableName":"Service",
              "AttributeDefinitions":[
                 {
                    "AttributeName":"key",
                    "AttributeType":"S"
                 }
              ],
              "KeySchema":[
                 {
                    "AttributeName":"key",
                    "KeyType":"HASH"
                 }
              ],
              "BillingMode": "PROVISIONED",
              "ProvisionedThroughput":{
                 "ReadCapacityUnits":5,
                 "WriteCapacityUnits":1
              }
           }
        },
        "GamesTable": {
            "Type": "AWS::DynamoDB::Table",
            "DeletionPolicy": "Retain",
            "Properties": {
                "TableName": "Games",
                "AttributeDefinitions": [
                    {
                        "AttributeName": "key",
                        "AttributeType": "S"
                    }
                ],
                "KeySchema": [
                    {
                        "AttributeName": "key",
                        "KeyType": "HASH"
                    }
                ],
                "BillingMode": "PAY_PER_REQUEST",
                "ProvisionedThroughput": {
                    "ReadCapacityUnits": 0,
                    "WriteCapacityUnits": 0
                }
            }
        }
    }
}
```

------
#### [ Example YAML ]

```
AWSTemplateFormatVersion: 2010-09-09
Description: Import test
Resources:
  ServiceTable:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: Service
      AttributeDefinitions:
        - AttributeName: key
          AttributeType: S
      KeySchema:
        - AttributeName: key
          KeyType: HASH
      BillingMode: PROVISIONED
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 1
  GamesTable:
    Type: AWS::DynamoDB::Table
    DeletionPolicy: Retain
    Properties:
      TableName: Games
      AttributeDefinitions:
        - AttributeName: key
          AttributeType: S
      KeySchema:
        - AttributeName: key
          KeyType: HASH
      BillingMode: PAY_PER_REQUEST
      ProvisionedThroughput:
        ReadCapacityUnits: 0
        WriteCapacityUnits: 0
```

------