amazon-web-services - AWS CDK 应用程序的可重构性如何?

标签 amazon-web-services aws-cloudformation aws-cdk infrastructure-as-code

我正在探索 CDK 应用程序的可重构性。假设我定义了一个自定义构造(堆栈)来创建 EKS 集群。我们将其称为 EksStack。理想情况下,我将创建与集群和 EKS 集群本身关联的角色,如以下代码片段所述(我使用 Scala 而不是 Java,因此代码片段将采用 Scala 语法):

class EksStack (scope: Construct, id: String, props: StackProps) extends Stack(scope, id, props) {
    private val role = new Role(this, "eks-role", RoleProps.builder()
        .description(...)
        .managedPolicies(...)
        .assumedBy(...)
        .build()
    )

    private val cluster = new Cluster(this, "eks-cluster", ClusterProps.builder()
        .version(...)
        .role(role)
        .defaultCapacityType(DefaultCapacityType.EC2)
        .build()
    )
}

当我综合应用程序时,我可以看到生成的模板包含 VPC 的定义以及弹性 IP、NAT、Internet 网关等。

现在假设我想重构 EksStack 并拥有不同的堆栈,例如 VpcStack,显式创建 VPC:

class VpcStack (scope: Construct, id: String, props: StackProps) extends Stack(scope, id, props) {
    val vpc = new Vpc(this, VpcId, VpcProps.builder()
      .cidr(...)
      .enableDnsSupport(true)
      .enableDnsHostnames(true)
      .maxAzs(...)
      .build()
    )
}

理想情况下,EksStack 中的集群将仅使用对 VpcStack 创建的 VPC 的引用,类似于(请注意对 vpc() 的新调用) 在集群构建器中):

class EksStack (scope: Construct, id: String, props: StackProps, vpc: IVpc) extends Stack(scope, id, props) {
    private val role = new Role(this, "eks-role", RoleProps.builder()
        .description(...)
        .managedPolicies(...)
        .assumedBy(...)
        .build()
    )

    private val cluster = new Cluster(this, "eks-cluster", ClusterProps.builder()
        .version(...)
        .role(role)
        .vpc(vpc)
        .defaultCapacityType(DefaultCapacityType.EC2)
        .build()
    )
}

这显然不起作用,因为 CloudFormation 会删除 EksStack 创建的 VPC,转而使用 VpcStack 创建的 VPC。我到处阅读并尝试在 EksStack 中添加保留策略,并使用我最初在 CloudFormation 模板中看到的 ID 覆盖 VpcStack 中 VPC 的逻辑 ID对于EksStack:

val cfnVpc = cluster.getVpc.getNode.getDefaultChild.asInstanceOf[CfnVPC]
cfnVpc.applyRemovalPolicy(RemovalPolicy.RETAIN)

val cfnVpc = vpc.getNode.getDefaultChild.asInstanceOf[CfnVPC]
cfnVpc.overrideLogicalId("LogicalID")

然后重试diff。同样,VPC 似乎被删除并重新创建。

现在,我发现可以使用“将资源导入堆栈”操作来迁移 CloudFormation 资源 ( https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/refactor-stacks.html )。我的问题是:我可以将资源的创建从 CDK 中的一个堆栈移动到另一个堆栈而不重新创建它吗?

编辑: 为了详细说明我的问题,当我在 VpcStack 中定义 VPC 时,我希望 CDK 认为该资源是由 VpcStack 创建的> 改为 ok EksStack。例如将其定义从一个堆栈移动到另一个堆栈,而无需让 CloudFormation 删除原始堆栈来重新创建它。在我的用例中,我最初有一个堆栈定义一个创建(显式或隐式,例如我的 VPC),但之后,我可能想重构我的应用程序,将该资源的创建移动到专用堆栈。我试图了解这种移动是否总是导致资源被重新创建,是否有任何方法可以避免它。

最佳答案

我认为,当谈到 CDK 和 CloudFormation 的可重构性时,尤其是多堆栈配置时,有一些原则需要牢记。

  1. 整个应用程序应该能够完全删除并重新创建。所有数据管理均在应用程序中处理,无需进行手动流程。

  2. 不要总是依赖使用堆栈导出的自动堆栈间依赖关系管理。我喜欢将 CloudFormation 依赖项分为两类:硬依赖项和软依赖项。硬依赖意味着您无法删除资源,因为使用它的事物会阻止它发生。软依赖则相反,即使其他东西正在使用该资源,也可以毫无问题地删除和重新创建该资源。硬依赖示例:VPC、子网。软依赖示例:主题/队列/角色。

  3. 您可以更好地将堆栈软依赖项作为 SSM 参数类型的堆栈参数传递,因为您将能够更新提供独立于使用它的依赖项的堆栈。然而,当使用默认的堆栈导出方法时,您会陷入僵局。您无法删除资源,因为其他资源正在导入它。因此,您最终不得不做一些烦人的事情才能使其正常工作,例如部署一次并重复部署,然后再次部署删除旧的内容。使用 SSM 参数需要一些额外的工作而不导致堆栈导出,但从长远来看,对于软依赖项来说这是值得的。

  4. 对于硬依赖项,我不同意使用查找,因为如果有东西正在使用它,您确实希望防止删除,因为您最终会得到 DELETE_FAILED 堆栈,这是一个可怕的结果。因此,对于 VPC/子网之类的事情,我认为实际使用堆栈导出/导入技术非常重要,如果您确实需要因更改而重新创建 VPC,如果您遵循原则 1,则只需执行 CDK 销毁即可部署后一切都会好起来的,因为您构建的 CDK 应用程序是完全可重新创建的。

  5. 当谈到数据的可重复性时,CustomResources 是您的 friend 。

关于amazon-web-services - AWS CDK 应用程序的可重构性如何?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64825165/

相关文章:

java - AWS、Lambda、Java、POJO、自定义 json 属性名称

ruby - eu-central-1(法兰克福)AWS 身份验证失败

python - 在 EMR 集群上安装 pandas

amazon-web-services - AWS-Lambda:无法添加另一个事件,无用的GenerateChangeSet失败消息

amazon-web-services - 在 AWS CloudFormation 中,使用 aws cli 创建新堆栈时,堆栈状态从 CREATE_IN_PROGRESS 更改为 ROLLBACK_COMPLETE

amazon-web-services - 防止 AWS cloudformation 中的回滚

typescript - 使用自定义 Lambda 函数轮换 key

java - SWF : How can I signal the parent workflow from the child workflow?

amazon-web-services - Assets 执行步骤在代码管道中失败 - CDK (Java)

amazon-web-services - 关于 cdk bootstrap 中的 IAM 角色