

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 堆疊重構
<a name="stack-refactoring"></a>

透過堆疊重構，您可以重整 CloudFormation 堆疊中的資源，同時保留現有資源的屬性與資料。您可以在堆疊之間移動資源、將大型堆疊分割為較小的堆疊，或將多個堆疊合併為一個堆疊。

**Topics**
+ [堆疊重構的運作方式](#stack-refactoring-overview)
+ [堆疊重構考量事項](#stack-refactoring-considerations)
+ [先決條件](#stack-refactoring-prerequisites)
+ [重構堆疊 （主控台）](#stack-refactoring-console)
+ [重構堆疊 (AWS CLI)](#stack-refactoring-cli)
+ [資源限制](#stack-refactoring-resource-limitations)

## 堆疊重構的運作方式
<a name="stack-refactoring-overview"></a>

堆疊重構包含下列階段：

1. **評估目前的基礎設施** – 檢閱您現有的 CloudFormation 堆疊與資源，找出可進行堆疊重構的機會。

1. **規劃重構** – 定義資源的組織方式。考量資源相依性、命名慣例及運作限制。這些因素會影響後續的 CloudFormation 驗證。

1. **決定目的地堆疊** – 確定您要將資源重構至哪些堆疊。您可以在至少 2 個堆疊 （使用 主控台） 和最多 5 個堆疊 （使用 ) 之間移動資源 AWS CLI。資源可在巢狀堆疊之間移動。

1. **更新範本** – 變更 CloudFormation 範本，以反映規劃的變更，例如在範本間移動資源定義。您可在此程序期間重新命名邏輯 ID。

1. **建立堆疊重構** – 提供您要重構的堆疊名稱與範本清單。

1. **檢閱重構影響並解決任何衝突** – CloudFormation 會驗證您提供的範本，並檢查跨堆疊相依性、標籤更新有問題的資源類型，以及資源邏輯 ID 衝突。

   若驗證成功，CloudFormation 會產生執行期間即將執行的重構動作預覽。

   若驗證失敗，請解決偵測到的問題後重試。若有衝突，請提供資源邏輯 ID 映射，以顯示衝突資源的來源和目的地。

1. **執行重構** – 確認變更符合重構目標後，完成堆疊重構。

1. **監控** – 追蹤執行狀態，確保作業順利完成。

## 堆疊重構考量事項
<a name="stack-refactoring-considerations"></a>

重構堆疊時，請注意下列事項：
+ 堆疊重構僅限於重整現有資源。您無法在重構期間建立或刪除資源、修改資源組態，或變更或新增參數、條件或映射。若要進行這些變更，請先更新您的堆疊，然後執行堆疊重構。
+ 您無法將相同的資源重構入多個堆疊。
+ 若資源參考的虛擬參數 (例如 `AWS::StackName`) 在來源與目標堆疊中的數值不同，則無法對該資源進行重構。
+ CloudFormation 不支援空白堆疊。若重構會導致某個堆疊沒有資源，您必須先向該堆疊新增至少一項資源，再執行 [create-stack-refactor](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/create-stack-refactor.html)。可新增簡單資源，例如 `AWS::SNS::Topic` 或 `AWS::CloudFormation::WaitCondition`。例如：

  ```
  Resources:
    MySimpleSNSTopic:
      Type: AWS::SNS::Topic
      Properties:
        DisplayName: MySimpleTopic
  ```
+ 堆疊重構不支援已附加堆疊政策的堆疊，不論該政策允許或拒絕哪些操作。

## 先決條件
<a name="stack-refactoring-prerequisites"></a>

若要重構堆疊，您必須已建立修訂後的範本。

使用 [get-template](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/get-template.html) 命令，擷取您要重構的堆疊對應 CloudFormation 範本。

```
aws cloudformation get-template --stack-name Stack1
```

取得範本後，使用您偏好的整合式開發環境 (IDE) 更新範本，使其符合預期的結構與資源組織方式。

## 重構堆疊 （主控台）
<a name="stack-refactoring-console"></a>

使用下列程序來重構使用主控台的堆疊。

**重構堆疊**

1. 登入 AWS 管理主控台 並在 https：//[https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/) 開啟 CloudFormation 主控台。

1. 在畫面頂端的導覽列上，選擇 AWS 區域 堆疊所在的 。

1. 在左側導覽窗格中，選擇**堆疊重構**。

1. 在**堆疊重構**頁面上，選擇**開始堆疊重構**。

1. 針對**描述**，提供描述以協助您識別堆疊重構。然後選擇**下一步**。

1. 對於堆疊 1，請執行下列動作：

   1. 選擇**更新現有堆疊的範本**或**建立新堆疊**。

      如果您選擇**更新現有堆疊的範本**，請從清單中選擇現有的堆疊。或者，選擇**輸入堆疊 ARN** 以輸入現有堆疊的 ARN。

      如果您選擇**建立新堆疊**，請針對**堆疊名稱**提供新堆疊的名稱。

   1. 在**將現有範本取代為重構範本**下，選擇 **Amazon S3 URL** 或**上傳範本檔案**，以上傳 Stack 1 所需的範本。

   1. 選擇**下一步**。

1. 對於 Stack 2，請執行下列動作：

   1. 選擇**更新現有堆疊的範本**或**建立新堆疊**。

      如果您選擇**更新現有堆疊的範本**，請從清單中選擇現有的堆疊。或者，選擇**輸入堆疊 ARN** 以輸入現有堆疊的 ARN。

      如果您選擇**建立新堆疊**，請針對**堆疊名稱**提供新堆疊的名稱。

   1. 在**將現有範本取代為重構範本**下，選擇 **Amazon S3 URL** 或**上傳範本檔案**，以上傳 Stack 2 所需的範本。

   1. 選擇**下一步**。

1. 在**指定邏輯資源 ID 重新命名**頁面上，確定 CloudFormation 知道如何將顯示的任何資源映射至其正確的邏輯 IDs 來重構堆疊。作為堆疊重構的一部分，如果任何資源的邏輯 IDs已變更，您需要提供來源堆疊名稱、原始邏輯 ID、目的地堆疊名稱和重新命名的邏輯 ID 來指定其重新命名方式。在某些情況下，CloudFormation 主控台可能會自動偵測資源映射，您可以直接驗證預先填入的資源映射是否正確，然後再繼續。

1. 選擇**下一步**。

1. 在**檢閱和執行**頁面上，檢閱先前步驟中的所有選擇，並確認一切設定正確。

1. 當您準備好重構堆疊時，請選擇**執行堆疊重構**。

## 重構堆疊 (AWS CLI)
<a name="stack-refactoring-cli"></a>

用於堆疊重構的 AWS CLI 命令包括：
+ [create-stack-refactor](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/create-stack-refactor.html) 用於驗證和產生規劃變更的預覽。
+ [describe-stack-refactor](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-stack-refactor.html) 用於擷取堆疊重構操作的狀態與詳細資訊。
+ [execute-stack-refactor](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/execute-stack-refactor.html) 用於完成經驗證的堆疊重構操作。
+ [list-stack-refactors](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/list-stack-refactors.html) 用於列出您帳戶中所有堆疊重構操作及其目前狀態和基本資訊。
+ [list-stack-refactor-actions](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/list-stack-refactor-actions.html) 用於顯示 CloudFormation 在重構執行期間將對每個堆疊和資源執行的特定動作的預覽。

利用以下程序使用 AWS CLI重構堆疊。

**重構堆疊**

1. 使用 [create-stack-refactor](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/create-stack-refactor.html) 命令，並提供要重構的堆疊名稱與更新後的範本。加入 `--enable-stack-creation` 選項，讓 CloudFormation 可在新堆疊不存在時建立。

   ```
   aws cloudformation create-stack-refactor \
     --stack-definitions \
       StackName=Stack1,TemplateBody@=file://template1-updated.yaml \
       StackName=Stack2,TemplateBody@=file://template2-updated.yaml \
     --enable-stack-creation
   ```

   命令會傳回 `StackRefactorId`，後續步驟將會用到。

   ```
   {
       "StackRefactorId": "9c384f70-4e07-4ed7-a65d-fee5eb430841"
   }
   ```

   若範本驗證期間偵測到衝突 (可在下一個步驟確認)，請搭配 `--resource-mappings` 選項使用 [create-stack-refactor](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/create-stack-refactor.html) 命令。

   ```
   aws cloudformation create-stack-refactor \
     --stack-definitions \
       StackName=Stack1,TemplateBody@=file://template1-updated.yaml \
       StackName=Stack2,TemplateBody@=file://template2-updated.yaml \
     --enable-stack-creation \ 
     --resource-mappings file://resource-mapping.json
   ```

   以下是範例 `resource-mapping.json` 檔案。

   ```
   [
       {
           "Source": {
               "StackName": "Stack1",
               "LogicalResourceId": "MySNSTopic"
           },
           "Destination": {
               "StackName": "Stack2",
               "LogicalResourceId": "MyLambdaSNSTopic"
           }
       }
   ]
   ```

1. 使用 [describe-stack-refactor](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-stack-refactor.html) 命令來確定 `Status` 為 `CREATE_COMPLETE`。這表示驗證已完成。

   ```
   aws cloudformation describe-stack-refactor \
     --stack-refactor-id 9c384f70-4e07-4ed7-a65d-fee5eb430841
   ```

   輸出範例：

   ```
   {
       "StackRefactorId": "9c384f70-4e07-4ed7-a65d-fee5eb430841",
       "StackIds": [
           "arn:aws:cloudformation:us-east-1:123456789012:stack/Stack1/3e6a1ff0-94b1-11f0-aa6f-0a88d2e03acf",
           "arn:aws:cloudformation:us-east-1:123456789012:stack/Stack2/5da91650-94b1-11f0-81cf-0a23500e151b"
       ],
       "ExecutionStatus": "AVAILABLE",
       "Status": "CREATE_COMPLETE"
   }
   ```

1. 使用 [list-stack-refactor-actions](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/list-stack-refactor-actions.html) 命令，預覽即將執行的特定動作。

   ```
   aws cloudformation list-stack-refactor-actions \
     --stack-refactor-id 9c384f70-4e07-4ed7-a65d-fee5eb430841
   ```

   輸出範例：

   ```
   {
       "StackRefactorActions": [
           {
               "Action": "MOVE",
               "Entity": "RESOURCE",
               "PhysicalResourceId": "MyTestLambdaRole",
               "Description": "No configuration changes detected.",
               "Detection": "AUTO",
               "TagResources": [],
               "UntagResources": [],
               "ResourceMapping": {
                   "Source": {
                       "StackName": "arn:aws:cloudformation:us-east-1:123456789012:stack/Stack1/3e6a1ff0-94b1-11f0-aa6f-0a88d2e03acf",
                       "LogicalResourceId": "MyLambdaRole"
                   },
                   "Destination": {
                       "StackName": "arn:aws:cloudformation:us-east-1:123456789012:stack/Stack2/5da91650-94b1-11f0-81cf-0a23500e151b",
                       "LogicalResourceId": "MyLambdaRole"
                   }
               }
           },
           {
               "Action": "MOVE",
               "Entity": "RESOURCE",
               "PhysicalResourceId": "MyTestFunction",
               "Description": "Resource configuration changes will be validated during refactor execution.",
               "Detection": "AUTO",
               "TagResources": [
                   {
                       "Key": "aws:cloudformation:stack-name",
                       "Value": "Stack2"
                   },
                   {
                       "Key": "aws:cloudformation:logical-id",
                       "Value": "MyFunction"
                   },
                   {
                       "Key": "aws:cloudformation:stack-id",
                       "Value": "arn:aws:cloudformation:us-east-1:123456789012:stack/Stack2/5da91650-94b1-11f0-81cf-0a23500e151b"
                   }
               ],
               "UntagResources": [
                   "aws:cloudformation:stack-name",
                   "aws:cloudformation:logical-id",
                   "aws:cloudformation:stack-id"
               ],
               "ResourceMapping": {
                   "Source": {
                       "StackName": "arn:aws:cloudformation:us-east-1:123456789012:stack/Stack1/3e6a1ff0-94b1-11f0-aa6f-0a88d2e03acf",
                       "LogicalResourceId": "MyFunction"
                   },
                   "Destination": {
                       "StackName": "arn:aws:cloudformation:us-east-1:123456789012:stack/Stack2/5da91650-94b1-11f0-81cf-0a23500e151b",
                       "LogicalResourceId": "MyFunction"
                   }
               }
           }
       ]
   }
   ```

1. 檢閱並確認變更後，使用 [execute-stack-refactor](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/execute-stack-refactor.html) 命令來完成堆疊重構操作。

   ```
   aws cloudformation execute-stack-refactor \
     --stack-refactor-id 9c384f70-4e07-4ed7-a65d-fee5eb430841
   ```

1. 使用 [describe-stack-refactor](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-stack-refactor.html) 命令監控執行狀態。

   ```
   aws cloudformation describe-stack-refactor \
     --stack-refactor-id 9c384f70-4e07-4ed7-a65d-fee5eb430841
   ```

   輸出範例：

   ```
   {
       "StackRefactorId": "9c384f70-4e07-4ed7-a65d-fee5eb430841",
       "StackIds": [
           "arn:aws:cloudformation:us-east-1:123456789012:stack/Stack1/3e6a1ff0-94b1-11f0-aa6f-0a88d2e03acf",
           "arn:aws:cloudformation:us-east-1:123456789012:stack/Stack2/5da91650-94b1-11f0-81cf-0a23500e151b"
       ],
       "ExecutionStatus": "SUCCEEDED",
       "Status": "COMPLETE"
   }
   ```

## 資源限制
<a name="stack-refactoring-resource-limitations"></a>
+ 堆疊重構僅支援具有 `provisioningType` 為 `FULLY_MUTABLE` 的資源類型，您可以使用 [describe-type](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-type.html) 命令確認。
+ 建立重構時，CloudFormation 會驗證資源適用性，並在 [describe-stack-refactor](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-stack-refactor.html) 命令的輸出中回報所有不支援的資源。
+ 下列資源不支援堆疊重構：
  + `AWS::ACMPCA::Certificate`
  + `AWS::ACMPCA::CertificateAuthority`
  + `AWS::ACMPCA::CertificateAuthorityActivation`
  + `AWS::ApiGateway::BasePathMapping`
  + `AWS::ApiGateway::Method`
  + `AWS::AppConfig::ConfigurationProfile`
  + `AWS::AppConfig::Deployment`
  + `AWS::AppConfig::Environment`
  + `AWS::AppConfig::Extension`
  + `AWS::AppConfig::ExtensionAssociation`
  + `AWS::AppStream::DirectoryConfig`
  + `AWS::AppStream::StackFleetAssociation`
  + `AWS::AppStream::StackUserAssociation`
  + `AWS::AppStream::User`
  + `AWS::BackupGateway::Hypervisor`
  + `AWS::CertificateManager::Certificate`
  + `AWS::CloudFormation::CustomResource`
  + `AWS::CloudFormation::Macro`
  + `AWS::CloudFormation::WaitCondition`
  + `AWS::CloudFormation::WaitConditionHandle`
  + `AWS::CodeDeploy::DeploymentGroup`
  + `AWS::CodePipeline::CustomActionType`
  + `AWS::Cognito::UserPoolRiskConfigurationAttachment`
  + `AWS::Cognito::UserPoolUICustomizationAttachment`
  + `AWS::Cognito::UserPoolUserToGroupAttachment`
  + `AWS::Config::ConfigRule`
  + `AWS::Config::ConfigurationRecorder`
  + `AWS::Config::DeliveryChannel`
  + `AWS::DataBrew::Dataset`
  + `AWS::DataBrew::Job`
  + `AWS::DataBrew::Project`
  + `AWS::DataBrew::Recipe`
  + `AWS::DataBrew::Ruleset`
  + `AWS::DataBrew::Schedule`
  + `AWS::DataZone::DataSource`
  + `AWS::DataZone::Environment`
  + `AWS::DataZone::EnvironmentBlueprintConfiguration`
  + `AWS::DataZone::EnvironmentProfile`
  + `AWS::DataZone::Project`
  + `AWS::DataZone::SubscriptionTarget`
  + `AWS::DirectoryService::MicrosoftAD`
  + `AWS::DynamoDB::GlobalTable`
  + `AWS::EC2::CustomerGateway`
  + `AWS::EC2::EIP`
  + `AWS::EC2::LaunchTemplate`
  + `AWS::EC2::NetworkInterfacePermission`
  + `AWS::EC2::PlacementGroup`
  + `AWS::EC2::SpotFleet`
  + `AWS::EC2::VPCDHCPOptionsAssociation`
  + `AWS::EC2::VolumeAttachment`
  + `AWS::EMR::Cluster`
  + `AWS::EMR::InstanceFleetConfig`
  + `AWS::EMR::InstanceGroupConfig`
  + `AWS::ElastiCache::CacheCluster`
  + `AWS::ElastiCache::ReplicationGroup`
  + `AWS::ElastiCache::SecurityGroup`
  + `AWS::ElastiCache::SecurityGroupIngress`
  + `AWS::ElasticBeanstalk::ConfigurationTemplate`
  + `AWS::ElasticLoadBalancing::LoadBalancer`
  + `AWS::ElasticLoadBalancingV2::ListenerCertificate`
  + `AWS::Elasticsearch::Domain`
  + `AWS::FIS::ExperimentTemplate`
  + `AWS::Glue::Schema`
  + `AWS::GuardDuty::IPSet`
  + `AWS::GuardDuty::PublishingDestination`
  + `AWS::GuardDuty::ThreatIntelSet`
  + `AWS::IAM::AccessKey`
  + `AWS::IAM::UserToGroupAddition`
  + `AWS::ImageBuilder::Component`
  + `AWS::IoT::PolicyPrincipalAttachment`
  + `AWS::IoT::ThingPrincipalAttachment`
  + `AWS::IoTFleetWise::Campaign`
  + `AWS::IoTWireless::WirelessDeviceImportTask`
  + `AWS::Lambda::EventInvokeConfig`
  + `AWS::Lex::BotVersion`
  + `AWS::M2::Application`
  + `AWS::MSK::Configuration`
  + `AWS::MSK::ServerlessCluster`
  + `AWS::Maester::DocumentType`
  + `AWS::MediaTailor::Channel`
  + `AWS::NeptuneGraph::PrivateGraphEndpoint`
  + `AWS::Omics::AnnotationStore`
  + `AWS::Omics::ReferenceStore`
  + `AWS::Omics::SequenceStore`
  + `AWS::OpenSearchServerless::Collection`
  + `AWS::OpsWorks::App`
  + `AWS::OpsWorks::ElasticLoadBalancerAttachment`
  + `AWS::OpsWorks::Instance`
  + `AWS::OpsWorks::Layer`
  + `AWS::OpsWorks::Stack`
  + `AWS::OpsWorks::UserProfile`
  + `AWS::OpsWorks::Volume`
  + `AWS::PCAConnectorAD::Connector`
  + `AWS::PCAConnectorAD::DirectoryRegistration`
  + `AWS::PCAConnectorAD::Template`
  + `AWS::PCAConnectorAD::TemplateGroupAccessControlEntry`
  + `AWS::Panorama::PackageVersion`
  + `AWS::QuickSight::Theme`
  + `AWS::RDS::DBSecurityGroup`
  + `AWS::RDS::DBSecurityGroupIngress`
  + `AWS::Redshift::ClusterSecurityGroup`
  + `AWS::Redshift::ClusterSecurityGroupIngress`
  + `AWS::RefactorSpaces::Environment`
  + `AWS::RefactorSpaces::Route`
  + `AWS::RefactorSpaces::Service`
  + `AWS::RoboMaker::RobotApplication`
  + `AWS::RoboMaker::SimulationApplication`
  + `AWS::Route53::RecordSet`
  + `AWS::Route53::RecordSetGroup`
  + `AWS::SDB::Domain`
  + `AWS::SageMaker::InferenceComponen`
  + `AWS::ServiceCatalog::PortfolioPrincipalAssociation`
  + `AWS::ServiceCatalog::PortfolioProductAssociation`
  + `AWS::ServiceCatalog::PortfolioShare`
  + `AWS::ServiceCatalog::TagOptionAssociation`
  + `AWS::ServiceCatalogAppRegistry::AttributeGroupAssociation`
  + `AWS::ServiceCatalogAppRegistry::ResourceAssociation`
  + `AWS::StepFunctions::StateMachineVersion`
  + `AWS::Synthetics::Canary`
  + `AWS::VoiceID::Domain`
  + `AWS::WAF::ByteMatchSet`
  + `AWS::WAF::IPSet`
  + `AWS::WAF::Rule`
  + `AWS::WAF::SizeConstraintSet`
  + `AWS::WAF::SqlInjectionMatchSet`
  + `AWS::WAF::WebACL`
  + `AWS::WAF::XssMatchSet`
  + `AWS::WAFv2::IPSet`
  + `AWS::WAFv2::RegexPatternSet`
  + `AWS::WAFv2::RuleGroup`
  + `AWS::WAFv2::WebACL`
  + `AWS::WorkSpaces::Workspace`