AWS CodePipeline - 如何部署数十个 CloudFormation / Stackset / Lambda 资源,而无需为每个文件手动创建管道操作

AWS CodePipeline - 如何部署数十个 CloudFormation / Stackset / Lambda 资源,而无需为每个文件手动创建管道操作

使用 Code Pipeline 部署数十种资源(例如 CloudFormation 模板、Stack Sets 和 Lambda 函数)的最佳方法是什么?

在 AWS 中,我有一个运行 AWS 组织的多账户架构。我希望管道在单个账户中运行。该管道将 CloudFormation 模板部署到组织内的一个或多个账户。

我目前找到的选项是:

  • 为每个源文件设置一个管道阶段或操作。这种方法效果很好,但意味着每次添加源文件时都需要修改管道,这似乎是可以自动化或消除的开销。您无法使用此方法部署 StackSets。您还需要每个帐户的每个模板都有一个要部署到的阶段,因此这种方法不切实际。

  • 使用嵌套堆栈。这样做的问题是 1) 在主堆栈中,我不知道使用什么命名约定来直接从 CodeCommit 调用其他堆栈。我可以通过让 CodeBuild 将所有文件复制到 S3 来解决这个问题,但这似乎不太优雅。2) 嵌套堆栈更难调试,因为如果它们失败,它们会被拆除和删除,因此很难找到问题的原因

  • 让 CodeBuild 运行一个 bash 脚本,该脚本使用 AWS CLI 部署所有模板。

  • 让 CodeBuild 运行 Ansible 剧本来部署所有模板。

  • 让 Lambda 在被 CodePipeline 调用后部署每个模板。这可能不是一个很好的选择,因为 Lambda 的每次调用都是针对单个模板,并且没有关于要部署到哪个账户的信息。执行所有部署的单个 Lambda 函数可能是一个选择。

理想情况下,我希望 CodePipeline 部署 CodeCommit 存储库中具有特定扩展名的每个文件,或者更好的是部署清单文件中列出的文件。但是我认为这是不可能的。

我希望避免使用任何不必要的技术或服务。我也不想使用 Jenkins、Ansible、Teraform 等,因为此脚本可以部署在多个客户站点,我不想强​​迫他们使用任何第三方技术。如果必须使用第三方,我宁愿使用可以在 CodeBuild 容器中运行的东西,而不是必须在 Jenkins 这样的实例上运行的东西。

--

自从我问了这个问题以来的经验

  • 必须在 CodeBuild 中编写 Borne Shell (sh) 脚本非常复杂、痛苦且缓慢。

  • 创建或更新 StackSet 时需要一些逻辑。如果您只是调用“创建 stackset”,更新时就会失败。

  • AWS Landing Zone 管道之所以复杂是有原因的,因为它使用了诸如步骤函数之类的东西。

  • 如果有一种简单的方法来编写逻辑,例如“如果此堆栈集存在则更新它”,事情就会简单得多。ASW CDK 是解决此问题的一种可能的方法,因为它允许您使用 Java、.Net、JavaScript 或 TypeScript 创建 AWS 基础设施。Teraform 等第三方工具也可能有所帮助,但我对它们了解不够,无法发表评论。

我将保留这个问题以便有人能找到很好的答案。

--

来自 AWS Support 的信息

AWS 给出了以下建议(我对其进行了解释,根据我的理解进行了筛选,任何错误都是我自己的,而不是 AWS 的错误建议):

  • CodePipeline 每个操作只能部署一个工件(例如 CloudFormation 模板)

  • CodePipeline 无法直接部署 StackSet,这允许跨账户部署模板。可以通过调用 CodeBuild / Lambda 来部署 StackSet。

  • CodePipeline 可以通过指定其他账户中的角色来部署到其他账户。这每次只能部署到一个账户,因此每个账户每个模板都需要一个操作

  • CodeBuild 作为 CodePipeline 的一部分在容器中运行,提供了更大的灵活性,你可以在这里做任何你喜欢的事情

  • CodePipeline 可以启动 Lambda,这非常灵活。如果您从 CodePipeline 操作启动 Lambda,则会获得单个资源的 URL,这可能会受到限制。(我的猜测)您可能可以以允许其完成整个部署的方式调用 Lambda。

答案1

我会考虑通过一个Ansible 剧本playbook.yml您可以拥有多个任务,每个 CFN 模板一个,为每个模板提供所需的参数,将输出从一个堆栈传送到下一个堆栈等。此外,Ansible 是幂等的,因此当重新运行剧本时,它只会(重新)部署已修改的内容。

这一切都可以是 CodePipeline 中的单个步骤。

现在如何实际运行它?CodePipeline 可以执行 CodeBuild、CodeDeploy、ECS Task 或 Elastic Beanstalk。我可能会选择带有 Ansible docker 镜像的 CodeBuild。为什么不想使用 CodeBuild?

如果您确实想通过 CloudFormation 方法进行 CodePipeline 部署,您可能可以创建一些执行 ansible playbook 的自定义资源,但这似乎相当复杂。

我的选择将会CodePipeline ➜ CodeBuild ➜ Ansible playbook ➜ 部署大量 CloudFormation 堆栈


顺便调试嵌套模板失败你可以随时改变筛选在控制台中失败的或者已删除并检查那里的失败堆栈事件。当它们被删除时,它们只会从默认视图中消失,但详细信息仍然存在。

但是我不喜欢复杂的嵌套模板,我发现它们比使用 Ansible 更难管理和更新。

希望有帮助:)

相关内容