跨账户AWS CDK Stack自动引用S3参数及多区域部署实现方法
AWS CDK跨Stack参数引用与多区域部署配置问题
我正在使用AWS CDK创建两个Stack:
- 第一个Stack通过
BucketDeployment构造创建S3存储桶,并上传Lambda压缩包,代码如下:
//FirstStack const deployments = new BucketDeployment(this, 'LambdaDeployments', { destinationBucket: bucket, destinationKeyPrefix: '', sources: [ Source.asset(path) ], retainOnDelete: true, extract: false, accessControl: BucketAccessControl.PUBLIC_READ, });
- 第二个Stack仅用于生成CloudFormation模板交付给客户,需要在其中创建Lambda函数,传入第一个Stack中上传的Lambda压缩包对应的S3存储桶名称和对象键参数,代码如下:
//SecondStack const lambdaS3Bucket = "??"; //TODO const lambdaS3Key = "??"; //TODO const bucket = Bucket.fromBucketName(this, "Bucket", lambdaS3Bucket); const lambda = new Function(this, "LambdaFunction", { handler: 'index.handler', runtime: Runtime.NODEJS_16_X, code: Code.fromBucket( bucket, lambdaS3Key ), });
现咨询两个问题:
- 如何在第二个Stack中自动引用第一个Stack的相关参数?
- 如何为
lambdaS3Bucket配置AWS::Region参数,使客户可在任意区域部署(我只需在客户所需区域运行第一个Stack)?
问题1:跨Stack自动引用参数
CDK支持通过Stack之间的属性传递实现自动引用,具体步骤如下:
在
FirstStack中暴露需要传递的属性
修改FirstStack类,将存储桶名称和BucketDeployment生成的对象键作为公共属性导出:class FirstStack extends Stack { public readonly lambdaBucketName: string; public readonly lambdaS3Key: string; constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); // 创建S3存储桶实例 const bucket = new Bucket(this, 'LambdaAssetBucket', { // 你的存储桶配置项 }); const deployments = new BucketDeployment(this, 'LambdaDeployments', { destinationBucket: bucket, destinationKeyPrefix: '', sources: [Source.asset(path)], retainOnDelete: true, extract: false, accessControl: BucketAccessControl.PUBLIC_READ, }); // 对外暴露关键属性 this.lambdaBucketName = bucket.bucketName; this.lambdaS3Key = deployments.deployedObjectKey; } }实例化
SecondStack时传入FirstStack的属性const app = new App(); const firstStack = new FirstStack(app, 'FirstStack', { env: { account: '你的AWS账号ID', region: '客户目标区域' } }); // 将FirstStack的属性作为参数传入SecondStack new SecondStack(app, 'SecondStack', { lambdaS3Bucket: firstStack.lambdaBucketName, lambdaS3Key: firstStack.lambdaS3Key });修改
SecondStack接收并使用传入的参数interface SecondStackProps extends StackProps { lambdaS3Bucket: string; lambdaS3Key: string; } class SecondStack extends Stack { constructor(scope: Construct, id: string, props: SecondStackProps) { super(scope, id, props); const bucket = Bucket.fromBucketName(this, "Bucket", props.lambdaS3Bucket); const lambda = new Function(this, "LambdaFunction", { handler: 'index.handler', runtime: Runtime.NODEJS_16_X, code: Code.fromBucket(bucket, props.lambdaS3Key), }); } }
通过以上步骤,SecondStack就能自动引用FirstStack的存储桶名称和对象键,无需手动填写固定值。
问题2:配置支持任意区域部署的存储桶参数
由于S3存储桶名称全局唯一,且你仅在客户目标区域部署FirstStack,可通过以下两种方案让SecondStack模板适配任意区域:
方案1:通过CloudFormation参数传递区域,动态拼接存储桶名称
如果你的存储桶名称采用lambda-assets-{region}-{accountId}这类包含区域的格式:
class SecondStack extends Stack { constructor(scope: Construct, id: string, props: SecondStackProps) { super(scope, id, props); // 定义区域参数,客户部署时可指定目标区域 const regionParam = new CfnParameter(this, 'TargetRegion', { type: 'String', default: this.region, description: 'AWS区域,对应Lambda资源包所在的S3存储桶部署区域' }); // 动态拼接存储桶名称 const lambdaBucketName = Fn.join('-', [ 'lambda-assets', regionParam.valueAsString, this.account ]); const bucket = Bucket.fromBucketName(this, "Bucket", lambdaBucketName); const lambda = new Function(this, "LambdaFunction", { handler: 'index.handler', runtime: Runtime.NODEJS_16_X, code: Code.fromBucket(bucket, props.lambdaS3Key), }); } }
方案2:直接传递包含区域的存储桶名称
如果FirstStack创建的存储桶名称已包含区域信息(比如创建时显式指定带区域的名称),可直接将firstStack.lambdaBucketName传递给SecondStack,客户部署时无需额外配置,因为存储桶名称已关联正确的区域。
另外需要注意:如果客户在与FirstStack不同的区域部署SecondStack,需确保FirstStack的存储桶配置了跨区域访问权限;若直接在客户目标区域部署FirstStack,则可避免跨区域访问的问题。
内容的提问来源于stack exchange,提问作者Petra Barus
相关产品推荐
相关产品推荐

