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

Joh*_*ohn 8 amazon-web-services aws-cloudformation aws-cdk

我有一个应用程序,它有两个堆栈,都在同一个区域/帐户内。其中一个堆栈需要另一个堆栈中存在的 lambda 的 ARN。我如何参考这个?

// 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);
Run Code Online (Sandbox Code Playgroud)

如何将 ARN 传入 StackB?

Chu*_*uck 28

CDK的官方文档有一个在堆栈之间共享S3存储桶的完整示例。我将其复制到下面以供更快参考。

/**
 * 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 });
Run Code Online (Sandbox Code Playgroud)


Abh*_*aya 9

您可以访问不同堆栈中的资源,只要它们在同一账户和 AWS 区域中即可。以下示例定义了堆栈 stack1,它定义了一个 Amazon S3 存储桶。然后它定义了第二个堆栈 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());
Run Code Online (Sandbox Code Playgroud)

  • stack1.getBucket 在哪里定义的?不定义它意味着我们必须猜测,有时我们猜测错误。 (2认同)

jtc*_*n63 8

我发现所有答案都在正确的道路上,但没有一个答案完全和/或很好地解释了它。在此示例中,我将 VPC 从 VPC 堆栈传递到 ECS 集群。

首先,向原始堆栈添加一个属性。每当创建资产时都会设置此属性:

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',
        });
    });
}
Run Code Online (Sandbox Code Playgroud)

接下来,需要此属性作为消费堆栈的参数:

// 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
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

第三,传递应用程序文件中的引用:

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
});
Run Code Online (Sandbox Code Playgroud)

希望这有助于澄清一些模棱两可的领域。


Ami*_*nes 7

选项1:

使用构造函数将数据从堆栈 A 传递到堆栈 B:

您可以扩展cdk.stack并创建一个包含 stackA 的新类。

在该堆栈中,使用public XXX: string\number (etc)(参见示例中的第 2 行)公开所需的相关数据。

稍后,只需将此数据传递给 StackB 构造函数(您也可以使用 props 传递它)。

工作代码片段:

堆栈 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 });
    
        }
    }
Run Code Online (Sandbox Code Playgroud)

堆栈 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)

    }
}
Run Code Online (Sandbox Code Playgroud)

垃圾箱:

const importedKey = new StackA(app, 'id',props).YourKey;
new StackB(app, 'id',importedKey,props);
Run Code Online (Sandbox Code Playgroud)

选项 2:

有时最好将此类内容保存在参数存储中并从那里读取。

更多信息在这里