无缝部署并非完全没有成本,但一些技术在增加少量复杂性的同时带来了很多好处。
译自 5 Deployment Strategies: The Pros and Cons,作者 Steve Fenton。
在将应用程序和服务部署到生产环境时,您希望最大程度地减少停机时间并提供无缝的用户体验。关闭应用程序以执行升级的日子早已一去不复返,而零停机时间部署现在已成为许多行业的标配。
您无法完全免费获得无缝部署。每种策略都要求您处理版本之间的兼容性。但是,某些技术带来了很多好处,而复杂性几乎没有增加。
为了在没有维护窗口的情况下管理更新,有许多部署策略可用。让我们看看最常见的策略,了解其权衡取舍:
- 重新创建
- 蓝/绿
- 金丝雀
- 滚动
- 影子
重新创建策略关闭正在运行的应用程序,部署新版本,然后向用户提供新版本。这意味着用户在部署期间无法使用该应用程序。
由于此策略最易于实施,因此它通常是应用程序的默认部署策略。减少重新创建部署停机时间的唯一机制是尽可能快地进行部署操作。
- 部署前:版本 1 正在运行并接受所有流量。
- 部署期间:版本 1 已停止,并且在部署新版本时不接受流量。
- 部署后:版本 2 正在运行并接受所有流量。
用于部署的重新创建策略非常简单。您不必管理同时运行的多个应用程序版本,在部署后,您可以预期所有用户都在运行同一个应用程序版本。
当您使用重新创建策略时,用户穿越版本边界进行交互的情况较少。所有正在运行的实例具有相同的应用程序版本。
在某些情况下,用户仍可能穿越版本边界进行交互。如果他们在版本 1 中打开了一个表单并在部署后提交了表单,如果应用程序无法接受先前版本的提交,则请求可能会失败。如果您有一个运行后台请求的前端应用程序,用户有可能在前端从版本 1 向您新部署的版本 2 后端发出请求。
重新创建策略的主要缺点是停机。应用程序不可用,因此在部署期间提出的请求将导致错误。您的服务级别目标 (SLO) 可能考虑部署窗口,在这种情况下,只要您可以在不人为限制部署频率的情况下实现目标,就不需要更复杂的策略。
重新创建策略还意味着所有用户都会遇到新应用程序版本中引入的问题。如果检测到问题,则必须重新部署先前的应用程序版本,从而导致进一步的停机。
渐进式部署策略可以最大程度地减少与部署相关的停机时间。渐进式交付允许您逐步部署应用程序,最大程度地减少停机时间,并在需要时提供简单的回滚。让我们看看渐进式交付最常见的选项。
使用蓝/绿部署,新版本在不接收流量的情况下部署。在部署完成后,负载均衡器将更新为将流量发送到新应用程序版本。
- 部署前:蓝色环境正在运行版本 1 并接受所有流量,而绿色环境未安装任何版本。
- 部署期间(第 1 阶段):版本 2 部署到绿色环境,而蓝色环境继续使用版本 1 处理流量。
- 部署期间(第 2 阶段):流量从蓝色环境切换到绿色环境。蓝色环境没有流量,但正在运行并且可用,如果需要回滚到版本 1。
- 部署后:绿色环境正在运行版本 2 并接受所有流量,蓝色环境已逐步淘汰。
在应用程序新版本部署期间,流量继续流向应用程序。这意味着部署没有停机时间。如果你检测到新应用程序版本的问题,你可以同样轻松地将流量切换回前一个版本。
两个应用程序版本之间的请求可能更多地重叠,因此需要将应用程序设计为能够优雅地应对这种情况。如果您想实现无缝回滚,那么必须考虑兼容性。
由于两个应用程序版本同时运行,因此您需要足够的资源来运行这两个工作负载。不平衡的工作负载消耗的资源不会像生产工作负载一样多,但仍然会消耗一些资源。一旦您满意新版本运行成功,那么便可以取消不平衡资源的配置。或者,您可以让它们保持可用状态以便快速回滚。
使用滚动部署,每个应用程序实例都会被新版本替换,直到所有实例都运行应用程序的新版本。这允许进行零停机部署,而无需与蓝/绿部署相同的资源要求。
- 部署前:所有实例都具有应用程序的版本 1。
- 部署期间:一次一个,每个实例都会停止并替换为新应用程序版本的一个实例。
- 部署后:所有实例都具有应用程序的版本 2。
滚动部署所需的资源少于蓝/绿部署,但仍提供零停机部署。
如果您发现新版本存在问题,您必须重新部署上一个版本以解决该问题。这会比蓝/绿部署花费更长时间,因为在蓝/绿部署中,您只需更新负载均衡器以将流量发送到上一个版本即可。
您还需要有足够的容量来处理移除一个实例后的请求,这可能会限制您在高峰时期进行部署的能力。为了避免此问题,您可以使用激增升级,该升级会在移除每个旧实例之前添加一个新实例。
通过滚动部署,应用程序的两个版本将在整个部署过程中同时运行。这意味着您必须设计应用程序以处理同时运行的两个版本,包括两个版本与同一数据库通信等问题。
金丝雀策略不会一次性向所有用户展示新应用程序,而是向少数用户展示新版本。您可以在向更多用户发送新版本之前验证应用程序的稳定性。您可以将此方法用作部署和测试策略。
- 部署前:所有用户都被路由到应用程序的版本 1。
- 部署期间:一小部分用户被路由到新应用程序版本。如果成功,您可以增加使用新版本的用户比例。
- 部署后:所有用户都被路由到新应用程序版本。
金丝雀部署降低了部署风险,因为只有部分用户会被路由到新的应用程序版本。您可以根据金丝雀样本对应用程序性能和功能稳定性进行测试。
金丝雀部署比其他策略更复杂。您需要在负载均衡器上使用更高级的路由,以确保用户不会在每次请求时在应用程序版本之间切换。但是,这也使您能够进行 A/B 测试更改,因为您可以根据请求标头或用户属性(如位置)设置路由规则。
虽然负载均衡器将每个用户固定到一个版本,但您需要确保数据存储等组件与应用程序的两个版本兼容。
您可能需要额外的容量,因为流量量可能无法反映分配给每个应用程序版本的用户的比例。例如,您可能会将一组用户路由到新版本,但发现他们是系统中最密集的用户。这可能导致资源不足以处理金丝雀组。
虽然金丝雀部署可以帮助您减少新应用程序版本引入的任何问题的的影响,但这仅在您及早发现问题时才有效。如果您发现问题太晚,您可能已经将所有用户路由到新版本。
在无法使用真实流量样本测试新应用程序版本的情况下,您可以使用影子部署策略。此方法在隔离的环境中重放真实请求。
如果操作正确,影子部署对生产系统没有影响。在新版本中发现的任何问题对真实用户没有任何影响。
您可以将生产请求的响应时间与影子环境中的响应时间进行比较,这意味着生产环境和影子环境之间的性能、错误和结果的最准确比较。
您必须确定重复请求在隔离的环境中不会产生副作用。例如,如果您的应用程序向用户发送电子邮件或其他通知,您必须确保在影子环境中关闭这些通知。您还需要确保影子环境不会向可能导致副作用的外部服务发出调用。
由于请求是从运行先前应用程序版本的生产环境重播的,因此如果影子环境对这些请求做出重大更改,它们将失败。
通过引入影子部署,您将使您在生产中必须完成的工作量增加一倍。真正的生产环境和影子环境都需要处理实际工作负载。
对于您现有的应用程序,引入影子部署的风险可能大于使用金丝雀部署针对新版本运行少量用户。
当需要将新软件版本推广到生产环境时,您仍然需要使用其他部署策略之一,因为影子部署是一种仅用于测试的策略。
在选择部署策略时需要考虑一些事项:
- 您是否可以通过当前方法实现所需的部署频率?
- 停机时间是否可以接受?
- 您可以在基础设施上花费多少资金来减少停机时间?
- 您的系统支持哪些模式,您是否可以对其进行重新架构?
- 您需要多快重新部署一个版本?
策略 | 零停机时间 | 轻松回滚 | 预飞行测试 | 成本 |
---|---|---|---|---|
重新创建 | 否 | 否 | 否 | 无额外资源 |
蓝/绿 | 是 | 是 | 否 | 部署期间必须同时运行两个环境,但不是全时运行 |
滚动 | 是 | 否 | 否 | 需要一些额外资源 |
金丝雀 | 是 | 是 | 是 | 无额外资源 |
影子 | 不适用 | 不适用 | 是 | 在整个测试过程中需要并行环境 |
重新创建部署策略对于现代应用程序来说很少足够,但值得仔细检查您是否需要更复杂的内容。如果您的软件在当地营业时间之外未使用,您可以安排在非营业时间部署并避免任何复杂性。
然而,在大多数情况下,您需要消除停机时间。持续交付和 DevOps 意味着我们正在转向更频繁的部署,这会将停机时间的影响倍增到难以实现 SLO 的程度。
如果资源成本可以接受,蓝/绿部署以最小的复杂性提供了最大的好处。在需要控制成本的情况下,滚动部署以低成本消除了停机时间,尽管您没有蓝/绿部署的回滚优势。
金丝雀部署和 A/B 部署(带有更具体路由规则的金丝雀部署)允许您使用真实流量测试新软件版本,这可能是发现自动化测试可能遗漏的问题的好方法。理想情况下,您将利用从金丝雀测试中学到的知识来增加将来在部署管道中检测到类似问题的可能性。
影子部署需要一个健壮的架构,以确保影子环境没有副作用。这使得很难将其改造到现有应用程序中,尽管某些组件可能离此要求不远。这是一个具有许多绊脚石的高级策略,因此如果您无法从这种方法中获得大量有价值的见解,最好避免它。
现代基础设施和 CD 工具可以帮助您实施这些部署策略,而无需从头开始发明它们。