Yan*_*Liu 1 amazon-web-services aws-cloudformation aws-codepipeline aws-cdk
我有一个创建了 S3Bucket 的 ApplicationStack:
export class ApplicationStack extends Cdk.Stack {
public readonly websiteBucket : S3.Bucket;
constructor(scope: Construct, id: string, props: ApplicationStackProps) {
super(scope, id, props);
// Amazon S3 bucket to host the store website artifact
this.websiteBucket = new S3.Bucket(this, "eCommerceWebsite", {
bucketName: `${props.websiteDomain}-${account}-${region}`,
websiteIndexDocument: "index.html",
websiteErrorDocument: "error.html",
removalPolicy: Cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: true,
accessControl: S3.BucketAccessControl.PRIVATE,
encryption: S3.BucketEncryption.S3_MANAGED,
publicReadAccess: false,
blockPublicAccess: S3.BlockPublicAccess.BLOCK_ALL,
});
// Create a dummy export.
// https://www.endoflineblog.com/cdk-tips-03-how-to-unblock-cross-stack-references
this.exportValue(this.websiteBucket.bucketArn);
...
...
...
}
}
Run Code Online (Sandbox Code Playgroud)
我还定义了ApplicationStage上面包含的内容ApplicationStack
export class ApplicationStage extends Cdk.Stage {
public readonly websiteBucket : S3.Bucket;
constructor(scope: Construct, id: string, props: ApplicationStageProps) {
super(scope, id, props);
const applicationStack = new ApplicationStack(this, `eCommerceDatabaseStack-${props.stageName}`, {
stageName: props.stageName,
websiteDomain: props.websiteDomain,
});
this.websiteBucket = applicationStack.websiteBucket;
}
public getWebsiteBucket() {
return this.websiteBucket;
}
}
Run Code Online (Sandbox Code Playgroud)
在我的管道堆栈中,我想为需要将网站工件部署到其相应 S3 存储桶的每个阶段创建应用程序阶段。这是一个跨账户 CI/CD 管道,我为此网站有 3 个独立的 AWS 账户(Alpha、Gamma、Prod)。每当我发出代码时,管道应该将新工件部署到 Alpha,然后是 Gamma,然后是 Prod alpha.ecommerce.com,并且gamma.ecommerce.com, ,ecommerce.com应该按此顺序更新。当在 S3DeployAction 中引用 S3Bucket 时,就会出现问题:
export class CodePipelineStack extends CDK.Stack {
constructor(scope: CDK.App, id: string, props: CodePipelineStackProps) {
super(scope, id, props);
...
...
// Here the pipelineStageInfoList contains Gamma and Prod information.
pipelineStageInfoList.forEach((pipelineStage: PipelineStageInfo) => {
const applicationStage = new ApplicationStage(this, pipelineStage.stageName, {
stageName: pipelineStage.stageName,
pipelineName: props.pipelineName,
websiteDomain: props.websiteDomain,
env: {
account: pipelineStage.awsAccount,
region: pipelineStage.awsRegion,
},
});
const stage = pipeline.addStage(applicationStage);
// Here is what went wrong. It is trying to deploy the S3Bucket for that stage.
stage.addAction(
new codepipeline_actions.S3DeployAction({
actionName: "Deploy-Website",
input: outputWebsite,
bucket: applicationStage.getWebsiteBucket(),
})
);
});
}
...
...
...
}
Run Code Online (Sandbox Code Playgroud)
运行cdk synthesize出现以下错误:
/Users/yangliu/Projects/eCommerce/eCommerceWebsitePipelineCdk/node_modules/aws-cdk-lib/core/lib/deps.ts:39
throw new Error(`You cannot add a dependency from '${source.node.path}' (in ${describeStage(sourceStage)}) to '${target.node.path}' (in ${describeStage(targetStage)}): dependency cannot cross stage boundaries`);
^
Error: You cannot add a dependency from 'eCommerceWebsitePipelineCdk-CodePipeline-Stack' (in the App) to 'eCommerceWebsitePipelineCdk-CodePipeline-Stack/ALPHA/eCommerceDatabaseStack-ALPHA' (in Stage 'eCommerceWebsitePipelineCdk-CodePipeline-Stack/ALPHA'): dependency cannot cross stage boundaries
Run Code Online (Sandbox Code Playgroud)
我认为这意味着我在这里没有以正确的方式传递 S3Bucket 引用。
如何修复它?
根据 matthew-bonig@ 的建议,我能够完成这项工作。
我有一个单独的堆栈要部署到每个帐户,以创建 S3 存储桶及其所需的 CloudFront 分配。然后我的管道堆栈只专注于跟踪我的 GitHub 存储库,并在推送新提交时更新 S3 存储桶。
除了@Matthew 的回答之外,如果您无意中将应用程序逻辑包含在 CDK 管道逻辑中,也可能会发生这种情况。部署管道时,您的管道(首先创建)将使用您的管道无权访问的资源进行部署,因为管道尚未部署应用程序。换句话说,管道步骤“乱序”。
\n例如,如果您创建的post步骤包含您的逻辑stage(例如将Vpc在您创建的步骤传递到您的步骤stage中post),则可能会发生这种情况。
即使隐式执行此操作(例如创建construct包含多个 CDK 服务,并在这些服务之间传递变量,这些变量稍后将传递到stage管道post stage中的步骤)也会引发dependency cannot cross stage boundaries错误。
stage起初,这似乎违反直觉,因为将资源从您的步骤传递到您的步骤似乎应该很简单(并且合乎逻辑)post stage。
但是,由于 CDK Pipelines 部署管道和应用程序的方式,这不会像您预期的那样工作。
\n相反,你有三个选择(据我所知):
\n使用ssm parameters或secrets在 之间传递数据stages。注意:一个潜在的缺点是您需要部署这些secrets或parameters在部署和运行管道之前。(如果我在这里弄错了,请告诉我 \xe2\x80\x93 我已经经历过这个ssm parameters)。
Export数据的使用CfnOutput和import它的使用Fn.importValue。
创建一个Custom Resource。如果您需要长时间运行的异步实现来执行下一个任务之前stage,请使用该Provider框架。注意:截至撰写本文时,该框架仅支持 1 小时超时。如果您需要运行时间更长的东西,您需要StateMachine自己创建一个。
相关资源:
\n| 归档时间: |
|
| 查看次数: |
1633 次 |
| 最近记录: |