这是 AWS CDK v2 开发者指南。旧版 CDK v1 于 2022 年 6 月 1 日进入维护阶段,并于 2023 年 6 月 1 日终止支持。
本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
重构 CDK 代码时保留已部署的资源
重要
CDK 重构目前为预览版,可能会发生变化。
借助 C AWS loud Development Kit (AWS CDK) 重构,您可以重构您的 CDK 代码,例如重命名构造、在堆栈之间移动资源以及重组应用程序,同时保留已部署的资源而不是替换它们。此功能可帮助您保持良好的软件工程最佳实践,而不会导致意外的资源替换。
什么是具有资源保留的 CDK 重构?
部署 CDK 应用程序时,会根据资源的逻辑 IDs来 AWS CloudFormation 识别资源。 AWS CDK IDs 根据构造 ID 及其在构造树中的路径生成这些逻辑。如果您更改构造的 ID 或将其移至代码中的其他位置, AWS CloudFormation 通常会将其解释为请求创建新资源并删除旧资源。对于数据库、存储桶或队列等有状态资源,这种替换可能会导致服务中断或数据丢失。
CDK 重构通过以下方式解决此问题:
-
检测代码中资源何时被移动或重命名。
-
使用 AWS CloudFormation的重构功能来保留底层的物理资源。
-
在 IDs 不替换实际资源的情况下更新逻辑。
-
维护堆栈中资源之间的引用。
您可以使用 CDK CLI cdk refactor 命令或 CDK 工具包库的 refactor 操作来执行 CDK 重构。本指南主要讨论 CLI 方法,但基本原则适用于这两种方法。有关使用工具包库的信息,请参阅使用 CDK 工具包库执行编程操作。
重要
重构操作必须单独执行,与其他操作(例如,添加新资源、删除资源或修改资源属性)分开执行。
如果您需要添加、删除或修改资源以及重构,则应首先单独部署这些更改,然后使用重构来重组您的资源。
CDK 重构的好处
CDK 重构为 CDK 开发者提供了以下好处 AWS :
-
改进代码组织:重命名结构并重组 CDK 应用程序的结构,而无需替换资源。
-
创建可重用组件:将重复代码提取为可重用的 L3 构造,同时保留已部署的资源。
-
增强架构分离:在堆栈之间移动资源,以更好地隔离应用程序的不同部分。
-
防止意外替换资源:避免在重命名构造时意外重新创建资源。
-
缓解第三方库更改:保护您的应用程序,以免您所依赖的构造库中的逻辑 ID 发生更改。
-
应用软件工程最佳实践:在不影响已部署基础设施的情况下重构代码。
CDK CLI cdk refactor 命令的工作原理
重要
您必须对使用此功能的所有命令提供 --unstable=refactor 选项。
首先,部署初始 CDK 应用程序以在 AWS 账户中建立基准资源。重构 CDK 代码(例如,重命名构造或在堆栈之间移动资源)后,使用 cdk refactor 命令开始重构已部署资源的过程。
当您运行重构命令时,CDK CLI 会将当前代码与已部署状态进行比较,从而检测本地更改。它验证您的 CDK 应用程序是否包含与已部署状态完全相同的资源集,只是它们在构造树中的位置不同。然后,CDK CLI 会生成一个重构计划来将旧资源位置映射到新位置。CDK CLI 会向您显示建议的更改,并在您确认后,使用 AWS CloudFormation其重构 API 更新资源的逻辑 IDs 而无需替换它们。
在后台,CDK CLI 通过比较资源的属性和依赖项来确定哪些资源已移动,识别功能等效但在构造树中的路径不同的资源。如果检测到任何资源添加、删除或修改,则重构操作将被拒绝并显示一条错误消息。
重构 CDK 代码时保留资源的示例
在此示例中,我们使用 CDK CLI cdk refactor 命令重构 CDK 代码,同时保留已部署的资源。
我们的示例 CDK 应用程序由包含 S3 存储桶、 CloudFront 分配和 Lambda 函数的单个堆栈组成。构造树的结构如下:
App └─ MyStack ├─ Bucket ├─ Distribution └─ Function
下面是我们的应用程序代码示例:
const app = new cdk.App(); const myStack = new cdk.Stack(app, 'MyStack'); const bucket = new s3.Bucket(myStack, 'Bucket'); const distribution = new cloudfront.Distribution(myStack, 'Distribution', { defaultBehavior: { origin: new origins.S3Origin(bucket) } }); const function = new lambda.Function(myStack, 'Function', { // function properties }); // Synthesize the app app.synth();
现在,假设您想重构此代码来实现以下目的:
-
将存储桶从
Bucket重命名为更具描述性的WebsiteOrigin。 -
将存储桶和分配移动到新的
WebStack堆栈。
重构后,构造树将如下所示:
App ├─ WebStack │ ├─ WebsiteOrigin │ └─ Distribution └─ MyStack └─ Function
重构后的代码如下:
// Refactored structure const app = new cdk.App(); // New WebStack with the bucket and distribution const webStack = new cdk.Stack(app, 'WebStack'); const bucket = new s3.Bucket(webStack, 'WebsiteOrigin'); const distribution = new cloudfront.Distribution(webStack, 'Distribution', { defaultBehavior: { origin: new origins.S3Origin(bucket) } }); // Original MyStack with just the function const myStack = new cdk.Stack(app, 'MyStack'); const function = new lambda.Function(myStack, 'Function', { // function properties }); // Synthesize the app app.synth();
如果没有 CDK 重构,这些更改将 AWS CloudFormation 导致创建新资源并删除旧资源,因为逻辑 IDs 会发生变化:
-
MyStack/Bucket/Resource会变为WebStack/WebsiteOrigin/Resource。 -
MyStack/Distribution/Resource会变为WebStack/Distribution/Resource。
通过 CDK 重构,CDK CLI 可以检测到这些路径变化,并使用其重构功能 AWS CloudFormation来保留底层资源。运行 cdk refactor 后,CLI 会显示它将进行的更改:
$ cdk refactor The following resources were moved or renamed: ┌───────────────────────────────┬───────────────────────────────┬───────────────────────────────────┐ │ Resource Type │ Old Construct Path │ New Construct Path │ ├───────────────────────────────┼───────────────────────────────┼───────────────────────────────────┤ │ AWS::S3::Bucket │ MyStack/Bucket/Resource │ WebStack/WebsiteOrigin/Resource │ ├───────────────────────────────┼───────────────────────────────┼───────────────────────────────────┤ │ AWS::CloudFront::Distribution │ MyStack/Distribution/Resource │ WebStack/Distribution/Resource │ └───────────────────────────────┴───────────────────────────────┴───────────────────────────────────┘ Do you wish refactor these resources (y/n)?
输入 y 确认后,CDK CLI 会显示重构操作的进度:
Refactoring... ✅ Stack refactor complete
确认后,CDK CLI 将运行重构操作,保留这两个资源,同时更新其逻辑 IDs 以匹配您的新代码结构。
cdk diff 命令的输出也会显示相同映射,按堆栈进行组织:
Stack MyStack Resources [-] AWS::S3::Bucket Bucket Bucket1234567 destroy (OR move to WebStack.WebsiteOrigin1234567 via refactoring) [-] AWS::CloudFront::Distribution Distribution Distribution1234567 destroy (OR move to WebStack.Distribution1234567) ... Stack WebStack Resources [+] AWS::S3::Bucket WebsiteOrigin WebsiteOrigin1234567 (OR move from MyStack.Bucket1234567) [+] AWS::CloudFront::Distribution Distribution Distribution1234567 (OR move from MyStack.Distribution1234567) ...
开始使用 CDK 重构
要开始重构,请完成下面的先决条件:
- 使用最新模板引导环境
-
CDK 重构在引导堆栈中需要新权限。为确保您拥有必要的权限,请使用最新模板引导您的环境:
cdk bootstrap有关引导的更多信息,请参阅 AWS CDK 的引导环境。
- 安装最新的 CDK CLI 版本
-
CDK 重构需要最新版本的 CDK CLI。为了确保您拥有最新版本,请运行以下命令:
npm install -g aws-cdk有关详细的安装说明,请参阅开始使用 AWS CDK。
使用覆盖文件来解决重构中的歧义
CDK CLI 会根据您的代码与已部署资源的比较结果自动计算所有资源映射。大多数情况下,这种自动检测效果很好,但有时 CLI 可能会遇到它自己无法解决的歧义。要为 CDK CLI 提供指导,请使用覆盖文件。
- 创建覆盖文件以解决歧义
-
覆盖文件是一个 JSON 文件,用于在 CDK CLI 无法确定资源的重构解析时提供映射。该文件包含按环境组织的资源映射:
{ "environments": [ { "account": "123456789012", "region": "us-east-2", "resources": { "StackA.OldName": "StackB.NewName", "StackC.Foo": "StackC.Bar" } } ] }在此文件中:
-
environments数组包含一个或多个带有账户和区域信息的环境条目。 -
在每个环境内,
resources对象都包含映射。 -
键表示当前位置,格式为
<stack name>.<logical ID>。 -
值表示新位置,格式相同。
要将覆盖文件与 CDK CLI 一起使用,请运行以下命令:
cdk refactor --override-file=overrides.json -
跨多个环境重构堆栈
一个 CDK 应用程序可以包含部署到不同环境(AWS 账户和区域)的多个堆栈。在重构此类应用程序期间,为了保留资源,CDK CLI 会以特定方式处理环境:
-
CLI 会按环境对堆栈进行分组,并在每个环境中分别执行重构。
-
重构期间,您可以在堆栈之间移动资源,但所有参与移动的堆栈必须位于同一环境中。
-
尝试跨环境移动资源将导致错误。
这种行为可确保资源保留在其原始 AWS 账户和区域内,这是必要的,因为 CloudFormation 资源无法在账户或区域边界之间实际移动。
例如,如果您的 CDK 应用程序针对开发环境和生产环境都定义了堆栈,则重构操作将在每个环境中独立执行。资源可以在开发环境或生产环境内的堆栈之间移动,但不能从开发环境移动到生产环境,反之亦然。
处理需要替换的资源
某些 CDK 构造依赖于 CloudFormation的资源替换行为作为其设计的一部分。例如,API Gateway 的 Deployment 和 Lambda 的 Version 构造都旨在当资源属性发生变化时创建新资源。
重构时,请勿进行任何会导致资源替换的更改。否则,CDK CLI 可能会检测到并保留这些资源。这意味着需要替换的资源必须与重构操作分开处理。
要正确管理需要替换的资源,请执行以下操作:
-
首先,部署您的应用程序,根据需要替换这些资源。
-
然后,分别执行重构操作来重新组织代码。
这种两步法确保需要替换的资源得到正确处理,同时还能让您从其他资源的 CDK 重构中受益。
一般注意事项和限制
在 CDK 重构期间保留资源时,请记住以下注意事项:
-
环境约束:资源只能在同一环境内的不同堆栈之间移动。不支持跨环境移动。
-
歧义:如果您同时重命名多个相同的资源,CDK CLI 可能无法自动确定正确的映射。在这些情况下,您需要使用覆盖文件提供显式映射。
-
引导要求:要在重构期间保留资源,您需要将引导堆栈更新到包含必要权限的最新版本。
-
排除某些构造:某些构造(例如 API Gateway 的
Deployment和 Lambda 的Version)依赖于资源替换,因此会自动从重构中排除。
使用管道进行重构 CI/CD
要在 CI/CD 管道中使用重构功能,您需要能够将 CDK CLI 作为管道的一部分运行。以下是将重构集成到工作流程中的 CI/CD 一些重要注意事项。
- 在 CI/CD 中使用重构的先决条件
-
您必须能够在您的 CI/CD 环境中使用 CDK CLI 才能从此功能中受益。
- 将重构集成到管线工作流中
-
如果您在 CI/CD 管道中使用 CLI 进行部署,则脚本通常如下所示:
... cdk deploy <stack filter> ...如果要将重构纳入工作流,下面是一个基本示例:
... cdk refactor <stack filter> cdk deploy <stack filter> ...您也可以将重构作为管线中的一个单独步骤。
- 处理重构失败
-
请注意,如果您的代码在重构的同时还包含实际的资源修改,则
cdk refactor将会失败。由于您在管线中自动调用了重构,因此需要处理潜在失败:# Allow refactoring to fail but continue the pipeline cdk refactor <stack filter> || true cdk deploy <stack filter>或者,您可能需要确保在成功完成重构之前不要进行任何部署:
# Only deploy if refactoring succeeds cdk refactor <stack filter> && cdk deploy <stack filter> - CI/CD 环境最佳实践
-
要在管道中 CI/CD 有效地使用重构,请执行以下操作:
-
将重构与其他变更分开:请记住,重构操作必须与资源的添加、删除或修改分开。在您的管线中,请考虑为重构采用专用的提交和部署。
-
适当使用覆盖文件:请注意,CDK CLI 仅将覆盖文件用作解决歧义情况的备用方案。
-
无需
--force在管道中使用:在管道等 CI/CD 非交互式环境中,CDK 重构命令会自动执行而不提示确认。--force选项仅在交互式环境中需要。
-
相关资源
有关 CDK CLI cdk refactor 命令的选项和参数的信息,请参阅
cdk refactor
。
要开始使用 CDK 工具包库的 refactor 操作,请参阅使用 CDK 工具包库执行编程操作。