你当前正在访问 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 DevOps Services?

管道流程图。

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

部署:零停机更新

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

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

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

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

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

  • 一个一致的过程 - 如果基础结构和应用程序更新有意或无意地混合发布,则错误会更少。

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

  • 更轻松地部署和调试应用程序 - 整个标记永远不会并行托管应用程序的多个版本。

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

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

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

分支策略

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

分支 说明
feature/*fix/* 任何更改的入口点。 这些分支由开发人员创建,应提供描述性名称,例如 feature/catalog-updatefix/worker-timeout-bug。 准备合并更改时,将创建针对 main 分支的拉取请求 (PR)。 每个 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 (pre-prod) 环境。 环境 staging 用于部署和验证 release 分支,更新过程与 prod(蓝/绿部署)一样。

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

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

部署:共享和专用资源

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

发布单位

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

全局共享资源

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

Front Door

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

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

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

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

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

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

    2. API 的源组,该组托管在 AKS 上。 如果存在具有不同 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 中删除,请检查:

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

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

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

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

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

  • 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 加载 Locust 是一款采用 Python 编写的开源负载测试工具。
Playwright UI 和烟雾 Playwright 是一款开源 Node.js 库,可通过单个 API 实现 Chromium、Firefox 和 WebKit 的自动化。 Playwright 测试定义也可以独立于引用实现使用。
Azure Chaos Studio 故障注入 参考实现使用 Azure Chaos Studio 作为 E2E 验证管道中的可选步骤,以注入故障进行复原验证。

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

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

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

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

自动

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

手动

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

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

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

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

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

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

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

    服务 结果
    密钥保管库 阻止访问密钥保管库时,最直接的影响是新 Pod 无法生成。 在 Pod 启动时提取机密的密钥保管库 CSI 驱动程序无法执行其任务并阻止 Pod 启动。 通过 kubectl describe po CatalogService-deploy-my-new-pod -n workload 可以观察到相应的错误消息。 现有 Pod 将继续工作,尽管将观察到相同的错误消息。 错误消息由定期更新检查机密的结果生成。 尽管未经测试,但假定执行部署在无法访问密钥保管库时不起作用。 管道运行中的 Terraform 和 Azure CLI 任务向密钥保管库发出请求。
    事件中心 当阻止访问 Azure 事件中心时,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 立即检测到此故障,并取消标记的旋转。