繁体   English   中英

cfn 模板和管道都是使用 AWS CDK 创建的,如何使用 CodePipeline 部署 CloudFormation 堆栈?

[英]How to deploy a CloudFormation stack using CodePipeline when both, the cfn template and the pipeline where created using the AWS CDK?

使用 AWS CDK,我创建了一个带有 Auto Scaling 组的简单堆栈,并定义了启动配置资源以在 ec2 实例创建期间执行一些 powershell 脚本。 这些脚本位于同一个 cdk typescript 项目中,我使用 aws-s3-asset 构造上传脚本目录。 当 CDK 合成模板时,它会使用自动生成的名称创建 3 个 CloudFormation 参数,以引用资产的 S3 存储桶。 此时一切正常,我执行 cdk deploy StackWithAutoScalingGroup 命令,cdk 自动填充 CloudFormation 参数的值并部署堆栈。

我决定实现一个 CodePipeline 堆栈 (StackWithTheCodePipline) 来部署 StackWithAutoScalingGroup,它从 CodeCommit 存储库中获取代码并执行代码构建以合成模板,并且作为最后阶段,它是用于部署堆栈的 CodeDeploy CloudFormation 操作。 这最后一步失败了,因为 CloudFormation 参数不是由管道提供的。

我正在寻找一种从 StackWithTheCodePipline 访问在 StackWithAutoScalingGroup 中创建的 s3 Assets 存储桶的方法,以便提供所需的 CloudFormation 参数

任何帮助将不胜感激

StackWithAutoScalingGroup.ts

const captivaServer = new AutoScalingGroupStandard(this, 'CaptivaServer', {
      vpc: props.vpc,
      instanceType: ec2.InstanceType.of(ec2.InstanceClass.T2, ec2.InstanceSize.MICRO),
      machineImage: new ec2.WindowsImage(ec2.WindowsVersion.WINDOWS_SERVER_2019_ENGLISH_FULL_BASE),
    });

const scripts = new assets.Asset(this, 'Scripts', {
path: path.join('cfninit', 'scripts'),
readers: [
captivaServer.instanceRole,
]
});

StackWithAutoScalingGroup.template.json(在堆栈合成后创建的参数)

"Parameters": {
    "SsmParameterValueawsserviceamiwindowslatestWindowsServer2019EnglishFullBaseC96584B6F00A464EAD1953AFF4B05118Parameter": {
      "Type": "AWS::SSM::Parameter::Value<String>",
      "Default": "/aws/service/ami-windows-latest/Windows_Server-2019-English-Full-Base"
    },
    "ScriptsS3Bucket1E273C2D": {
      "Type": "String",
      "Description": "S3 bucket for asset \"CdkCaptivaStack/Scripts\""
    },
    "ScriptsS3VersionKey0B5B668F": {
      "Type": "String",
      "Description": "S3 key for asset version \"CdkCaptivaStack/Scripts\""
    },
    "ScriptsArtifactHashC07F896B": {
      "Type": "String",
      "Description": "Artifact hash for asset \"CdkCaptivaStack/Scripts\""
    }
  }

StackWithTheCodePipline.ts

    new codepipeline.Pipeline(this, 'Pipeline', {
      stages: [
        {
          stageName: 'Source',
          actions: [
            new codepipeline_actions.CodeCommitSourceAction({
              actionName: 'CodeCommitSource',
              repository: code,
              output: sourceOutput,
            }),
          ],
        },
        {
          stageName: 'Build',
          actions: [
            new codepipeline_actions.CodeBuildAction({
              actionName: 'BuildStack',
              project: buildProject,
              input: sourceOutput,
              outputs: [buildOutput],
            }),
          ],
        },
        {
          stageName: 'DeployToTest',
          actions: [
            new codepipeline_actions.CloudFormationCreateUpdateStackAction({
              actionName: 'DeployStack',
              templatePath: buildOutput.atPath('StackWithAutoScalingGroup.template.json'),
              stackName: 'csg-cdk-captiva',
              //parameterOverrides: props.parameterOverrides,
              adminPermissions: true,
            }),
          ],
        },
      ],
    });

该操作提供了 parameterOverrides 属性来设置所需的参数,但就像名称是自动生成的一样,我无法找到一种方法来了解模板不期望参数值的参数。

我期望的是一种了解生成的参数名称的方法,以及一种引用 s3 资产存储桶以提供参数值的方法。

       {
          stageName: 'DeployToTest',
          actions: [
            new codepipeline_actions.CloudFormationCreateUpdateStackAction({
              actionName: 'DeployStack',
              templatePath: buildOutput.atPath('StackWithAutoScalingGroup.template.json'),
              stackName: 'csg-cdk-captiva',
              parameterOverrides: {
                   'ScriptsS3Bucket1E273C2D':????,//how I can get the param name and also the values
                   'ScriptsS3VersionKey0B5B668F':???,
               }
              adminPermissions: true,
            }),
          ],
        },

我不确定如何设置。 我相信您也许可以做类似的事情

let yourS3Bucket = cdk.S3(blah)

parameterOverrides: {
  yourS3Bucket:yourS3Bucket.<your_property>
}

代替

parameterOverrides: {
                   'ScriptsS3Bucket1E273C2D':????,//how I can get the param name and also the values
                   'ScriptsS3VersionKey0B5B668F':???,
               }

这些都是伪代码。 本质上,您可以将S3存储桶分配给变量,然后在以后引用该变量。

你可以做几件事:

  1. 在您的存储桶上使用一个集合名称(或在部署时使用上下文变量定义一个变量前缀的集合名称),然后使用 Bucket.fromAttributes 将其导入到您的其他堆栈中

  2. 将 Bucket 对象作为堆栈上的属性公开。 当您在应用程序中实例化堆栈时,您可以将该属性作为自定义参数引用到另一个堆栈中(伪代码)

在给定的堆栈内...

my_bucket = s3.Bucket...

在您的应用程序中

my_stack = MyStack(...
...
second_stack=SecondStack(.... specialBucket:mystack.my_bucket

在第二个堆栈中

你需要桶的东西(桶:specialBucket

这种方法的问题在于它链接了两个堆栈,从而在它们之间建立了依赖关系。 这反过来意味着对一个堆栈的更改可能无法部署,因为另一个堆栈会不同步。 您可以通过在通用应用程序堆栈中创建 MyStack 和 SecondStack(来自上述示例)嵌套堆栈来解决此问题。 这使您能够在堆栈之间移动部分并将它们全部部署为 CloudFormation 堆栈方面的单个应用程序,从而防止部署问题

最后...如果你部署不需要大量的复杂的步骤和东西跟着,我发现它容易简单地用一个CodeBuild,安装预编译期间CDK和运行CDK部署堆叠*从内代码构建。 以这种方式排列资产和诸如此类的东西要容易得多。

CodeCommit -> CodeBuild(即 cdk 部署)

暂无
暂无

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

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