解析错误:无法以跨环境方式使用资源“x”,必须显式设置资源的物理名称

jez*_*nag 3 aws-cloudformation aws-cdk

我正在尝试将 ecs 集群从一个堆栈传递到另一个堆栈。

我收到此错误: Error: Resolution error: Resolution error: Resolution error: Cannot use resource 'BackendAPIStack/BackendAPICluster' in a cross-environment fashion, the resource's physical name must be explicit set or use `PhysicalName.GENERATE_IF_NEEDED`.

集群在 BackendAPIStack 中定义如下:

this.cluster = new ecs.Cluster(this, 'BackendAPICluster', {
   vpc: this.vpc
});
Run Code Online (Sandbox Code Playgroud)

堆栈定义如下:

 const backendAPIStack = new BackendAPIStack(app, `BackendAPIStack${settingsForThisEnv.stackVersion}`, {
    env: {
      account: process.env.CDK_DEFAULT_ACCOUNT,
      region: process.env.CDK_DEFAULT_REGION
    },
    digicallPolicyQueue: digicallPolicyQueue,
    environmentName,
    ...settingsForThisEnv
  });

  const metabaseStack = new MetabaseStack(app, 'MetabaseStack', backendAPIStack.vpc, backendAPIStack.cluster, {
    vpc: backendAPIStack.vpc,
    cluster: backendAPIStack.cluster
  });

  metabaseStack.addDependency(backendAPIStack);
Run Code Online (Sandbox Code Playgroud)

这是 MetabaseStack 的构造函数:

constructor(scope: cdk.Construct, id: string, vpc: ec2.Vpc, cluster: ecs.Cluster, props: MetabaseStackProps) {
        super(scope, id, props);

        console.log('cluster', cluster)

        this.vpc = vpc;
        this.cluster = cluster;

        this.setupMetabase()
    }
Run Code Online (Sandbox Code Playgroud)

然后我在这里使用集群:

      const metabaseService = new ecs_patterns.ApplicationLoadBalancedFargateService(this, 'Metabase', {
            assignPublicIp: false,
            cluster: this.cluster,
...
Run Code Online (Sandbox Code Playgroud)

我找不到有关如何做我正在尝试做的事情的文档。

Mat*_*ein 10

您正在创建特定Stack于区域/帐户的with,BackendAPIStack因为您通过envprop 值将堆栈绑定到特定帐户和区域。

然后,您通过创建不带任何prop 值的值来创建区域/帐户不可知堆栈。MetabaseStackenv

在一般情况下,有两个独立的像这样的栈是好的,但在这里,你通过传递从参考他们连接起来BackendAPIStackMetabaseStack,这是行不通的。

这是一个问题,因为 CDK 通常通过执行值的堆栈导出和导入将堆栈链接在一起,但 CloudFormation不支持跨区域或跨账户堆栈引用

因此,您可能的解决方案是:

  • (A) 设置您MetabaseStack使用与您相同的帐户/地区BackendAPIStack
    • 在幕后,这会将集群的 ARN 设置为堆栈导出BackendAPICluster,然后MetabaseStack将能够导入它。
  • (B1)BackendAPICluster使用您选择的clusterName创建。
    • IE new Cluster(..., {vpc: this.vpc, clusterName: 'backendCluster' })
    • 通过不提供名称,您将使用默认的“CloudFormation 生成的名称”,这是 CDK 报告的问题的基础,尽管它以一种令人困惑的方式。
    • 当您提供名称时,集群的 ARN 是确定性的(不是在部署时由 CloudFormation 选择的),因此 CDK 在构建时有足够的信息来确定集群的 ARN 是什么,并且可以将其提供给您的MetabaseStack.
  • (B2)BackendAPICluster用 a创建clusterName让 CDK 选择
    • 这是通过设置clusterName PhysicalName.GENERATE_IF_NEEDED
      • IE new Cluster(..., {clusterName: PhysicalName.GENERATE_IF_NEEDED })
    • PhysicalName.GENERATE_IF_NEEDED是一个标记,表示物理(名称)仅在跨环境引用需要时才由 CDK 生成。否则,将由 CloudFormation 分配。
    • 这就是错误试图告诉你的,但我也不明白......

如果可能的话,我会选择(A)。我怀疑无论如何这只是一个疏忽,您没有将相同的env值传递给MetabaseStack并且您可能希望同一区域中的这两个堆栈都减少延迟等等。

如果没有,那么我个人接下来会选择 (B2),因为我尽量不给我的任何资源提供明确的名称,除非它们是与另一组合同的一部分。即在帐户 XYZ 中承担名为“ServiceWorker”的角色从 Bucket 'ABC' 下载数据