你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

使用 Bicep 和 Azure 容器注册表处理企业基础结构即代码

Azure 容器注册表
Azure DevOps
Azure Kubernetes 服务 (AKS)
Azure 资源管理器
Azure Policy

模块化 Azure 资源管理器模板(ARM 模板)的管理可以减少重复,为基础结构开发中的最佳做法建模,并获得一致的标准部署。

实现这种模块化的一个示例用例是使用 T 恤尺寸的隐喻来部署虚拟机 (VM)。 假设你已部署数十或数百个 VM。 这些部署使用模板版本 1.0.0,并使用旧系列的标准中等大小。 如果你只部署了新模板,则过渡到新系列可能需要短暂中断服务。 但是,通过生成版本 1.5.0 并使用模块化,可以使用更新的标准来部署新的基础结构,同时使旧基础结构保持可部署状态。 通过提供旧版本的基础结构,产品和应用程序团队可以在有时间升级到新版本时依赖于已知良好的配置。

存储库的层堆叠:企业示例

当谈到模板的应用范围、更新方式等方面的强烈偏好时,有两个主要考虑因素:分支和内包。

  • 分支。 此示例方案有利于支持 GitflowGitHub 流的 git 分支模型。 有关 Gitflow 的详细信息,请参阅 Jeff Kreeftmeijer 的博客文章 Using git-flow to automate your git branching workflow(使用 git-flow 自动化 git 分支工作流)。 有关 GitHub 流的详细信息,请参阅 GitHub 文档中的 GitHub 流

  • 内包。 第二个因素是内包,即,将开源软件开发的协作实践引入内部开发。 在这种情况下,你可以更自信地共享不同的模板和模块源代码,而无需担心部署模型本身的权限。 有关内包开发的详细信息,请参阅 GitHub 上的内包简介

Bicep 是用于部署 Azure 资源的一种声明性语言。 Bicep 的可重用代码可将 Azure 容器注册表用作专用注册表来托管版本受控的 ARM 模板。 以这种方式使用容器注册表,企业可为基础结构建立持续集成和持续交付 (CI/CD) 流程。 你可以在 CI 流程中运行集成和单元测试,而容器注册表可以在模块成功生成后接收模块。 应用团队在准备好升级之前可以继续使用旧版本,或者可以更新以利用新版模板中的功能。

除了使用容器注册表之外,还可将此模型与 Azure Verified Modules 等功能配合使用。 实现可以使用公共注册表中的数据,最好是监视公共存储库并将更改拉入专用注册表以便进一步使用。 将更改拉入你自己的容器注册表可以针对公共模块运行测试,同时确保在合并质量和安全实践之前不会在生产环境中使用这些更改。

图层

此示例方案中建议的模型是一个堆叠的模型。 越靠近堆叠结构顶部的层中的部署越频繁,且部署定制程度越高。 Bicep 代码提供一致的部署。 开发团队在其贡献层中工作,从下面的层中提供的服务和基础结构生成解决方案。 下层中的任何组件都不应依赖于上层中的资源。 从第 0 层到第 3 层是全局库、全局基础结构(全局共享服务)、产品平台(共享服务)和应用程序。

Diagram that shows the layers of development, ordered by development frequency.

此模型可以建立自治性和一致性,即,其中提供:

  • 可供企业方便使用的常用工具。 例如,每个人都使用 git 进行源代码管理,并使用 GitHub Actions 实现 CI/CD。 但是,我们都不过分。 例如,我们不要求所有团队都使用 Bicep;他们可以使用 Terraform、ARM 模板和其他工具。

  • 分享最佳做法的功能。 他们可以采用 ARM 模板、黄金映像或代码片段的形式。 最佳做法也可以是特定技术的文档。 例如,如何在环境中轮换密钥以及如何测试代码。

  • 某些服务在堆叠结构中向下移动。 例如,某个应用团队可能最初开发了一个用于部署 Kubernetes 群集的模板,然后将其作为共享服务拉入产品平台。 此模板如此有用,以至于它被拉入示例库。

第 0 层 - 全局库

底层是全局库,它是一个未部署到生产环境中的有用片段的存储库。 从访问控制的角度看,应该向公司中请求读取访问权限的任何人提供这种访问权限。 对于更改、建议等,云卓越中心 (CCoE) 会审批 PR 并管理积压工作,就如同它是任何其他产品一样。

Screen shot of the folder structure of layer 0, global infrastructure library, with the 'arm' folder selected.

第 0 层不应包含:

  • 在生产环境中部署的模板。
  • 机密或特定于环境的配置。

第 0 层应包含:

  • 代码片段(Python、C# 等)。
  • Azure Policy 示例。
  • 可用作示例的 ARM 模板、Bicep 模板或 Terraform 文件。

例如,这是一个示例体系结构,它演示公司如何在没有任何特定于环境的信息的情况下为三层应用程序编写部署。 此示例体系结构可以包含标记、网络、网络安全组等。 省略环境的特定信息是有用做法,因为并非所有内容都可以或者需要放入模块。 尝试这样做可能会导致过度参数化。

此外,第 0 层可以链接到其他已知良好的示例代码源,例如 Terraform 注册表或 Azure 资源模块。 如果你的组织采用来自这些源的代码或模式,我们建议将代码或模式拉入你自己的第 0 层,而不要直接从公共源中拉取。 依赖于第 0 层可以编写自己的测试、调整方案和安全配置。 如果不依赖于公共资源,则可以减少依赖于可能被意外删除的内容而带来的风险。

要使示例代码被视为合理,模板和模块应遵循良好的开发实践,包括安全性和组织要求的输入验证。 为了保持这种严格程度,应该向主分支添加策略,以要求对建议的更改进行拉取请求 (PR) 和代码评审,如果合并更改,这些更改将流入主容器注册表。

第 0 层为 Azure Pipelines 或 GitHub Actions 馈送数据,以便在 Azure 容器注册表中自动创建版本受控的项目。 可为 git 提交消息生成自动化,以实现项目的语义版本控制。 要使这种方法正常进行,需有一个确定性的命名标准,例如 <service>.bicep,使自动化始终可维护。 使用适当的分支策略,还可以添加集成测试作为代码评审的先决条件。 可以使用 Pester 等工具进行检测。

实施这些策略和保护措施后,容器注册表可以成为企业中随时可供使用的基础结构模块的事实来源。 应考虑标准化更改日志以及可用代码示例的索引,使此代码可供发现。 未知代码是未使用的代码!

第 1 层 - 全局基础结构:全局共享服务

第 1 层是 Azure 登陆区域构造的存储库。 虽然 Microsoft 提供了用于部署 Azure 登陆区域的模板,但建议修改某些组件并提供参数文件。 这类似于将公共注册表和模块存储库拉入第 0 层,如前所述。

Screen shot of the contents of the 'infrastructure' and 'policy' folders in layer 1, global infrastructure (globally shared services).

Azure 容器注册表是此体系结构的关键部分。 即使你的公司不打算使用容器,也必须部署容器注册表才能成功地对 Bicep 模板进行版本控制。 容器注册表使模块具备很高的灵活性和可重用性,同时提供企业级安全性和访问控制。

第 1 层应包含:

  • 在管理组或订阅级别应用的策略分配和定义。 这些策略应符合企业治理要求。
  • 核心网络基础结构的模板,例如 ExpressRoute、VPN、虚拟 WAN 和虚拟网络(共享或中心)。
  • DNS。
  • 核心监视(日志分析)。
  • 企业容器注册表。

应配置分支保护以限制将更改推送到此存储库的能力。 仅限 CCoE 或云治理成员审批来自其他开发人员的 PR。 此层的参与者主要是曾经与此层中的组件关联的组的成员。 例如,网络团队为网络生成模板,运营团队配置监视,等等。 但是,应该为请求只读访问权限的个人授予这种访问权限,因为这样才能使其他组中的开发人员能够对核心基础结构提出更改建议。 他们可能会参与改进,但不能在未经批准和测试的情况下合并他们的更改。

这些文件应该使用标准组件的容器注册表中的模块。 但是,你还有一个或一系列已针对企业的 Azure 登陆区域或类似治理结构的实现进行自定义的 Bicep 文件。

第 2 层 - 产品平台:共享服务

可将第 2 层(产品平台)视为特定产品线或业务单位的共享服务。 这些组件不是在整个组织中通用的,而是旨在满足特定的业务需求。 对于与第 1 层(全局基础结构)中的中心建立对等关系的虚拟网络,这是一个适当的层。 密钥保管库是此层的另一个示例组件。 密钥保管库可将共享机密存储到由此平台内的不同应用程序共享的存储帐户或数据库。

Screen shot of the contents of the 'infrastructure' and 'platform-code' folders in layer 2, product platform (shared services).

第 2 层应包含:

  • 应用于订阅或资源组以匹配产品特定要求的策略分配。
  • 用于密钥保管库、日志分析、SQL 数据库(如果产品中的各种应用程序使用数据库)和 Azure Kubernetes 服务的 ARM 模板。

应实施权限来限制将更改推送到此存储库的能力。 与其他层一样,应使用分支保护来确保产品主管或所有者可以审批来自其他开发人员的 PR。 在对产品平台的读取访问权限方面没有固定的规则,但至少应为任何应用程序团队中的开发人员授予读取访问权限,以便能够提出更改建议。 由于第 2 层可能包含某种专有体系结构或类似信息,你可能会选择限制组织中使用平台的人员的访问。 但是,如果存在这种情况,请确保构建一个从此存储库中收集良好做法和片段的流程,以便与全局库(第 0 层)共享。

第 3 层 - 应用程序

第 3 层(应用程序层)包括构建在产品平台之上的组件。 这些组件提供业务部门请求的功能。 例如,对于流式处理平台,一个应用可以提供搜索功能,而另一个应用可以提供建议。

Screen shot of the contents of the 'app' and 'infrastructure' folders in layer 3, applications.

第 3 层应包含:

  • C#、Python 等语言的应用程序代码。
  • 单个组件的基础结构(即仅在此应用程序中使用):函数、Azure 容器实例、事件中心。

用于将更改推送到此存储库的权限受到限制。 应使用分支保护来使此应用程序的团队成员能够审批另一个团队成员提出的 PR。 不应允许团队成员审批他们自己的更改。 由于此层可能包含专有体系结构、业务逻辑或类似信息,你可能会选择限制组织中生成此应用程序的人员的访问。 但是,如果存在这种情况,则还应该构建一个从此层收集良好做法和片段的流程,以与全局库(第 0 层)共享。

跨层共同性

虽然本文介绍了每一层的某些具体细节,但还应该考虑所有层的一些特质。

基础结构应该像应用程序一样运行。 这意味着,应该构建一个持续集成 (CI) 流程,在其中对新功能进行全面测试,包括单元测试、冒烟测试和集成测试。 应该只将通过这些测试的代码合并到主发布分支中。

此外,应确保实施分支策略,以防止个人规避流程,即使出于权宜之计。 如果 CI 流程被视为障碍,则意味着你已经承担了必须处理的技术债务。 这并不意味着需要去除策略和保护措施。

最后,尽管你可能没有所有存储库及其中的代码的索引,但组织应该开发一个流程,供个人请求访问存储库。 某些规则可以完全自动化。 例如,可以实施一条规则,以便向产品团队中的参与者授予对属于产品的任何应用程序的读取访问权限,而无需进行评审。 通常可以在环境中使用基于组的成员身份和基于组的角色分配来实施此类规则。 配置这种访问权限应该有助于促进内包和组织培训工作。

作者

本文由 Microsoft 维护, 它最初是由以下贡献者撰写的。

主要作者:

其他参与者:

后续步骤