持续交付与可用性

从 Amazon.com 和 Netflix 看自动化交付的重要性

Posted by 薛以致用 on December 21, 2019

前言

现实中,客户非常容易接受 DevOps (研发运营一体化)的理念,但落地实践的时候常常遇到各种挑战,很多人就认为 DevOps 只有互联网客户可以做到,比如我们经常引用的两个客户成功转型故事 Amazon.com 和 Netflix,我们首先需要认识到,我们这个时代见证的 DevOps 转型是一种服务和组织架构转型

服务和组织架构转型

对于一个企业而言,客观的业务通常存在双模业务:(1)传统业务,通常以 ITIL 为管理运营理念,追求持续稳定现有业务发展(2)创新业务,以 DevOps 为核心,强调如何推陈出新,布局新的产品和模式。因此对于一个非纯线上业务而言的企业而言,企业内部可能同时存在三种模式,传统模式,企业DevOps模式以及 DevOps 模式,如下图所示;无论哪种模式,DevOps(研发运维一体化)整个能力域涉及三块内容(1)研发管理,主要包含需求管理,产品设计,服务研发,研发团队组织管理等等(2)持续交付,包括配置管理,构建与持续集成,测试,部署和发布,环境管理,数据和度量等等(3)持续运营,包括监控,日志,容量,变更,可用性,连续性,事件管理等等。

三种模式

持续交付就意味着系统会有持续更新,那如何在自动化持续交付管道和系统可用性度量取得平衡呢?本篇我们就来看看,哪些变更对可用性的影响,以及如何在自动化管道中处理这些潜在的风险。

可用性挑战

无论是 Amazon.com 电商平台还是 Netflix 在线流媒体服务,在业务发展过程中,都遇到非常大的可用性挑战;2004年底,Amazon.com 在促销时遭遇长时间站点不可用,这也是亚马逊坚定走微服务架构和两个披萨组织转型的核心缘由;Netflix 从传统的碟片租赁转型到在线流媒体,从传统数据中心迁移到 AWS,更是遇到相当多的技术挑战,最近几年,他们的用户从 5000万增长到 1.25亿(2018年官方博客数字),除了遭遇扩展性挑战外,如何保障整体的服务高可用性对于 24小时在线业务尤其重要。

亚马逊技术团队,支撑 DevOps 工具链中首个关键工具就是 Apollo,一个十几年前就在内部推出的自动化部署引擎,无论是电商模块还是 AWS 服务都是通过 Apollo 进行自动化部署,支持不停机部署,健康检查,及回滚,保障软件的变更不会导致整个服务不可用;今天客户在 AWS 平台上看到的 CodeDeploy 就是该工具的对外版本,同时亚马逊团队还将该工具集成到了自动化流水线中(CodePipeline)。

Netflix 团队开发了 Spinnaker 作为持续交付的工具平台,很多 Netflix 对于可用性的经验都固化到了该开源工具当中,避免人为重复犯错。

1. 限制故障爆炸半径在一个 AWS 可用区/区域

对于一般客户而言,做到单区域多可用区高可用,是一个合理的高可用架构选型,当然,如果覆盖全球用户,而且避免单区域故障,在多区域多站点架构前提下,可以按业务重要性实现,跨区域的应用高可用性。

Netflix 在线流媒体服务从北美起家,目前已经支持拉美,亚太,欧洲,中东和非洲地区,从应用架构来看,他们实现了在 AWS 多个区域多活的全球架构,因此为了持续保障用户访问,就必须限制系统更改的爆炸半径,验证更新之后再推广到更多地区用户;也就是说,一次只部署到一个 AWS 区域,如果该区域发生异常故障,可以将该区域流量切换到其他可用的区域;

限制爆炸半径

2. 生产环境采用蓝绿部署

在蓝绿或红黑部署策略下,新版本将在通过健康检查后,开始接受流量;新版本正常运行后,旧版本将下线,不再接受流量;如果需要回滚,则跟上新一样简单;对于新服务,这种模型,允许团队快速采取行动,并在出现问题时,快速恢复到已知的良好状态;

蓝绿

3. 关注部署时间窗口

每当部署新版本的应用程序时,都需要牢记两件事:首先,您及您的同事是否能够观察部署的影响,并且可以根据需要进行修复? 其次,如果您的部署有问题,您是否能将爆炸半径限制在尽可能少的客户范围内?

这两个因素在部署新软件或新版本时要多加注意;在 Netflix 案例中,流媒体流量遵循相对可预测的模式,大多数人在晚上访问,无论他们居住在哪里;我们建议在工作时间和非高峰时段为所选区域选择部署时间窗口。

4. 自动化部署动作尽量不要在非工作时间执行

部署窗口也适用于自动触发的事件。 Spinnaker 允许通过 cron 表达式作为管道触发器。 这有助于减少用户手工操作,并降低心理负担;但这也可能是一个冒险的策略:很容易形成一个激进的 cron 表达式,它将在非工作时间或周末执行管道,这可能与预期不符。无论您使用什么样的自动化方式,请确保任何自动触发(例如,由 cron)的管道都可以在无人值守的情况下运行,也就是说,充分测试之后再自动化执行;

5. 集成混沌猴子(Chaos Monkey)

由 Netflix 构建和开源,混沌工程工具套件的一部分。 混沌猴子不可预测,并自动终止生产中的单个实例。这可以作为服务的一种强制功能,以确保设计服务的方式能够抵御单实例故障。如果不是这样,混沌猴子会暴露这个问题,以便服务所有者可以在它变成广泛面向客户的事件之前修复它。在 Netflix,我们的最佳实践是,所有生产中的服务都应启用混沌猴子,这些服务的所有者应检测到混沌猴子终止应用程序实例的问题,并在架构和应用程序侧实现自愈。

混沌猴子

6. 自动化测试及金丝雀分析 - Kayenta

快速迭代的关键在于在部署新版本的软件之前对其进行自动测试验证。 理想情况下,无需任何人工干预即可运行所有必要的测试套件;

首先,金丝雀部署架构是我们进行前后版本的 A/B 测试常用方法,如下图架构,Netflix 和 Airbnb 都采用了类似的部署架构,验证和分析新旧版本的不同响应和相关关键指标;

金丝雀架构

金丝雀分析分析是通过实时流量验证服务的新更改的有效方法;Airbnb 采用了Twitter开源的 Diffy 工具,Netflix 则构建了一个开源工具 Kayenta,来实现自动化的金丝雀分析任务;Kayenta 很容易集成到 Spinnaker 中;结合手动判断,Kayenta 是上生产之前的最后一个控制点。

金丝雀分析

7. 适当的人工干预

在尽可能的情况下实现自动化,但在适当的地方使用人工干预。 例如,在将新版本推向生产之前,检查和分析金丝雀结果场景,引入人工判断是必要的。

8. 一致的版本

现在,您已经对新版本进行了大量测试和验证,强烈建议您部署到生产环境和经过测试的版本完全一致。 在 Amazon EC2 为基本部署单元的时候是 Amazon AMI 镜像,在容器环境下是一致的 Docker Image,这意味着我们更喜欢从测试环境中重用经过验证的应用及其环境,而不是在生产中重新构建。

9. 定期检查紧急联系人清单

有时,保障应用程序的可用性做的最好很简单,但并不总是如此。当您的应用出现问题时,最重要的是,及时找到能够解决问题的人员。 因此,请检查您的紧急呼叫设置,并定期检查。这将有助于确保在发生事件时迅速召集到合适的人。

在 Netflix 内部,Spinnaker 有一个方便的呼叫“应用所有者”按钮,因此,此信息是最新的,这一点尤其重要,这样我们就不会对能够联系到应用程序所有者,有错误的安全感,但随后发现 我们最需要的联系人信息已经过时了。

10. 掌控快速回滚的方法

现实中,即使进行了可靠性测试,功能测试和其他验证,有时也会在生产中部署某些会引起问题的服务。 也许这是种族条件暴露的罕见错误,只能大规模访问时才能触发。 无论是哪种情况,重要的是要知道在需要时如何快速回滚到众所周知的健康状态。

在 Spinnaker 中,如果您的新版本应用出现生产问题,则可以通过“服务器组”菜单下的“回滚”操作进行回滚。 回滚将启用您选择的弹性工作组 ASG(通常是前一个)并禁用有故障的弹性工作组 ASG; Spinnaker 还支持创建回滚管道,回滚管道可以在管道发生故障时执行,甚至可以手动触发。

11. 实例运行不正常时使部署失败

多年以来,当部署成功并启动实例时,有几次我们陷入了糟糕的状态,但是实例并不健康,实际上无法适当处理流量。 “成功”的部署给我们带来了一种错误的安全感,当关键服务实际上并不健康时,这种安全感便迅速消失,并且请求迅速堆积并失败,有时会引起重试风暴和各种破坏。从这些经验中,我们学习到在实例启动但不正常的情况下使部署失败的重要性。

Spinnaker 具有用于识别实例运行状况的灵活方式。当实例不正常时,Spinnaker会相应地记录下来;而且,运行不正常的实例将不会收到流量。如果弹性工作组 ASG 中的所有实例都不正常,则 Spinnaker 将使部署失败。为了方便操作,Spinnaker 还清楚地将实例状态标记为准备启动,启动中,等待发现,不健康以及健康状态用不同颜色进行标注,如下所示。

12. 通知部署成功事件

建议让团队知道部署已成功投入生产;这对我们成功运营至关重要。我们的最佳实践是在部署更改时始终监视您的系统。当出现问题时,重要的是要知道发生了什么变化以及何时发生了变化。 因此,对于自动化部署而言,通知团队以使他们知道保持服务健康非常重要。 Netflix 内部使用 Slack 渠道进行通知;在 Spinnaker 中,管道可以集成在完成后通知相关人员想要通知的任何通道。

13. 哪怕是一次性工作,也要自动化执行

每个工程师都为非常见情形编写了一次性的脚本程序。而且很多情况下,这些“一次性”情况再次发生,现在团队中的其他成员都不知道一位工程师在脚本中打算执行一次然后被扔掉的行为!管道是自动化任何一系列步骤的有效手段,即使不是每天执行的那些步骤。 一个示例是构建用于紧急推送的管道,其中提供参数以控制条件执行(例如跳过部署窗口)。不要忘记在非紧急情况下定期测试您的非典型(和典型)部署管道!

14. 使用先决条件验证预期状态

我们每个人都在一个系统不断变化的环境中运作。 在 Netflix,有数百种微服务会不断更新。 对其他系统的状态进行假设可能很危险;从错误中吸取教训,我们现在使用前提条件来确保在部署新代码或进行其他更改时这些假设仍然有效。 对于长时间执行的管道(可能是由于手动判断和/或部署窗口的延迟)而言,这尤其重要。 使用前提条件阶段可以在潜在破坏性操作之前验证预期状态。

总结

任何企业都可以落地 DevOps

如下图所示,国内信通院和开源社区以及很多业界知名企业一起通过 DevOps (研发运营一体化)标准来指导企业落地最佳实践,该指南每年都会动态更新,作为社区驱动及行业化最佳实践不断演进,本文结合海外成功客户案例,在保障可用性的基础上,如何更好的落地自动化持续交付管道的最佳实践。

企业DevOps实践不同维度

从转型成功的企业学习最佳实践

服务可用性是很多客户的在线业务持续追求的目标,无论是 Amazon.com 电商平台还是 Netflix 流媒体服务,虽然所在行业不一样但类似的都追求自动化持续交付流水线,并将测试,混沌,金丝雀分析等最佳实践集成到流水线,在必要的情况下引入人工干预机制;亚马逊通过 AWS 云平台提供客户和亚马逊内部团队一个无人值守的高效自服务平台,而 Netflix 全部托管在 AWS 的基础之上,跟进自身业务特性,不断创新研发符合自身组织和业务的各种工具。

在我们构建自身的自动化流水线时,不妨参考如上客户在生产实践的经验总结,勤动手实践!


公众号二维码

诞生于 2019,遇见 2020。

感谢关注,欢迎动动手指标星和置顶;

这样就不会错过少但精彩的技术探讨、团队建设、案例分享!

每周至少一更,转发是对我的最大鼓励!

学习之路漫漫,走走停停,
偶有所感,随心所记,
言由心声,问心无愧!

从客户中来,到客户中去!