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

是的,在生产环境中测试是有风险的,但我们仍然应该这样做,而不是在罕见或特殊情况下才这样做。
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% 的自动化单元测试覆盖率,单元测试与它们验证的代码更改位于同一更改集或拉取请求中。在进入生产环境之前,您应该完成多层测试:功能/行为测试、集成测试、部署/配置测试、可访问性测试、安全测试和高可用性故障转移测试。如果您正在逐步推出新功能,也要测试推出过程。是的,我也相信手动测试,但绝不能替代自动化测试!

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

此外,不要手动重新配置您的生产系统,无论是出于测试目的还是任何其他原因。手动更改会使您的系统处于未知状态,并且可能很难将它们恢复到已知配置。使用基础设施即代码(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 条评论

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

很棒的文章,对于扩展 DevOps 来说非常重要,我们正在将这篇文章用作我们在 DevOps Victoria Canada Meetup 上的一个部分,非常感谢 Ann Marie!我将努力获得一些反馈!

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