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

在 Azure 上部署和测试任务关键型工作负荷

任务关键环境的部署和测试是整体参考体系结构的关键部分。 单个应用程序标记使用源代码存储库中的基础结构即代码进行部署。 对基础设施和应用程序的更新应该在应用程序零停机的情况下部署。 建议使用 DevOps 持续集成管道从存储库中检索源代码,并在 Azure 中部署单个标记。

部署和更新是体系结构中的中心过程。 基础结构和应用程序相关的更新应部署到完全独立的标记。 只有体系结构中的全局基础结构组件才能跨标记共享。 不会触摸基础结构中的现有标记。 基础结构更新将部署到这些新标记。 同样,新应用程序版本将部署到这些新标记。

新标记将添加到 Azure Front Door。 流量逐渐转移到新的标记。 当从新标记中提供流量而不发出时,将删除以前的标记。

建议对部署的环境进行渗透、混乱和压力测试。 主动测试基础结构会发现弱点,以及部署的应用程序在发生故障时的行为方式。

部署

参考体系结构中的基础结构部署取决于以下过程和组件:

  • DevOps - GitHub 中的源代码和基础结构的管道。

  • 零停机更新 - 更新和升级部署到环境,部署的应用程序不会停机。

  • 环境 - 用于体系结构的短期和永久环境。

  • 共享和专用资源 - 专用和共享到标记和整体基础结构的 Azure 资源。

部署过程的流程图。

有关详细信息,请参阅 Azure 上任务关键型工作负荷的部署和测试:设计注意事项

部署:DevOps

DevOps 组件提供源代码存储库和 CI/CD 管道,用于部署基础结构和更新。 GitHub 和 Azure Pipelines 被选为组件。

  • GitHub - 包含应用程序和基础结构的源代码存储库。

  • Azure Pipelines - 体系结构用于所有生成、测试和发布任务的管道。

用于部署的设计中的额外组件是生成代理。 Microsoft托管生成代理用作 Azure Pipelines 的一部分,用于部署基础结构和更新。 使用 Microsoft 托管生成代理可减轻开发人员维护和更新生成代理的管理负担。

有关 Azure Pipelines 的详细信息,请参阅 什么是 Azure Pipelines?

DevOps 管道流程的示意图。

有关详细信息,请参阅 Azure 上任务关键型工作负荷的部署和测试:基础结构即代码部署

部署:零停机更新

参考体系结构中的零停机时间更新策略是整个任务关键型应用程序的核心。 替换而不是升级标记的方法可确保将应用程序全新安装到基础结构标记中。 参考体系结构利用蓝/绿方法,允许单独的测试和开发环境。

参考体系结构有两个主要组件:

  • 基础结构 - Azure 服务和资源。 使用 Terraform 及其关联的配置进行部署。

  • 应用程序 - 为用户提供服务的托管服务或应用程序。 基于用于单页应用程序 (SPA) UI 的 HTML 和 JavaScript 中的 Docker 容器和 npm 生成项目。

在许多系统中,假设应用程序更新比基础结构更新更频繁。 因此,为每个更新制定了不同的过程。 使用公有云基础结构时,更改的速度可能会更快。 选择了一个用于应用程序更新和基础结构更新的部署过程。 一种方法可确保基础结构和应用程序更新始终同步。此方法允许:

  • 一个一致的过程 - 如果基础结构和应用程序更新在发布中混合在一起,有意或无意地混合在一起,则出错的可能性更少。

  • 启用蓝/绿部署 - 每次更新都是通过将流量逐步迁移到新版中部署的。

  • 更轻松地部署和调试应用程序 - 整个环境永远不会同时托管应用程序的多个版本。

  • 简单回滚 - 如果遇到错误或问题,可以将流量切换回运行以前的版本的标记。

  • 消除手动更改和配置偏移 - 每个环境都是全新的部署。

有关详细信息,请参阅 Azure 上任务关键型工作负载的 部署和测试:短暂性的蓝/绿部署

分支策略

更新策略的基础是使用 Git 存储库中的分支。 参考体系结构使用三种类型的分支:

分支 描述
feature/*fix/* 任何更改的入口点。 开发人员创建这些分支,应提供描述性名称,例如 feature/catalog-updatefix/worker-timeout-bug。 准备合并更改时,将创建针对 main 分支的拉取请求 (PR)。 必须至少有一名审阅者批准所有拉取请求。 在有限的例外情况下,PR 中提出的每个更改都必须通过端到端 (E2E) 验证管道运行。 开发人员应使用 E2E 管道来测试和调试对完整环境的更改。
main 持续向前移动和稳定分支。 主要用于集成测试。 仅通过拉取请求更改 main。 分支策略禁止直接写入。 从 main 分支自动执行针对永久 integration (int) 环境的夜间发布。 main 分支被视为稳定。 假设在任何给定时间,都可以从中创建发布,这是安全的。
release/* 发布分支仅从 main 分支创建。 分支遵循格式 release/2021.7.X。 使用分支策略,以便仅允许存储库管理员创建 release/* 分支。 仅使用这些分支部署到 prod 环境。

有关详细信息,请参阅 Azure 上任务关键型工作负荷的部署和测试:分支策略

修补程序

当由于 bug 或其他问题而紧急需要修补程序并且无法完成常规发布过程时,可以使用修补程序路径。 初始测试期间未发现的用户体验的关键安全更新和修复被认为是热修复的有效示例。

必须在新 fix 分支中创建修补程序,然后使用常规 PR 合并到 main 中。 修补程序不是创建新的发布分支,而是将修补程序“切入”现有发布分支。 此分支已部署到 prod 环境。 最初使用所有测试部署发布分支的 CI/CD 管道将再次执行,将修补程序部署为管道的一部分。

为了避免重大问题,修补程序必须包含一些独立提交,这些提交可以轻松选取并集成到发布分支中。 如果无法选择独立提交以集成到发布分支中,则表明更改不符合修补程序的条件。 将更改作为完整的新版本进行部署。 将其与回退到以前的稳定版本相结合,直到可以部署新版本。

部署:环境

参考体系结构对基础结构使用两种类型的环境:

  • 生存期短 - E2E 验证管道用于部署生存期较短的环境。 短期环境用于纯粹的验证或调试,供开发人员使用。 可以从 feature/* 分支创建验证环境,接受测试,然后在所有测试都成功时销毁。 调试环境与验证部署方式相同,但不会立即销毁。 这些环境不应超过几天,并且应在合并功能分支的相应 PR 时删除。

  • 永久 - 在永久环境中,有 integration (int)production (prod) 版本。 这些环境持续运行,不会销毁。 环境使用固定域名,如 int.mission-critical.app。 在参考体系结构的实际实现中,应添加 staging(预生成)环境。 staging 环境用于部署和验证 release 分支,其更新过程与 prod(蓝/绿部署)相同。

    • 集成 (int) - 版本 int 每晚从 main 分支部署,过程与 prod 一样。 流量的切换速度比上一个发布单元快。 跟 prod 中一样,无需在几天内逐步切换流量,只需几分钟或几个小时即可完成 int 的过程。 这种更快的切换可确保更新的环境在第二天早上准备就绪。 如果管道中的所有测试都成功,则会自动删除旧标记。

    • 生产 (prod) - 版本 prod 仅从 release/* 分支部署。 流量切换使用更精细的步骤。 手动审批门位于每个步骤之间。 每个版本都会创建新的区域戳,并将新的应用程序版本部署到这些戳。 过程中不会接触现有标记。 对于 prod 尔雅,最重要的考量因素是,它应该“始终打开”。 不应发生计划内或计划外停机。 唯一的例外是数据库层的基础性更改。 可能需要计划内维护时段。

部署:共享和专用资源

参考体系结构中的永久环境(intprod)具有不同类型的资源,具体取决于它们是否与整个基础结构共享或专用于单个标记。 资源可以专用于特定版本,并且仅在下一个发布单元接管之前存在。

发布单位

发布单元是每个特定发布版本的多个区域标记。 标记包含未与其他标记共享的所有资源。 这些资源包括虚拟网络、Azure Kubernetes 服务群集、事件中心和 Azure Key Vault。 Azure Cosmos DB 和 ACR 配置了 Terraform 数据源。

全球共享资源

发布单元之间共享的所有资源都在独立的 Terraform 模板中定义。 这些资源包括 Front Door、Azure Cosmos DB、容器注册表(ACR)和 Log Analytics 工作区和其他与监视相关的资源。 在部署发布单元的第一个区域标记之前,部署这些资源。 这些资源在标记的 Terraform 模板中引用。

前门

虽然 Front Door 是跨邮票的全球共享资源,但其配置与其他全局资源略有不同。 部署新标记后,必须重新配置 Front Door。 必须重新配置 Front Door,以便将将流量逐步切换到新标记。

Front Door 的后端配置不能直接在 Terraform 模板中定义。 配置是通过 Terraform 变量插入的。 变量值是在 Terraform 部署启动之前构造的。

Front Door 部署中各个独立组件的配置定义为:

  • 前端 - 会话相关性配置为确保用户在单个会话期间不会在不同的 UI 版本之间切换。

  • 原点 - Front Door 配置了两种源组:

    1. 用于提供 UI 的静态存储的源组。 该组包含来自所有当前处于活动状态的发布单元的网站存储帐户。 可以将不同的权重分配给来自不同发布单元的源,以便逐渐将流量移动到较新的单位。 发布单元中的每个原点都应分配相同的权重。

    2. API 的源组,托管在 Azure Kubernetes 服务上。 如果存在不同 API 版本的发布单元,则每个发布单元都存在 API 源组。 如果所有发布单元都提供相同的兼容 API,则所有源都会添加到同一组并分配不同的权重。

  • 路由规则 - 有两种类型的路由规则:

    1. 与 UI 存储源组关联的 UI 路由规则。

    2. 当前由源支持的每个 API 的路由规则。 例如:/api/1.0/*/api/2.0/*

    如果发布引入了新版本的后端 API,则更改将反映在作为发布一部分部署的 UI 中。 UI 的特定版本始终调用 API URL 的特定版本。 使用某个 UI 版本的用户会自动利用相应的后端 API。 API 版本的不同实例需要特定的路由规则。 这些规则与相应的源组相关联。 如果未引入新的 API,则与 API 相关的所有路由规则都链接到单个源组。 在这种情况下,用户所使用的 UI 版本与 API 版本是否相同并不重要。

部署:部署过程

蓝/绿部署是部署过程的目标。 release/* 分支中的新版本将部署到 prod 环境中。 用户流量逐渐转移到新版本的标记中。

在新版本部署流程的第一步中,使用 Terraform 部署新发布单元的基础设施。 执行基础结构部署管道会从所选发布分支部署新基础结构。 与基础结构预配并行,容器映像生成或导入并推送到全局共享容器注册表(ACR)。 完成上述进程后,应用程序将部署到标记。 从实现的角度来看,它是一个具有多个依赖阶段的管道。 可以针对修补程序部署重新执行同一管道。

部署并验证新版本单元后,新单元将添加到 Front Door 以接收用户流量。

应该计划设置一个开关或参数,以区分引入新 API 版本的发布与不引入的发布。 如果版本引入了新的 API 版本,则必须创建一个具有 API 后端的新源组。 或者,可以将新的 API 后端添加到现有源组。 新的 UI 存储帐户将添加到相应的现有源组。 应根据所需的流量拆分设置新源的权重。 必须创建与相应源组对应的新路由规则,如前所述。

作为添加新发布单元的一部分,新源的权重应设置为所需的最小用户流量。 如果未检测到任何问题,则应在一段时间内将用户流量增加到新的源组。 若要调整权重参数,应使用所需值再次执行相同的部署步骤。

释放单元拆解

作为发布单元部署管道的一部分,不再需要发布单元后,销毁阶段会删除所有标记。 所有流量将被转向一个新发布版本。 此阶段包括从 Front Door 中删除发布单元引用。 此删除对于日后推出新版本至关重要。 Front Door 必须指向单个发布单元,以便为将来的下一个发布做好准备。

清单

作为发布节奏的一部分,应使用发布前和发布后清单。 以下示例包含至少在任何清单包含中的项。

  • 预发行清单 - 在开始发布之前,请检查以下内容:

    • 确保 main 分支的最新状态已成功部署到 int 环境并经过测试。

    • 通过 PR 针对 main 分支更新更改日志文件。

    • main 分支创建 release/ 分支。

  • 发行后清单 - 在销毁旧标记之前,将其引用从 Front Door 中删除,请检查:

    • 群集不再接收传入流量。

    • 事件中心和其他消息队列不包含任何未处理的消息。

部署:更新策略的限制和风险

此参考体系结构中所述的更新策略具有一些应提及的限制和风险:

  • 更高的成本 - 发布更新时,许多基础结构组件在发布期间处于活动状态两次。

  • Front Door 更新过程的复杂性 - 在 Front Door 中,更新过程的实现和维护非常复杂。 执行有效的蓝/绿部署并实现零停机时间的能力取决于其能否正常工作。

  • 较小的更改耗时 - 更新过程会导致较小的更改的发布过程更长。 通过上一部分所述的修补程序过程,可以部分缓解此限制。

部署:应用程序数据转发兼容性注意事项

更新策略可以支持多个版本的 API 和同时执行的工作组件。 由于 Azure Cosmos DB 在两个或更多版本之间共享,因此一个版本更改的数据元素可能并不总是与使用它的 API 版本或辅助角色的版本匹配。 API 层和工作单元必须实现前向兼容性设计。 早期版本的 API 或辅助角色组件处理由更高版本的 API 或辅助角色组件版本插入的数据。 它忽略它无法理解的部分。

测试

参考体系结构包含测试实现中不同阶段使用的不同测试。

这些测试包括:

  • 单元测试 - 这些测试验证应用程序的业务逻辑是否按预期工作。 参考体系结构包含 Azure Pipelines 在每个容器生成之前自动执行的单元测试示例套件。 如果任何测试失败,管道将停止。 生成和部署停止。 开发人员必须先修复此问题,然后才能再次执行管道。

  • 负载测试 - 这些测试有助于评估给定工作负荷或堆栈的容量、可伸缩性和潜在瓶颈。 参考实现包含用户负载生成器,用于创建可用于模拟真实流量的合成负载模式。 负载生成器也可以独立于引用实现使用。

  • 冒烟测试 - 这些测试确定基础结构和工作负载是否可用并按预期运行。 冒烟测试作为每个部署的一部分执行。

  • UI 测试 - 这些测试验证是否已部署用户界面并按预期工作。 当前实现仅在部署后捕获多个页面的屏幕截图,而无需进行任何实际测试。

  • 故障注入测试 - 这些测试可以自动执行或手动执行。 体系结构中的自动测试将 Azure Chaos Studio 作为部署管道的一部分集成。

有关详细信息,请参阅 azure 上任务关键型工作负荷的 部署和测试:持续验证和测试

测试:框架

联机参考应尽可能实现现有的测试功能和框架。

框架 测试 描述
NUnit 计价单位 此框架用于单元测试实现的 .NET Core 部分。 Azure Pipelines 在容器生成之前自动执行单元测试。
使用 Azure 负载测试的 JMeter 负荷 Azure 负载测试 是用于执行 Apache JMeter 负载测试定义的托管服务。
蝗虫 负荷 Locust 是用 Python 编写的开源负载测试框架。
剧作家 UI 和烟雾 Playwright 是一个开源 Node.js 库,用于使用单个 API 自动执行 Chromium、Firefox 和 WebKit。 Playwright 测试定义也可以独立于参考实现使用。
Azure Chaos Studio 故障注入 参考实现使用 Azure Chaos Studio 作为端到端验证管道中的可选步骤,通过注入故障进行韧性验证。

测试:故障注入测试和混沌工程

分布式应用程序应能够复原服务中断和组件中断。 故障注入测试(也称为故障注入或混沌工程)是将应用程序和服务应用于实际压力和故障的做法。

复原是整个系统的属性,注入错误有助于在应用程序中发现问题。 解决这些问题有助于验证应用程序对不可靠的条件、缺少依赖项和其他错误的复原能力。

可以针对基础结构执行手动和自动测试,以查找实现中的故障和问题。

自动

参考体系结构集成了 Azure Chaos Studio 来部署和运行一组 Azure Chaos Studio 试验,以在标记级别注入各种故障。 混沌试验可以作为 E2E 部署管道的可选部分执行。 执行测试时,始终并行执行可选的负载测试。 负载测试用于在群集上创建负载,以验证注入故障的影响。

手动

应在 E2E 验证环境中执行手动故障注入测试。 此环境可确保完全具有代表性的测试,而不会受到其他环境干扰的风险。 可以使用 Application Insights 实时指标 视图直接观察随测试生成的大多数故障。 剩余的失败在“故障”视图和相应的日志表中可用。 其他故障需要更深入的调试,例如使用 kubectl 来观察 Azure Kubernetes 服务内部的行为。

针对参考体系结构执行的故障注入测试的两个示例包括:

  • 基于 DNS(域名服务)的故障注入 - 可以模拟多个问题的测试用例。 由于 DNS 服务器或 Azure DNS 失败,DNS 解析失败。 基于 DNS 的测试可以帮助模拟客户端和服务之间的常规连接问题,例如,当 BackgroundProcessor 无法连接到事件中心时。

    在单主机方案中,可以修改本地 hosts 文件以覆盖 DNS 解析。 在具有多个动态服务器(如 AKS)的大型环境中,hosts 文件不可行。 Azure 专用 DNS 区域 可用作测试失败方案的替代方法。

    Azure 事件中心和 Azure Cosmos DB 是参考实现中使用的两项 Azure 服务,可用于注入基于 DNS 的故障。 可以使用绑定到其中一个标记的虚拟网络的 Azure 专用 DNS 区域操作事件中心 DNS 解析。 Azure Cosmos DB 是具有特定区域终结点的全局复制服务。 对这些终结点的 DNS 记录的操作可以模拟特定区域的故障,并测试客户端的故障转移。

  • 防火墙阻止 - 大多数 Azure 服务都支持基于虚拟网络和/或 IP 地址的防火墙访问限制。 在参考基础结构中,这些限制用于限制对 Azure Cosmos DB 或事件中心的访问。 一个简单的过程是删除现有的 允许 规则,或添加新的 阻止 规则。 此过程可以模拟防火墙配置错误或服务中断。

    可以使用防火墙测试测试引用实现中的以下示例服务:

    服务 结果
    密钥库 阻止访问 Key Vault 时,最直接的影响是新 Pod 无法生成。 在 Pod 启动时提取机密的 Key Vault CSI 驱动程序无法执行其任务并阻止 Pod 启动。 通过 kubectl describe po CatalogService-deploy-my-new-pod -n workload 可以观察到相应的错误消息。 现有 Pod 将继续工作,尽管将观察到相同的错误消息。 定期更新检查机密的结果会生成错误消息。 尽管未经测试,但在 Key Vault 不可访问的情况下执行部署不起作用。 管道运行中的 Terraform 和 Azure CLI 任务向 Key Vault 发出请求。
    事件中心 在阻止对事件中心的访问时,由CatalogServiceHealthService发送的新消息会失败。 BackgroundProcess 检索消息将缓慢失败,几分钟内完全失败。
    Azure Cosmos DB 删除虚拟网络的现有防火墙策略会导致运行状况服务开始失败,且延迟最少。 此过程仅模拟特定情况,即整个 Azure Cosmos DB 中断。 大多数在区域级别发生的故障情况应通过客户端的透明故障转移自动缓解到其他 Azure Cosmos DB 区域。 前面所述的基于 DNS 的故障注入测试是对 Azure Cosmos DB 的更有意义的测试。
    容器注册表 (ACR) 阻止对 ACR 的访问后,在 AKS 节点上拉取和缓存的新 Pod 将继续工作。 由于 K8s 部署标志 pullPolicy=IfNotPresent,创建仍然有效。 如果节点没有在块之前拉取和缓存映像,则节点无法生成新 Pod 且立即失败且出现 ErrImagePull 错误。 kubectl describe pod 显示相应的 403 Forbidden 消息。
    AKS 流入量负载均衡器 将 AKS 托管的网络安全组 (NSG) 中HTTP(S)(端口 80 和 443)的入站规则修改为 Deny 会导致用户或者运行状况探测流量无法到达群集。 此故障的测试很难找出根本原因,将其模拟为 Front Door 的网络路径与区域标记之间的阻塞。 Front Door 立即检测到此故障,并取消标记的旋转。