AWS CDK重构功能发布:安全重构基础设施即代码

AWS Cloud Development Kit推出重构功能,支持在不替换AWS资源的情况下重命名构造、在堆栈间移动资源和重组CDK应用。该功能基于CloudFormation重构能力,自动计算资源映射,避免状态资源的数据丢失和停机风险。

我们很高兴宣布一项新的AWS Cloud Development Kit功能,它使重构基础设施即代码变得更加容易和安全。CDK重构功能旨在在重命名构造、在堆栈间移动资源以及重组CDK应用程序时保留您的AWS资源——这些操作以前存在资源替换风险。

在使用CDK编写基础设施即代码时,开发人员偶尔需要重命名构造或在堆栈或目录之间移动它们。无论他们需要更好地组织代码、遵循编码最佳实践,还是利用类继承等面向对象编程模式,这些更改在已部署资源的环境中可能存在风险,因为它们会更改CDK生成的这些资源的逻辑ID。在CDK部署期间,AWS CloudFormation将这些更改解释为新资源,通常需要删除现有资源并使用新的逻辑ID创建新资源。对于有状态资源,这可能导致潜在的停机甚至数据丢失。为了减轻ID更改的影响,开发人员必须分阶段进行更改以创建新资源,制定数据或网络迁移计划,然后删除旧资源以防止这些重构影响。有时,开发人员认为这些更改的风险超过了重构的好处,并选择根本不执行重构。

如今,开发人员可以使用新的cdk refactor命令来检测、审查、确认和安全地将重构更改应用到他们的资源,而无需替换资源。此功能利用了最近推出的AWS CloudFormation重构功能,但CDK会自动计算CloudFormation重新定义重构资源所需的映射,提供一层抽象,使开发人员能够专注于代码而不是资源配置。让我们通过一个示例来演示此重构功能的好处。

先决条件

除了通常的CDK先决条件外,如果您在此发布之前引导了CDK项目,则需要在尝试重构之前重新引导环境以获得与CDK重构功能相关的新权限。

单体到微服务示例

对于此示例,假设我们有一个遗留的CDK应用程序,它部署一个单体堆栈,其中包含用于用户、产品和订单的Amazon DynamoDB表,以及一个在所有实体上实现CRUD操作的AWS Lambda函数。

单体应用程序

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function monolithApp() {
  const monolith = new CdkAppStack(app, monolithStackName, {env});
  const usersTable = makeTable(monolith, 'users');
  const productsTable = makeTable(monolith, 'products');
  const ordersTable = makeTable(monolith, 'orders');

  // 我们的应用程序中有一个单一的Lambda函数
  const func = new Function(monolith, `MonolithFunction`, {
    code: Code.fromInline(`访问所有三个表的一些代码`),
    runtime: Runtime.NODEJS_22_X,
    handler: 'index.handler',
  });

  usersTable.grantReadWriteData(func);
  productsTable.grantReadWriteData(func);
  ordersTable.grantReadWriteData(func);

  // 此函数创建REST API、资源、方法,并将所有内容链接到函数。
  // 现在,我们在三个地方传递相同的函数。
  makeApi(monolith, {
    usersFunction: func,
    productsFunction: func,
    ordersFunction: func,
  });
}

monolithApp();

我们被要求遵循Well Architected Framework最佳实践,并将单体分解为单独的Lambda函数,以便它们可以独立扩展。因为它们非常相似,我们还将创建一个可继承的Lambda类,我们可以重用它来提高代码的可读性和可维护性,并避免重新定义在所有函数中一致的Lambda配置设置。

最后,单体仅使用L1 CDK构造。为了进一步抽象我们的代码并利用辅助函数,我们将开始对DynamoDB、Lambda和API Gateway使用L2 CDK构造。此更改将允许自动定义IAM角色和权限,进一步简化我们的代码。

重构为每个域的单独堆栈

如果没有重构功能,CloudFormation将删除并重新创建Lambda和DynamoDB资源,这将导致后者中的所有数据丢失。或者,您可以在一次部署中创建全新的Lambda和Amazon DynamoDB表,在第二次部署中执行从旧表到新表的带外、时间点和流数据迁移,更新API Gateway配置以指向新的Lambda,并关闭流迁移过程。

使用重构功能,我们可以将资源定义移动到新文件,将它们更新为L2构造,并保留有状态资源!

首先替换无状态资源

首先,让我们重构CDK代码,将单体Lambda分解为3个特定领域的Lambda。CloudFormation的重构功能不支持创建新资源或更新现有资源的配置,因此我们将照常部署这些更改,而不使用新的重构功能。所有资源目前仍保留在单体堆栈中。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
function singleStackMicroservicesApp() {
  // 我们仍然有一个单一的堆栈
  const monolith = new CdkAppStack(app, monolithStackName, {env});

  // makeFunctionAndTable为每个作为参数传递的域创建不同的Lambda函数和DynamoDB表。
  // 在真实的CDK应用程序中,您可能会独立定义它们中的每一个。
  makeApi(monolith, {
    usersFunction: makeFunctionAndTable(monolith, 'users'),
    productsFunction: makeFunctionAndTable(monolith, 'products'),
    ordersFunction: makeFunctionAndTable(monolith, 'orders'),
  });
}

singleStackMicroservicesApp();

重构有状态资源

现在我们可以将有状态的DynamoDB表及其各自的Lambda重构到它们自己的堆栈中,使用cdk refactor映射它们的新ID而不替换资源。

但在重构之前,我们需要创建将接收函数和表的新堆栈:

1
2
3
4
5
singleStackMicroservicesApp();

const usersStack = new Stack(app, 'Users', {env});
const productsStack = new Stack(app, 'Products', {env});
const ordersStack = new Stack(app, 'Orders', {env});
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
function fullMicroservicesApp() {
    const monolith = new Stack(app, monolithStackName, {env});

    const usersStack = new Stack(app, 'Users', {env});
    const productsStack = new Stack(app, 'Products', {env});
    const ordersStack = new Stack(app, 'Orders', {env});

    makeApi(monolith, {
        // 现在每个函数+表对都在其自己的堆栈中
        usersFunction: makeFunctionAndTable(usersStack, 'users'),
        productsFunction: makeFunctionAndTable(productsStack, 'products'),
        ordersFunction: makeFunctionAndTable(ordersStack, 'orders'),
    });
}

fullMicroservicesApp();

运行cdk refactor --unstable=refactor启动该过程。(需要unstable标志,因为此功能仍可能发生破坏性更改。)CDK将比较应用程序的当前状态(已部署的单体应用程序)与新状态(重构后的CDK应用程序的输出)。

CDK重构确认对话框

如预期的那样,它显示了一个表格,列出了从Monolith堆栈移动到各自重构堆栈的资源。默认情况下,CLI会在继续之前请求确认。通过传递--force标志绕过确认,或确认更改并执行重构:所有资源,包括有状态表,都已安全地移动到其他堆栈,我们现在拥有了架构良好的应用程序。

CDK重构结果

结论

如果您有一直等待执行的重构,请在CDK重构文档中阅读有关功能集的更多信息,并立即开始重构您自己的CDK应用程序!

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计