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

时间:2020-07-20 05:27:46

标签: 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
});

堆栈定义如下:

 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);

这是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()
    }

然后我在这里使用集群:

      const metabaseService = new ecs_patterns.ApplicationLoadBalancedFargateService(this, 'Metabase', {
            assignPublicIp: false,
            cluster: this.cluster,
...

我找不到有关如何做自己想做的事情的文件。

1 个答案:

答案 0 :(得分:3)

您正在使用Stack创建特定于地区/帐户的BackendAPIStack,因为您是通过env属性值将堆栈绑定到特定帐户和地区的。

然后,您通过创建没有任何MetabaseStack道具价值的env来创建地区/帐户-不可知堆栈。

通常,有两个这样的独立堆栈很好,但是在这里,您可以通过将引用从BackendAPIStack传递到MetabaseStack来将它们链接在一起无法正常工作。

这是一个问题,因为CDK通常通过执行值的堆栈导出和导入来将堆栈链接在一起,但是CloudFormation does not support cross-region or cross-account Stack references

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

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

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

如果不是,那么我个人将接下来使用(B2),因为我尝试不给我的任何资源明确的名称,除非它们是与另一组的某些合同的一部分。即假设帐户XYZ中名为“ ServiceWorker”的角色从存储区“ ABC”中下载数据