当前位置: 首页 > 知识库问答 >
问题:

AWS CDK跨栈引用和部署顺序

刘绍晖
2023-03-14

如何克服AWS CDK中的循环依赖问题:让我们假设我有一个用于ECS集群的堆栈和一个用于ECS服务的堆栈(其中的几个):

export class EcsClusterStack extends cdk.Stack {
    public readonly cluster: ecs.Cluster
    ...
}
export class EcsServiceStack extends cdk.Stack {
    constructor(scope: cdk.Construct, id: string, cluster: ecs.ICluster) { }
}
const app = new cdk.App();
const vpc = new VpcStack(app,  'vpc');
const cluster = new ClusterStack(app, 'ecs', vpc.vpc);

const service = new EcsServiceStack(app, 'ecs-service', cluster.cluster);
0 | 7:15:19 PM | UPDATE_IN_PROGRESS   | AWS::CloudFormation::Stack            | ecs User Initiated
0 | 7:15:26 PM | UPDATE_ROLLBACK_IN_P | AWS::CloudFormation::Stack            | ecs Export ecs:ExportsOutputFnGetAttdefaultasgspotInstanceSecurityGroup2D2AFE98GroupId1084B7B2 cannot be deleted as it is in use by ecs-service

如果有一种方法可以强制ECS服务堆栈首先部署,这将解决问题,但AWS CDK似乎总是首先部署依赖项(在我的例子中是ECS集群),这将导致部署失败。那么有没有办法克服这一点呢?

共有1个答案

平俊茂
2023-03-14

AWS增加了一个官方的解决方案。它允许您在依赖堆栈中手动创建导出。当您需要删除导出时,请手动创建它,删除它的用法,部署,删除它,然后再次部署。

this.exportAttribute(this.bucket.bucketName)

我发现的一个解决方案是强制CDK将部署分为两个步骤。首先,我部署使用导出的堆栈,这样它就不再使用它了。然后,我部署创建导出的堆栈,以便在不再使用导出后删除该导出。即使在命令上指定堆栈名,它仍然部署它所依赖的所有堆栈。所以我必须使用--integrate标志。

cdk deploy --exclusively ecs-service
cdk deploy

在您的示例中,在创建新集群和部署堆栈之前需要先执行一个步骤,以便在ecs-service中导入一些新内容。

要使用该脚本,您必须分离synth和deploy步骤,并在它们之间运行脚本。

cdk synth && python phase-out-ref-exports.py && cdk deploy --app cdk.out --all

它需要读取堆栈的权限,因此它可能不能很好地用于跨帐户部署。

# phase-out-ref-exports.py
import json
import os
import os.path
 
from aws_cdk import cx_api
import boto3
import botocore.exceptions
 
 
def handle_template(stack_name, account, region, template_path):
    # get outputs from existing stack (if it exists)
    try:
        # TODO handle different accounts
        print(f"Checking exports of {stack_name}...")
        stack = boto3.client("cloudformation", region_name=region).describe_stacks(StackName=stack_name)["Stacks"][0]
        old_outputs = {
            o["OutputKey"]: o
            for o in stack.get("Outputs", [])
        }
    except botocore.exceptions.ClientError as e:
        print(f"Unable to phase out exports for {stack_name} on {account}/{region}: {e}")
        return
 
    # load new template generated by CDK
    new_template = json.load(open(template_path))
    if "Outputs" not in new_template:
        new_template["Outputs"] = {}
 
    # get output names for both existing and new templates
    new_output_names = set(new_template["Outputs"].keys())
    old_output_names = set(old_outputs.keys())
 
    # phase out outputs that are in old template but not in new template
    for output_to_phase_out in old_output_names - new_output_names:
        # if we already marked it for removal last deploy, remove the output
        if old_outputs[output_to_phase_out].get("Description") == "REMOVE ON NEXT DEPLOY":
            print(f"Removing {output_to_phase_out}")
            continue
 
        if not old_outputs[output_to_phase_out].get("ExportName"):
            print(f"This is an export with no name, ignoring {old_outputs[output_to_phase_out]}")
            continue
 
        # add back removed outputs
        print(f"Re-adding {output_to_phase_out}, but removing on next deploy")
        new_template["Outputs"][output_to_phase_out] = {
            "Value": old_outputs[output_to_phase_out]["OutputValue"],
            "Export": {
                "Name": old_outputs[output_to_phase_out]["ExportName"]
            },
            # mark for removal on next deploy
            "Description": "REMOVE ON NEXT DEPLOY",
        }
 
    # replace template
    json.dump(new_template, open(template_path, "w"), indent=4)
 
 
def handle_assembly(assembly):
    for s in assembly.stacks:
        handle_template(s.stack_name, s.environment.account, s.environment.region, s.template_full_path)
 
    for a in assembly.nested_assemblies:
        handle_assembly(a.nested_assembly)
 
 
def main():
    assembly = cx_api.CloudAssembly("cdk.out")
    handle_assembly(assembly)
 

if __name__ == "__main__":
    main()
 类似资料:
  • 我正在按照本指南部署MERN stack app,使用heroku和github页面-https://github.com/juliojgarciaperez/deploy-mern Q1.我是否需要创建两个不同的存储库,一个用于后端,一个用于前端来连接到Heroku?(T.EX后端存储库到heroku管道)我最初在同一个存储库下开发了后端和前端。 Q2.我设法获得了指南中的步骤:3,并按照前面提

  • 正在尝试在linux服务器上部署spring启动应用程序 r,“线程名称”:“localhost-startStop-1”,“级别”:“错误”,“级别值”:40000,“堆栈跟踪”:“组织”。springframework。豆。工厂BeanCreationException:创建名为“org”的bean时出错。springframework。验证。Bean验证。OptionalValidatorF

  • 我知道Spring Boot应用程序可以作为war文件部署到生产环境中。但是部署spring boot应用程序的典型方式是什么?它只需要jvm而不需要容器吗?

  • 我有一个全栈node.js项目,我不知道部署它的最佳实践是什么。 首先提供一些信息:应用程序包括: 下一个。js前端 redis缓存 postgres sql 和节点。js后端 部署不应该花费太多,因为这是一个爱好项目。 目前(作为开发环境),我使用vercel作为前端,我自己的vm作为后端 然而,我想在应用引擎中部署一切(即没有太多的配置和自动扩展) 我只是不知道最好的提供商是什么,因为有很多服

  • 我正在研究Terraform以及如何使用它来设置AWS环境。到目前为止,我已经有了用3个公共子网、3个私有子网、一个互联网网关和3个Nat网关设置VPC的脚本。然而,我对如何在私有子网中部署和重新部署应用程序感到困惑? 在我的场景中,我们使用Spring Boot构建微服务。我们的想法是转移到一种状态,在这种状态下,我们可以将弹性负载平衡器连接到公共子网,并在私有子网中的自动缩放组中承载我们的应用

  • 顺序栈(Sequential Stack) 1. 顺序栈的概念 1.1 顺序栈的定义 顺序栈是基于一维数组的存储表示实现的栈。 1.2 顺序栈中各元素的逻辑及存储关系 顺序栈可以采用顺序表作为其存储表示,因此,可以在顺序栈的声明中用顺序表定义它的存储空间。 顺序栈可以使用一维数组作为栈的存储空间,存放栈元素的数组的头指针为*elements,该数组的最大允许存放元素个数为maxSize,当前栈顶位