不要在生产环境中测试?在生产环境中测试!

是的,在生产环境中测试是有风险的,但我们仍然应该这样做,而且不应仅在罕见或特殊情况下才这样做。
222 位读者喜欢这篇文章。
Programming at a browser, orange hands

opensource.com

如果您上次更新 IT 安全标准是在五年或更久之前,那么它们很可能与当今 DevOps 和站点可靠性工程 (SRE) 实践不符。一个特别棘手的话题是在生产环境中进行测试,以及因此使用生产数据进行测试,因为 DevOps 和 SRE 模糊了生产环境与非生产环境之间的界限;什么是测试,什么不是测试。

为了澄清一些困惑,我们将深入探讨以下问题

  • 为什么我们要分离开发/测试和生产系统?
  • 我们应该根据生产系统的高标准管理什么?
  • 为什么在生产系统上进行测试如此危险?
  • 为什么我们应该在生产环境中测试?
  • 生产数据呢?
  • 我们如何才能降低在生产环境中测试的风险?

我应该注意到这是一篇观点文章;它基于多年的 DevOps 和测试集体经验,但不应将其解读为 IBM 的官方声明。

为什么我们要分离开发/测试和生产系统?

至少从合规性和风险管理的角度来看,区别对待开发、测试和生产系统是标准做法,主要是因为它们具有不同的安全性、数据和隐私控制。让我们退后一步,思考一下对这些部署环境采取不同态度的历史原因。

我们的生产系统是最重要的,因为它们运行着我们的业务和政府。这些系统为我们的客户服务,并直接影响客户满意度。开发人员的工作环境偶尔“崩溃”几个小时是正常的,但我们必须按照无可挑剔的质量、可靠性和可用性标准来管理生产系统。这就是为什么限制生产系统的风险至关重要。DevOps 和 SRE 仍然专注于规避风险,但与其他实践(如 ITIL)相比,它们使用不同的降低风险策略。

此外,生产系统很特殊,因为它们可以访问生产数据。生产数据必须是可靠的真理来源,因此我们必须保护它免受损坏。生产数据也可能包含我们只能与授权用户共享的信息,例如机密或个人数据,因此我们必须确保它受到生产级身份验证和授权的保护。最后,我们可能需要维护生产数据访问的审计跟踪(创建、读取、更新和删除),这对于开发/测试系统来说是不需要的。

image of a lock on data

生产系统受到更严格的控制和监控,这是有充分理由的。

我们还需要对生产系统的当前状态具有出色的可见性和控制力。我们仔细监控它们,以便我们可以快速检测问题,并且当问题发生时,了解这些系统的当前配置可以更容易地快速恢复。大多数人可能不在乎开发人员是否更改了他们个人笔记本电脑上的配置设置,但我们将生产系统锁定为已知配置,并实施了安全的变更控制。无论我们是通过变更控制数据库还是基础设施即代码来锁定配置,目标都是相同的:可见性和控制。

最后,请记住,我们以不同的方式管理开发/测试和生产系统,因为存在专门针对生产系统的合规性规则和法规。没有什么比对我们的开发/测试环境施加不必要的负担更能扼杀速度了!

我们应该根据生产系统的高标准管理什么?

当我们开始思考在生产环境中进行测试时,我们很快意识到我们是从一个假设开始的:应该很容易确定什么是生产环境,什么不是生产环境。但是,正如大多数假设一样,我们错了。开发人员和测试人员希望快速行动;当有疑问时,我们倾向于将系统归类为开发/测试而不是生产,这样我们就无需处理生产系统管理开销。但是,我们如何知道何时需要实施生产控制?这并非完全黑白分明,但有几个考虑因素。

一些更明确的例子:我们可以同意,开发人员的笔记本电脑和专门为测试设计的环境(例如,集成测试、系统测试、性能测试)不是生产系统。此外,人们普遍认为,直接或在幕后为真实客户提供服务并使用真实数据的系统是生产系统。还有一些我们仅在内部使用的系统,它们对于公司运营至关重要,因此也被认为是生产系统。

Image of a computer on a desk

现代软件开发和交付实践可能会模糊开发、测试和生产系统之间的界限。

但是,通常“生产”和“非生产”之间的界限取决于您的独特情况以及您对这些术语的使用

  • 暂存
  • 预生产
  • 预上线
  • 预览

例如,您的暂存环境可能只是您针对其运行测试的环境,在这种情况下,它更像是一个测试系统。另一方面,您的暂存环境可能是您的业务合作伙伴在您发布新 API 之前用于测试新 API 的环境。在这种情况下,您应该像管理生产系统一样管理它,在大多数意图和目的上都是如此,因为您希望它模拟这些 API 的真实用户体验。也许您可以容忍该类型服务器的更多停机时间,但您应该使用生产质量的身份验证和授权;您应该对服务器配置进行控制,并且您应该像生产系统一样监控服务器。

内容管理系统的预览环境是另一种听起来像一种类型但实际上是另一种类型的系统示例。预览内容尚未发布。也许它也对时间敏感,例如未发布产品的网站。有人会在公告发布后向全世界发布新产品的网页;但在发布之前,它们是高度机密的。因此,预览环境必须具有比生产环境更严格的身份验证和授权控制。除非当前用户有权查看预览页面,否则它不得呈现预览页面。

我们也应该像对待生产系统一样对待这些系统

  • 蓝绿部署。为什么?未接收流量的备份环境可能随时成为生产环境。
  • 高可用性配置中的备份服务器。为什么?备份服务器可能随时开始服务生产流量。
  • 金丝雀部署。为什么?这些服务器服务一小部分生产流量。
  • 分阶段发布。为什么?服务生产流量的所有硬件和软件版本都“在生产中”。
  • A/B 测试服务器。为什么?即使名称中包含“测试”,这些服务器也服务于生产流量。

当您将规则和启发式方法应用于您的系统和环境时,保持一致性非常重要。您不应将暂存环境一天视为生产系统,第二天又视为测试系统。那是灾难的根源。确保每个人都了解哪些系统是生产系统,哪些不是,然后记录您团队的决策和任何例外情况。

努力了解哪些系统是生产系统,哪些不是,并适当地对待它们,将确保您在不损害开发和测试速度的情况下保护您的生产系统。

为什么在生产系统上进行测试如此危险?

当人们说“不要在生产环境中测试”时,是因为他们想避免几种可能的(不良)结果

  • 损坏或无效的数据
  • 泄露受保护的数据
  • 不正确的收入确认(取消订单等)
  • 系统过载
  • 对其他生产系统产生意外的副作用或影响
  • 高错误率,触发警报并呼叫值班人员
  • 倾斜的分析(流量漏斗、A/B 测试结果等)
  • 充满脚本和机器人活动的日志不准确
  • 不符合标准

为什么我们仍然应该继续在生产环境中测试?

是的,在生产环境中测试是有风险的,但我们仍然应该这样做,而且不应仅在罕见或特殊情况下才这样做。这些生产环境中的测试已被 DevOps 和 SRE 社区接受为最佳实践

  • A/B 测试和实验
  • 可用性测试和用户体验研究
  • 蓝绿部署的最终冒烟测试
  • 功能标志
  • 分阶段发布
  • 金丝雀测试
  • 健康检查和其他生产系统监控,包括脚本化健康测试
  • 网页的可视化回归测试,以比较暂存版本与生产版本
  • 可访问性回归测试(在初始测试和部署之后)
  • 扫描网页以查找断开链接并报告错误的脚本
  • 真实用户监控
  • 混沌工程
  • 故障转移测试
  • 高可用性/灾难恢复计划的其他测试
  • 漏洞赏金计划

生产测试帮助我们

  • 防止糟糕的部署破坏生产系统
  • 客观地识别哪些用户体验更有效
  • 设计更令人愉悦的用户/网站互动
  • 逐步推出新功能
  • 快速获得有关我们最新更改成功或失败的反馈
  • 在用户注意到问题之前发现问题
  • 了解网页性能特征和变更影响
  • 构建更具弹性的系统
  • 提高系统质量

通过在部署时或按计划频率运行多种类型的生产测试,我们可以涵盖各种关键的非功能性需求

  用户体验 可用性 发布变更 反馈 质量 性能 弹性
A/B 测试          
可用性/用户体验        
冒烟测试      
功能标志        
分阶段发布        
金丝雀测试      
健康检查        
回归测试          
断链检查器          
真实用户监控        
混沌工程      
故障转移测试        
高可用性/灾难恢复测试        
漏洞赏金        
渗透测试        

各种类型生产测试的目标

…以及一个异常值(因为难道总会有一个问题儿童吗?):第三方渗透(“笔”)测试。我们应该在生产系统上进行吗?一方面,它无疑是危险的;例如,如果渗透测试人员发现注入漏洞,您最终可能会损坏数据库中的数据。另一方面,黑客可能每周都在您的面向互联网的系统上运行渗透测试套件。因此,渗透测试正在您的许多生产系统上进行,无论您是否批准。这就是为什么我将其包含在此生产测试列表中的原因。我有两个建议

  • 确保您雇用的渗透测试人员正在使用类似生产环境的环境,而不是玩具环境。
  • 在其他人对您的生产系统运行相同的测试之前,针对您的测试系统运行最流行的安全测试套件,并修复您发现的任何错误。

A hacker

您的生产系统需要能够抵抗黑客攻击并优雅地处理它们。

最后,您是否注意到这些生产环境中的测试有一些共同点?它们都没有制作生产数据的“测试副本”。它们都直接在真实的生产系统和数据上运行。

生产数据呢?

这里有一个捷径:开发/测试环境可能不需要特殊的测试数据。它们通常可以使用任何人都可以访问的生产数据,例如实际的网页内容,只要您的测试不会修改该数据,从而节省您创建测试数据的时间和费用。上一节中的所有生产测试都属于此类,许多 Web 服务和 API 也是如此。

但要注意!仅仅因为数据可以在互联网上获得或 REST API 可以免费使用,并不意味着您可以将其用于您的开发/测试目的。在您获取和使用开放数据之前,请确保您理解并遵守任何适用的许可协议和网站使用协议。

如果您可以通过使用生产数据来节省时间和金钱,那就太好了,但是您的一些应用程序和服务需要修改您的数据存储,因此您将需要也修改数据的测试。在生产环境中运行这些测试很难在不损坏生产系统的情况下完成。面对这种现实,当为了验证测试场景而必须修改数据存储时,大多数开发团队选择拥有不同的数据源:一个用于开发/测试,一个用于生产。但是,您如何设置足够真实和完整的测试数据以进行良好的测试呢?

如果您的生产数据库足够小,您可以在技术上制作一个副本,然后对其进行测试,但是将生产数据复制到开发/测试环境是有问题的,因为它可能会绕过安全和隐私控制。(GDPR,有人吗?)

让我们举一个例子。您已经实施了您精心设计的安全和隐私控制。您设置了生产系统,以便只有“需要知道”的人员才能访问任何个人数据;您知道您的数据存储在哪里;您已经建立了一个按需从您的系统中删除个人数据的流程;等等。也许您的数据库中有客户地址和电话号码。如果有人将数据库复制到开发/测试系统,而您没有在那里实施您的安全和隐私控制,那么您的系统中就存在漏洞。如果客户行使他们的“删除权”并请求您删除他们的地址和电话号码,您如何知道需要更新哪些开发/测试系统以删除该信息?如果开发人员的笔记本电脑或装有个人数据的测试移动设备被盗怎么办?您是否需要报告并减轻安全漏洞?为了弥补这些漏洞,您需要要么将个人数据排除在您的开发/测试系统之外,要么将有权访问个人数据的开发/测试系统纳入您的生产数据合规范围。

A padlocked laptop and smartphone

用链条锁住您的笔记本电脑和手机不是最佳方案。假设这些设备最终会被盗,并决定如何相应地管理它们。

显而易见的替代方案是为开发/测试环境使用模拟数据,但是决定何时使用模拟数据进行测试是很困难的,因为创建和维护模拟数据既耗时又容易出错。如果您从生产数据库开始并手动擦除它以模糊或删除敏感数据,您可能会遗漏某些内容。如果您擦除得太远,您可能会损坏数据或限制其测试用途。相反,如果您从头开始构建测试数据库,则很难创建良好的测试套件所需的所有排列和边缘情况。

只有您和您的团队成员才能决定哪个方向适合您的独特目的,但以下是一些有帮助的考虑因素

  • 在使用生产数据之前,请了解您的生产数据上有什么控制措施,并尊重这些控制措施。
  • 确保您的整个团队就敏感数据个人数据的含义达成一致。
  • 定义并获得对处理敏感和个人数据的协议的接受。
  • 记录并理解您系统中的敏感和个人数据。确保您的开发人员和测试人员确切了解他们使用的敏感和个人数据。
  • 如果您决定对生产数据进行清理以删除个人或敏感信息,请确保清理数据的过程本身不是安全/隐私/合规性漏洞。考虑使用第三方清理和消毒软件,因为它比自行开发的解决方案更不容易出错。

我们如何才能降低在生产环境中测试的风险?

“不要在生产环境中测试”这句格言的目的是保护我们的生产系统。既然我们已经确定我们可以而且应该每天在生产环境中进行测试,那么我们如何才能确保生产系统的安全?

A checklist

在将新组件投入生产之前,制定测试计划并完成它。经过充分测试的代码不太可能在生产环境中失败。

首先,也是最重要的,在进入生产环境之前,使用自动化测试彻底测试所有系统。我坚信 100% 的自动化单元测试覆盖率,单元测试与它们验证的代码更改在同一个更改集或拉取请求中。在进入生产环境之前,您应该完成多层测试:功能/行为测试、集成测试、部署/配置测试、可访问性测试、安全测试和高可用性故障转移测试。如果您正在逐步推出新功能,也要测试推出过程。是的,我也相信手动测试,但绝不能作为自动化测试的替代品!

那么在生产环境中进行自由形式的测试呢?两个词:要小心。“Bug hunt”日,例如,这是一个最佳实践,您要求团队中的每个人花一定的时间尝试查找您软件中的错误。这些活动既有趣又富有成效……只要您设置了适当的护栏。与您的团队一起审查在生产环境中进行测试的风险,并教导您的错误猎手他们不应该做什么,例如使用他们的个人信用卡下订单并立即取消订单。这些类型的测试会干扰收入确认和订单统计。

此外,不要手动重新配置您的生产系统,无论是出于测试目的还是任何其他原因。手动更改会将您的系统置于未知状态,并且可能很难将它们恢复到已知配置。使用基础设施即代码(Chef、Helm 等)和/或发布管理和编排工具(如 IBM UrbanCode Deploy 或 Kubernetes)管理您的生产系统配置。

在进行任何混沌工程之前,请确保您已按照 混沌工程 的基本原则规划了您的实验

  1. 计划一个实验
  2. 控制爆炸半径
  3. 扩大或缩小规模

您还可以通过满足以下先决条件来降低混沌工程的风险:可靠的自动化测试覆盖率、良好的监控和警报、具有快速自动化故障转移的高可用性设置,以及一个随时待命并在您的服务级别目标 (SLO) 内准备好恢复服务的团队(如果发生故障)。在我的团队中,我们通常在周末进行每个组件的第一次故障转移测试,并由值班开发人员在场,团队在通过第一组测试后“毕业”到在正常工作时间内测试弹性。

Falling dominoes

不要让混沌工程、可扩展性或性能测试在您的系统中引起一系列问题。松耦合的组件、良好的错误处理和计划的故障模式有助于隔离故障。

在计划可扩展性和性能测试时,请确保您不会影响您的客户。不要向您的生产系统抛出大量 API 请求并抱最好的希望。如果成本效益分析证明合理,请使用单独的隔离环境。如果您需要在生产环境中测试可扩展性或性能,请在监控您的系统的同时逐步增加流量,并在服务中断或故障之前停止。并且不要忘记从您的生产分析中过滤掉可扩展性/性能测试流量!

这些降低风险的技术将帮助您保持生产系统的弹性,并减少因在生产环境中测试而导致的故障。

结论

在生产环境中进行测试非常有价值,并且是现代软件工程、IT 运营和 IT 安全领域的最佳实践。生产测试帮助我们

  • 防止糟糕的部署破坏生产系统
  • 客观地识别哪些用户体验更有效
  • 设计更令人愉悦的用户/网站互动
  • 逐步推出新功能
  • 快速获得有关我们最新更改成功或失败的反馈
  • 在用户注意到问题之前发现问题
  • 了解网页性能特征和变更影响
  • 构建更具弹性的系统
  • 提高系统质量

因此,我们不应避免在生产环境中进行测试;相反,我们应该了解固有的风险,并在我们的系统中构建安全措施来解决这些风险。我们还应该更新我们的安全和合规性标准,以考虑现代生产测试实践。

感谢 Devopsdays Charlotte 上“在生产环境中测试”开放空间的与会者,他们共同集思广益,提炼出“测试”和“生产”这两个术语的真正含义,以及我们真正需要做些什么来保护我们的生产系统。我还要感谢 Craig Cook 和 Jocelyn Sese 对本文早期草稿提供的有益反馈。

标签
Ann Marie Fred profile photo
我是一名高级 DevOps 负责人、软件工程师、运维爱好者、前经理、客户拥护者、问题解决者和最佳实践的倡导者。

4 条评论

一个优秀的设置应该有两个相互镜像的生产系统,您可以将更改从开发/测试/QA 部署到一个镜像,如果一切正常,则将其设为默认生产环境,将另一个镜像置于“测试阶段”。

很棒的文章,对于扩展 DevOps 非常重要的一部分,我们正在我们的 DevOps Victoria Canada Meetup 中使用它,非常感谢 Ann Marie!我将努力获得一些反馈!

知识共享许可协议本作品根据知识共享署名-相同方式共享 4.0 国际许可协议获得许可。
© . All rights reserved.