

# 对 CloudFormation StackSets 进行偏差检测
<a name="stacksets-drift"></a>

即使在您通过 CloudFormation 管理堆栈及其包含的资源时，用户也可以在 CloudFormation 外部更改这些资源。用户可以使用创建资源的底层服务直接编辑资源。通过对 StackSet 执行偏移检测，您可以确定属于该 StackSet 的任何堆栈实例是否与它们的预期配置不同或*已偏移*。

**Topics**
+ [CloudFormation 如何对 StackSet 执行偏移检测](#stacksets-drift-how)
+ [检测 StackSet 上的偏移（控制台）](#stacksets-drift-console-procedure)
+ [检测 StackSet 上的偏移（Amazon CLI）](#stacksets-drift-cli-procedure)
+ [停止对 StackSet 的偏移检测](#stacksets-drift-stop)

## CloudFormation 如何对 StackSet 执行偏移检测
<a name="stacksets-drift-how"></a>

在 CloudFormation 对 StackSet 执行偏移检测时，它对与 StackSet 中的每个堆栈实例关联的堆栈执行偏移检测。为此，CloudFormation 将堆栈中的每个资源的当前状态与该资源的预期状态进行比较，该状态是堆栈的模板以及任何指定的输入参数中定义的。如果资源的当前状态不同于预期状态，则认为该资源已偏离。如果堆栈中的一个或多个资源已偏离，则将堆栈本身视为已偏离，并将与堆栈关联的堆栈实例也视为已偏离。如果 StackSet 中的一个或多个堆栈实例已偏移，则将 StackSet 本身视为已偏移。

偏差检测确定非托管更改；即，在 CloudFormation 外部对堆栈进行的更改。直接通过 CloudFormation 对堆栈进行的更改（而不是在 StackSet 级别）不会被视为偏移。例如，假设您具有一个与 StackSet 的堆栈实例关联的堆栈。如果您使用 CloudFormation 更新该堆栈以使用不同的模板，则不会将其视为偏移，即使该堆栈现在具有与属于 StackSet 的任何其他堆栈不同的模板。这是因为，该堆栈仍与它在 CloudFormation 中的预期模板和参数配置匹配。

有关 CloudFormation 如何对堆栈执行偏差检测的详细信息，请参阅[使用偏移检测功能检测堆栈和资源的非托管配置更改](using-cfn-stack-drift.md)。

由于分别 CloudFormation 对每个堆栈执行偏差检测，因此，它在确定堆栈是否偏离时考虑任何覆盖的参数值。有关在堆栈实例中覆盖模板参数的更多信息，请参阅[覆盖 CloudFormation StackSet 中的堆栈参数值](stackinstances-override.md)。

如果[直接](using-cfn-stack-drift.md)对与堆栈实例关联的堆栈执行偏差检测，则无法在 **StackSets** 控制台页面中查看这些偏差结果。

## 检测 StackSet 上的偏移（控制台）
<a name="stacksets-drift-console-procedure"></a>

**检测 StackSet 上的偏移**

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

1. 在 **StackSet** 页面上，选择要执行偏移检测的 StackSet。

1. 从 **Actions (操作)** 菜单中，选择 **Detect drifts (检测偏差)**。

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

1. 可选：要监控偏差检测操作进度，请执行以下操作：

   1. 选择 StackSet 名称以显示 **Stackset 详细信息**页面。

   1. 选择 **Operations (操作)** 选项卡，选择偏差检测操作，然后选择 **View drift details (查看偏差详细信息)**。

   CloudFormation 显示 **Operation details** (操作详细信息) 对话框。

1. 请耐心等待，直到 CloudFormation 完成偏差检测操作。偏移检测操作完成后，CloudFormation 会更新堆栈的**偏移状态**和**上次偏移检查时间**。这些字段在所选 StackSet 的 **StackSet 详细信息**页面的**概述**选项卡上列出。

   偏移检测操作可能需要一些时间，具体取决于 StackSet 中包含的堆栈实例数量以及 StackSet 中包含的资源数量。您一次只能在一个 StackSet 上运行一个偏移检测操作。即使您关闭信息栏，CloudFormation 也会继续执行偏差检测操作。

1. 要查看 StackSet 中的堆栈实例的偏移检测结果，请选择**堆栈实例**选项卡。

   **Stack name (堆栈名称)** 列列出与每个堆栈实例关联的堆栈的名称，**Drift status (偏差状态)** 列列出该堆栈的偏差状态。如果堆栈的一个或多个资源已偏离，则认为堆栈已偏离。

1. 要查看与特定堆栈实例关联的堆栈的偏差检测结果，请执行以下操作：

   1. 选择**操作**选项卡。

   1. 选择要查看其偏差检测结果的偏差操作。拆分面板将显示堆栈实例状态和所选操作的原因。对于偏差操作，状态原因列显示堆栈实例的偏差状态。

   1. 选择要查看其偏差详细信息的堆栈实例，然后选择**查看资源偏差**。在**资源偏差**页面上的**资源偏差状态**中，会列出每个堆栈资源及其偏差状态，以及最后一次在资源上启动偏差检测的时间。将会显示每个资源的逻辑 ID 和物理 ID，以帮助您识别它们。

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

   查看已修改资源的详细信息：

   1. 选定资源后，选择**查看偏差详细信息**。

     CloudFormation 会显示该资源的偏差详细信息页面。此页面列出资源的差异。其中还列出资源的预期和当前属性值。
**注意**  
如果堆栈所属的区域和账户与您当前登录的地区和账户不同，则**检测偏差**按钮将被禁用，您将无法查看详细信息。

## 检测 StackSet 上的偏移（Amazon CLI）
<a name="stacksets-drift-cli-procedure"></a>

要使用 Amazon CLI 在整个堆栈上检测偏差，请使用以下步骤：

**检测 StackSet 上的偏移**

1. 使用 [https://docs.amazonaws.cn/cli/latest/reference/cloudformation/detect-stack-set-drift.html](https://docs.amazonaws.cn/cli/latest/reference/cloudformation/detect-stack-set-drift.html) 命令检测整个 StackSet 及其关联堆栈实例上的偏移。

   以下示例中，对 `stack-set-drift-example` StackSet 启动偏移检测。

   ```
   aws cloudformation detect-stack-set-drift \
       --stack-set-name stack-set-drift-example
   ```

   输出：

   ```
   {
       "OperationId": "c36e44aa-3a83-411a-b503-cb611example"
   }
   ```

1. 由于 StackSet 偏移检测操作可能是长时间运行的操作，因此，请使用 [https://docs.amazonaws.cn/cli/latest/reference/cloudformation/describe-stack-set-operation.html](https://docs.amazonaws.cn/cli/latest/reference/cloudformation/describe-stack-set-operation.html) 命令监控偏移操作的状态。该命令使用 **detect-stack-set-drift** 命令返回的 StackSet 操作 ID。

   以下示例使用上一示例中的操作 ID 返回有关 StackSet 偏移检测操作的信息。在此示例中，该操作仍在运行。在与该 StackSet 关联的七个堆栈实例中，发现一个堆栈实例已偏移，两个实例正在进行同步，而其余四个堆栈实例仍在进行偏移检测。由于一个实例已偏移，StackSet 本身的偏移状态现在为 `DRIFTED`。

   ```
   aws cloudformation describe-stack-set-operation \
       --stack-set-name stack-set-drift-example \
       --operation-id c36e44aa-3a83-411a-b503-cb611example
   ```

   输出：

   ```
   {
       "StackSetOperation": {
           "Status": "RUNNING",
           "AdministrationRoleARN": "arn:aws:iam::123456789012:role/AWSCloudFormationStackSetAdministrationRole",
           "OperationPreferences": {
               "RegionOrder": []
           },
           "ExecutionRoleName": "AWSCloudFormationStackSetExecutionRole",
           "StackSetDriftDetectionDetails": {
               "DriftedStackInstancesCount": 1,
               "TotalStackInstancesCount": 7,
               "LastDriftCheckTimestamp": "2019-12-04T20:34:28.543Z",
               "InSyncStackInstancesCount": 2,
               "InProgressStackInstancesCount": 4,
               "DriftStatus": "DRIFTED",
               "FailedStackInstancesCount": 0
           },
           "Action": "DETECT_DRIFT",
           "CreationTimestamp": "2019-12-04T20:33:13.673Z",
           "StackSetId": "stack-set-drift-example:bd1f4017-d4f9-432e-a73f-8c22example",
           "OperationId": "c36e44aa-3a83-411a-b503-cb611example"
       }
   }
   ```

   该示例稍后执行相同的命令，以显示在偏差检测操作完成后返回的信息。在与该 StackSet 关联的总共 7 个堆栈实例中，有两个实例已偏移，从而使 StackSet 本身的偏移状态显示为 `DRIFTED`。

   ```
   aws cloudformation describe-stack-set-operation \
       --stack-set-name stack-set-drift-example \
       --operation-id c36e44aa-3a83-411a-b503-cb611example
   ```

   输出：

   ```
   {
       "StackSetOperation": {
           "Status": "SUCCEEDED",
           "AdministrationRoleARN": "arn:aws:iam::123456789012:role/AWSCloudFormationStackSetAdministrationRole",
           "OperationPreferences": {
               "RegionOrder": []
           } 
           "ExecutionRoleName": "AWSCloudFormationStackSetExecutionRole",
           "EndTimestamp": "2019-12-04T20:37:32.829Z",
           "StackSetDriftDetectionDetails": {
               "DriftedStackInstancesCount": 2,
               "TotalStackInstancesCount": 7,
               "LastDriftCheckTimestamp": "2019-12-04T20:36:55.612Z",
               "InSyncStackInstancesCount": 5,
               "InProgressStackInstancesCount": 0,
               "DriftStatus": "DRIFTED",
               "FailedStackInstancesCount": 0
           },
           "Action": "DETECT_DRIFT",
           "CreationTimestamp": "2019-12-04T20:33:13.673Z",
           "StackSetId": "stack-set-drift-example:bd1f4017-d4f9-432e-a73f-8c22example",
           "OperationId": "c36e44aa-3a83-411a-b503-cb611example"
       }
   }
   ```

1. 在 StackSet 偏移检测操作完成后，请使用 **describe-stack-set**、**list-stack-instances**、**describe-stack-instance** 和 **list-stack-instance-resource-drifts** 命令查看结果。

   [https://docs.amazonaws.cn/cli/latest/reference/cloudformation/describe-stack-set.html](https://docs.amazonaws.cn/cli/latest/reference/cloudformation/describe-stack-set.html) 命令包括 **describe-stack-set-operation** 命令返回的相同详细偏差信息。

   ```
   aws cloudformation describe-stack-set \
       --stack-set-name stack-set-drift-example
   ```

   输出：

   ```
   {
       "StackSet": {
           "Status": "ACTIVE",
           "Description": "Demonstration of drift detection on stack sets.",
           "Parameters": [],
           "Tags": [
               {
                   "Value": "Drift detection",
                   "Key": "Feature"
               }
           ], 
           "ExecutionRoleName": "AWSCloudFormationStackSetExecutionRole",
           "Capabilities": [],
           "AdministrationRoleARN": "arn:aws:iam::123456789012:role/AWSCloudFormationStackSetAdministrationRole",
           "StackSetDriftDetectionDetails": {
               "DriftedStackInstancesCount": 2,
               "TotalStackInstancesCount": 7,
               "LastDriftCheckTimestamp": "2019-12-04T20:36:55.612Z",
               "InProgressStackInstancesCount": 0,
               "DriftStatus": "DRIFTED",
               "DriftDetectionStatus": "COMPLETED",
               "InSyncStackInstancesCount": 5,
               "FailedStackInstancesCount": 0
           },
           "StackSetARN": "arn:aws:cloudformation:us-east-1:123456789012:stackset/stack-set-drift-example:bd1f4017-d4f9-432e-a73f-8c22example",
           "TemplateBody": [details omitted],
           "StackSetId": "stack-set-drift-example:bd1f4017-d4f9-432e-a73f-8c22ebexample",
           "StackSetName": "stack-set-drift-example"
       }
   }
   ```

   您可以使用 [https://docs.amazonaws.cn/cli/latest/reference/cloudformation/list-stack-instances.html](https://docs.amazonaws.cn/cli/latest/reference/cloudformation/list-stack-instances.html) 命令返回有关与 StackSet 关联的堆栈实例的摘要信息，包括每个堆栈实例的偏移状态。

   在本示例中，通过对示例 StackSet 执行 **list-stack-instances** 并将偏移状态筛选设置为 `DRIFTED`，我们可以确定哪两个堆栈实例具有 `DRIFTED` 偏移状态。

   ```
   aws cloudformation list-stack-instances \
       --stack-set-name stack-set-drift-example \
       --filters Name=DRIFT_STATUS,Values=DRIFTED
   ```

   输出：

   ```
   {
   "Summaries": [
           {
   "StackId": "arn:aws:cloudformation:eu-west-1:123456789012:stack/StackSet-stack-set-drift-example-b0fb6083-60c0-4e39-af15-2f071e0db90c/0e4f0940-16d4-11ea-93d8-0641cexample",
               "Status": "CURRENT",
               "Account": "012345678910",
               "Region": "eu-west-1",
               "LastDriftCheckTimestamp": "2019-12-04T20:37:32.687Z",
               "DriftStatus": "DRIFTED",
               "StackSetId": "stack-set-drift-example:bd1f4017-d4f9-432e-a73f-8c22eexample",
               "LastOperationId": "c36e44aa-3a83-411a-b503-cb611example"
           },
           {
               "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/StackSet-stack-set-drift-example-b7fde68e-e541-44c2-b33d-ef2e2988071a/008e6030-16d4-11ea-8090-12f89example",
               "Status": "CURRENT",
               "Account": "123456789012",
               "Region": "us-east-1",
               "LastDriftCheckTimestamp": "2019-12-04T20:34:28.275Z",
               "DriftStatus": "DRIFTED",
               "StackSetId": "stack-set-drift-example:bd1f4017-d4f9-432e-a73f-8c22eexample",
               "LastOperationId": "c36e44aa-3a83-411a-b503-cb611example"
           },
           
           [additional stack instances omitted]
    
       ]
   }
   ```

   [https://docs.amazonaws.cn/cli/latest/reference/cloudformation/describe-stack-instance.html](https://docs.amazonaws.cn/cli/latest/reference/cloudformation/describe-stack-instance.html) 命令也返回该信息，但仅为单个堆栈实例返回该信息，如以下示例所示。

   ```
   aws cloudformation describe-stack-instance \
       --stack-set-name stack-set-drift-example \
       --stack-instance-account 012345678910 --stack-instance-region us-east-1
   ```

   输出：

   ```
   {
       "StackInstance": {
           "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/StackSet-stack-set-drift-example-b7fde68e-e541-44c2-b33d-ef2e2988071a/008e6030-16d4-11ea-8090-12f89example",
           "Status": "CURRENT",
           "Account": "123456789012",
           "Region": "us-east-1",
           "ParameterOverrides": [],
           "DriftStatus": "DRIFTED",
           "LastDriftCheckTimestamp": "2019-12-04T20:34:28.275Z",
           "StackSetId": "stack-set-drift-example:bd1f4017-d4f9-432e-a73f-8c22eexample",
           "LastOperationId": "c36e44aa-3a83-411a-b503-cb611example"
       }
   }
   ```

1. 在确定哪些堆栈实例已偏离后，您可以使用有关 **list-stack-instances** 或 **describe-stack-instance** 命令返回的堆栈实例的信息以运行 [https://docs.amazonaws.cn/cli/latest/reference/cloudformation/list-stack-instance-resource-drifts.html](https://docs.amazonaws.cn/cli/latest/reference/cloudformation/list-stack-instance-resource-drifts.html) 命令。该命令会返回详细信息，说明对于特定偏差操作而言，堆栈中的哪些资源已产生偏差。

   以下示例使用 `--stack-instance-resource-drift-statuses` 参数来请求在上一个偏差操作示例中已修改或删除的资源的堆栈偏差信息。该请求会返回有关已修改的一个资源的信息，包括有关其中两个属性及其已更改值的详细信息。不会删除任何资源。

   ```
   aws cloudformation list-stack-instance-resource-drifts \
       --stack-set-name my-stack-set-with-resource-drift \
       --stack-instance-account 123456789012 \
       --stack-instance-region us-east-1 \
       --operation-id c36e44aa-3a83-411a-b503-cb611example \
       --stack-instance-resource-drift-statuses MODIFIED DELETED
   ```

   输出：

   ```
   {
       "Summaries": [
           {
               "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/my-stack-set-with-resource-drift/489e5570-df85-11e7-a7d9-50example",
               "ResourceType": "AWS::SQS::Queue",
               "Timestamp": "2018-03-26T17:23:34.489Z",
               "PhysicalResourceId": "https://sqs.us-east-1.amazonaws.com/123456789012/my-stack-with-resource-drift-Queue-494PBHCO76H4",
               "StackResourceDriftStatus": "MODIFIED",
               "PropertyDifferences": [
                   {
                       "PropertyPath": "/DelaySeconds",
                       "ActualValue": "120",
                       "ExpectedValue": "20",
                       "DifferenceType": "NOT_EQUAL"
                   },
                   {
                       "PropertyPath": "/RedrivePolicy/maxReceiveCount",
                       "ActualValue": "12",
                       "ExpectedValue": "10",
                       "DifferenceType": "NOT_EQUAL"
                   }
               ],
               "LogicalResourceId": "Queue"
           }
       ]
   }
   ```

## 停止对 StackSet 的偏移检测
<a name="stacksets-drift-stop"></a>

由于对 StackSet 的偏移检测可能是长时间运行的操作，因此，在某些情况下，您可能希望停止当前对 StackSet 运行的偏移检测操作。

**停止对 StackSet 的偏移检测（控制台）**

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

1. 在 **StackSet** 页面上，选择 StackSet 的名称。

   CloudFormation 将显示所选 StackSet 的 **StackSet 详细信息**页面。

1. 在 **StackSets details (堆栈集详细信息)** 页面上，选择 **Operations (操作)** 选项卡，然后选择偏差检测操作。

1. 选择 **Stop operation (停止操作)**。

**停止对 StackSet 的偏移检测（Amazon CLI）**
+ 使用 [https://docs.amazonaws.cn/cli/latest/reference/cloudformation/stop-stack-set-operation.html](https://docs.amazonaws.cn/cli/latest/reference/cloudformation/stop-stack-set-operation.html) 命令。您必须同时提供 StackSet 名称和偏移检测 StackSet 操作的操作 ID。

  ```
  aws cloudformation stop-stack-set-operation \
      --stack-set-name stack-set-drift-example \
      --operation-id 624af370-311a-11e8-b6b7-500cexample
  ```