如何通过CDK创建CodePipeline部署S3中GitLab CI生成的CFN模板?
GitLab CI合成CFN模板后通过CodePipeline部署的配置方案
场景说明
- 在GitLab Pipeline中执行
cdk synth生成CloudFormation模板文件,上传至S3存储桶 - 借助AWS CodePipeline完成模板的栈部署
- 核心优势:GitLab侧先完成代码校验,再利用成本更低的CodePipeline执行部署流程
GitLab CI 配置代码
cdk synth > template.yml aws s3 cp template.yml s3://testbucket/project
问题
现有CDK Pipeline代码中,CloudFormationCreateUpdateStackAction的template_path要求传入ArtifactPath类型对象,不想通过拉取整个GitLab仓库作为CodePipeline的代码源,需要更简便的配置方式。
原CDK代码片段:
from aws_cdk import Stack from constructs import Construct from aws_cdk import pipelines as pipelines from aws_cdk import aws_codepipeline as codepipeline from aws_cdk import aws_s3 as s3 class CodePipelineStack(Stack): def __init__(self, scope: Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) self.rcs_cdk_pipeline = codepipeline.Pipeline( self, "rcs-cdk-code-pipeline" ) self.stage_source = self.rcs_cdk_pipeline.add_stage(stage_name="Source") self.stage_source.add_action( codepipeline_actions.CloudFormationCreateUpdateStackAction( action_name="rcs-deploy-stacks", stack_name="RcsRootStack", admin_permissions=True, template_path=??? # 此处应为S3地址 ) )
解决方案
核心思路:将S3存储桶作为CodePipeline的源,仅拉取已生成的CFN模板文件作为Artifact,再在部署阶段引用该Artifact路径。
修改后的完整CDK代码
from aws_cdk import Stack from constructs import Construct from aws_cdk import aws_codepipeline as codepipeline from aws_cdk import aws_codepipeline_actions as codepipeline_actions from aws_cdk import aws_s3 as s3 class CodePipelineStack(Stack): def __init__(self, scope: Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # 1. 获取存储模板的S3桶(如果桶是预先创建的,用from_bucket_name导入;如果是CDK创建的,直接引用对象) template_bucket = s3.Bucket.from_bucket_name(self, "TemplateBucket", "testbucket") # 2. 创建一个Artifact用来存放从S3拉取的模板文件 template_artifact = codepipeline.Artifact("TemplateArtifact") # 3. 创建CodePipeline实例 self.rcs_cdk_pipeline = codepipeline.Pipeline( self, "rcs-cdk-code-pipeline" ) # 4. 配置Source阶段:拉取S3中的template.yml source_stage = self.rcs_cdk_pipeline.add_stage(stage_name="Source") source_stage.add_action( codepipeline_actions.S3SourceAction( action_name="FetchTemplateFromS3", bucket=template_bucket, bucket_key="project/template.yml", # 对应GitLab CI上传的路径 output=template_artifact ) ) # 5. 配置部署阶段:使用拉取到的模板部署CFN栈 deploy_stage = self.rcs_cdk_pipeline.add_stage(stage_name="Deploy") deploy_stage.add_action( codepipeline_actions.CloudFormationCreateUpdateStackAction( action_name="rcs-deploy-stacks", stack_name="RcsRootStack", admin_permissions=True, template_path=template_artifact.at_path("template.yml") # 引用Artifact中的模板路径 ) )
关键细节说明
- S3源配置:通过
S3SourceAction直接拉取指定路径下的模板文件,无需拉取整个仓库,满足轻量源的需求。 - Artifact引用:
template_artifact.at_path("template.yml")生成符合要求的ArtifactPath对象,直接传入部署动作的template_path参数。 - 权限处理:CDK会自动为CodePipeline角色添加读取目标S3桶的权限;如果桶是外部创建的,需确保桶的权限策略允许CodePipeline角色访问。
可选优化:模板版本化
为避免模板被覆盖,可在GitLab CI上传时添加唯一标识(如Git提交哈希),命令修改为:
cdk synth > template.yml TEMPLATE_FILE="template-$(git rev-parse HEAD).yml" aws s3 cp template.yml s3://testbucket/project/${TEMPLATE_FILE}
对应CDK中S3SourceAction的bucket_key需改为动态值,或配合S3事件触发CodePipeline执行(需额外配置S3触发器)。
内容的提问来源于stack exchange,提问作者Zu Jiry
相关产品推荐
相关产品推荐

