简体   繁体   English

AWS CDK:如何在同一应用程序中引用跨堆栈资源?

[英]AWS CDK: how do I reference cross-stack resources in same app?

I have an App that has two stacks, both within the same region/account.我有一个应用程序,它有两个堆栈,都在同一个区域/帐户中。 One of those stacks requires the ARN of a lambda that exists in the other stack.其中一个堆栈需要另一个堆栈中存在的 lambda 的 ARN。 How do I reference this?我如何参考这个?

// within stackA constructor
public StackA(Construct scope, String id, StackProps props) {
        SingletonFunction myLambda = SingletonFunction.Builder.create(this, "myLambda")
                                                              // some code here
                                                              .build()
        CfnOutput myLambdaArn = CfnOutput.Builder.create(this, "myLambdaArn")
                                                  .exportName("myLambdaArn")
                                                  .description("ARN of the lambda that I want to use in StackB")
                                                  .value(myLambda.getFunctionArn())
                                                  .build();
    
}

App app = new App();
Stack stackA = new StackA(app, "stackA", someAProps);    
Stack stackB = new StackB(app, "stackB", someBProps);
stackB.dependsOn(stackA);

How do pass the ARN into StackB?如何将 ARN 传递到 StackB?

You can access resources in a different stack, as long as they are in the same account and AWS Region.您可以访问不同堆栈中的资源,只要它们位于同一账户和 AWS 区域中。 The following example defines the stack stack1, which defines an Amazon S3 bucket.以下示例定义了堆栈 stack1,它定义了一个 Amazon S3 存储桶。 Then it defines a second stack, stack2, which takes the bucket from stack1 as a constructor property.然后它定义了第二个堆栈 stack2,它从 stack1 中获取存储桶作为构造函数属性。

// Helper method to build an environment
static Environment makeEnv(String account, String region) {
    return Environment.builder().account(account).region(region)
            .build();
}

App app = new App();

Environment prod = makeEnv("123456789012", "us-east-1");

StackThatProvidesABucket stack1 = new StackThatProvidesABucket(app, "Stack1",
        StackProps.builder().env(prod).build());

// stack2 will take an argument "bucket"
StackThatExpectsABucket stack2 = new StackThatExpectsABucket(app, "Stack,",
        StackProps.builder().env(prod).build(), stack1.getBucket());

Option 1:选项1:

pass the data from Stack A to Stack B using the constructor:使用构造函数将数据从堆栈 A 传递到堆栈 B:

You can extend cdk.stack and create a new class that will contain stackA.您可以扩展cdk.stack并创建一个包含 stackA 的新 class。

In that stack, expose the relevant data you want by using public XXX: string\number (etc) ( See line 2 in the example).在该堆栈中,使用public XXX: string\number (etc)您想要的相关数据(参见示例中的第 2 行)。

Later, just pass this data into StackB constructor ( you can pass it using props as well).稍后,只需将此数据传递给 StackB 构造函数(您也可以使用 props 传递它)。

Working code snippet:工作代码片段:

Stack A:堆栈 A:

    export class StackA extends cdk.Stack {
        public YourKey: KEY_TYPE;
    
        constructor(scope: cdk.Construct, id: string, props: cdk.StackProps ) {
            super(scope, id, props);
    
            Code goes here...
    
            // Output the key 
            new cdk.CfnOutput(this, 'KEY', { value: this.YourKey });
    
        }
    }

Stack B:堆栈 B:

export class StackB extends cdk.Stack {
    constructor(scope: cdk.Construct, id: string,importedKey: KEY_TYPE, props: cdk.props) {
        super(scope, id, props)

        Code goes here...
        
        console.log(importedKey)

    }
}

bin ts:垃圾箱:

const importedKey = new StackA(app, 'id',props).YourKey;
new StackB(app, 'id',importedKey,props);

Option 2:选项 2:

Sometimes it's just better to save this kind of stuff in the parameter store and read it from there.有时最好将这种东西保存在参数存储中并从那里读取。

More info here .更多信息在这里

CDK's official documentation has a complete example for sharing a S3 bucket between stacks . CDK 的官方文档中有一个在栈之间共享 S3 存储桶的完整示例。 I copied it below for quicker reference.我在下面复制了它以便更快地参考。

/**
 * Stack that defines the bucket
 */
class Producer extends cdk.Stack {
  public readonly myBucket: s3.Bucket;

  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const bucket = new s3.Bucket(this, 'MyBucket', {
      removalPolicy: cdk.RemovalPolicy.DESTROY,
    });
    this.myBucket = bucket;
  }
}

interface ConsumerProps extends cdk.StackProps {
  userBucket: s3.IBucket;
}

/**
 * Stack that consumes the bucket
 */
class Consumer extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props: ConsumerProps) {
    super(scope, id, props);

    const user = new iam.User(this, 'MyUser');
    props.userBucket.grantReadWrite(user);
  }
}

const producer = new Producer(app, 'ProducerStack');
new Consumer(app, 'ConsumerStack', { userBucket: producer.myBucket });

I found all of the answers to be on the right path, but none explained it fully and/or well.我发现所有答案都在正确的道路上,但没有一个人能完全和/或很好地解释它。 In this example, I'm passing a VPC from a VPC stack to an ECS cluster.在此示例中,我将 VPC 从 VPC 堆栈传递到 ECS 集群。

First, add a property to the originating stack.首先,将属性添加到原始堆栈。 This property is set whenever the asset is created:每当创建资产时都会设置此属性:

export class VpcStack extends cdk.Stack {
    readonly vpc: Vpc;

    constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);
    
        // Here
        this.vpc = new Vpc(this, 'vpc', {
            maxAzs: 3,
            cidr: '10.0.0.0/16',
        });
    });
}

Next, require this property as a parameter to the consuming stack:接下来,需要此属性作为使用堆栈的参数:

// Create an interface that extends cdk.StackProps
// The VPC property is added here
interface EcsClusterStackProps extends cdk.StackProps {
    vpc: Vpc,
}

export class EcsClusterStack extends cdk.Stack {
    // Use your interface instead of the regular cdk.StackProps
    constructor(scope: cdk.Construct, id: string, props: EcsClusterStackProps) {  
        super(scope, id, props);
    
        // Use the passed-in VPC where you need it
        new Cluster(this, "myCluster", {
            capacity: {
                instanceType: InstanceType.of(InstanceClass.M6I, InstanceSize.LARGE)
            },
            clusterName: "myCluster",
            vpc: props.vpc,  // Here
        });
    }
}

Third, pass the reference in your app file:第三,在你的应用文件中传递引用:

const app = new cdk.App();

// Create the VPC stack
const vpcStack = new VpcStack(app, 'vpc-stack', {
    env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION },
});

// Pass the VPC directly to the consuming stack's constructor
const ecsClusterStack = new EcsClusterStack(app, 'ecs-cluster-stack', {
    vpc: vpcStack.vpc,  // Here
});

Hopefully this helps clarify some of the ambiguous areas.希望这有助于澄清一些模棱两可的领域。

Can I refer Autoscaling group in the above way?我可以通过上述方式引用 Autoscaling 组吗? How to refer a stack (instantiate an existing stack) before referring to in the other?在引用另一个堆栈之前如何引用堆栈(实例化现有堆栈)?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM