原文地址:
https://medium.com/@jeehad.jebeile/devops-and-segregation-of-duties-9c1a1bea022e
原文作者:Jeehad Jebeile
翻译君:CODING 戴维奥普斯
在国内不少的研发组织依然通过职责分离的方式来管理研发团队,这种情况下就会造成团队之间合作效率低下、责任互相推诿等问题。我们翻译了以下这篇文章来与读者们一起探讨 DevOps 与职责分离究竟该如何结合在一起,从而更好地提高研发团队的效率。
引言
如何把 DevOps 与职责分离完美地融合在一起?
DevOps 和职责分离(SoD:Segregation of Duties)通常不会相提并论。DevOps 旨在消除障碍并最大限度地减少交接,而职责分离则是通过增加隔离以最大限度地降低风险。
在受到高度监管的行业(如金融、医疗保健)工作时,采用 DevOps 工作方式来运作团队可能非常具有挑战性。这是因为监管机构希望只有经过请求、批准以及充分测试的变更才能进入生产环境。在这些情况下,主要的控制方式实际上是职责分离。
职责分离
什么是职责分离?
职责分离(SoD)是不止一人来完成任务的概念。在商业中,通过在一个任务中通过多个人来实现分离是一种旨在防止欺诈和错误的内部控制方式。
—— 维基百科
在软件工程领域,这基本上意味着开发代码的人或团队无法批准他人或者自己部署代码。 这是为了防止意外或恶意将未经授权的代码发布到生产环境中。
相比之下,DevOps 是将开发和运维两个分离的功能合二为一。一个团队同时可以开发和测试代码,还支持部署代码。隔离,意味着将人或者事物从主体中剥离出来,这仍然是目前常见的控制生产环境的方法之一。
在 DevOps 团队中实行职责分离的缺点是什么?
- SoD 会通过添加不必要的切换来降低团队速度,并且可能会引入错误。每次发生切换时,都需要进行信息传递,这不仅会降低速度,还可能会导致信息传递有误。交接不仅会影响变更的部署,还会影响生产环境中紧急事件的处理。在这种情况下,处理事情的责任人最好是能更好地响应事件而不是负责变更的人(或团队)。
- 职责分离表明对团队缺乏信任,这助长了“恐惧”文化的培养。DevOps 团队需要自主,以获得这个理念所宣扬的全部价值和速度优势。为了实现这种自主权,团队需要始终被信任他们正在做正确的事情。在他们做错事的时候,依然会被要求负责并纠正错误。请记住,能力越大,责任就越大。
- SoD 无法解决与共同决策有关的问题。这涉及到有人(或团队)故意将未经授权的变更推向生产,无论他们是出于恶意还是出于紧急情况来企图破坏这过程。例如,他们会说:“我们没有时间进行完整的回归测试,因为我们需要明天发布,你能不能马上签名?”。无论有多少控制措施,你都无法摆脱这个问题。
如果你别无选择,只能实施 SoD 该怎么办?
正如文章开头中所提到的,有一些受到高度监管的行业不允许 DevOps 团队完全自主地工作。如果你发现自己遇到这种情况,以下是你的团队应该关注的一些事项。
最大限度地减少交接次数
DevOps 的主要原则之一是改进你的工作流,以便执行任务的效率是最高的。在 DevOps 中,重点通常是 SDLC(即 CI/CD),但其实最小化切换可以应用于团队中的大多数流程。在最开始,需要首先通过确认工作流之间的相关性来评估现有流程;随后,你可以通过简化流程来获得实现目标所需的最少步骤数。确定新的工作流后,你可以加上自动化了。但要记住, 即使自动化很重要并且通常也是一个好主意,但自动化一个糟糕或者冗余的流程是没有任何意义的。所以先确认工作流,优化它,然后自动化。
译者注:SDLC(systems development life cycle)即系统发展生命周期,也称软件生命周期,用于描述一个信息系统从规划、创建、测试到最终完成部署的全过程。
自动化
自动化你的构建、测试和部署。通过自动化交付流水线,你可以最大限度地降低人为错误导致的风险。
- 持续集成: 是一种开发实践,需要开发人员每天多次将代码集成到共享代码存储库中。然后通过自动构建和单元测试过程验证每个签入,可以让团队尽早发现问题。
- 持续交付: 是持续集成的自然延伸:团队确保对系统的每次更改都是可发布的,并且我们只需按一下按钮即可发布任何版本。持续交付旨在使发布成为一件无聊的事情,我们可以经常快速交付并且快速得到用户的反馈。
- 持续部署: 在以上环节准备好后可立即自动部署某个版本的代码,进一步扩展了持续交付。
即使最终生产环境的部署需要由另一个人或团队完成,你也可以实现持续交付,至少可以让研发组织在最快的时间内达到生产环境就绪状态。
删除外部依赖项
消除对外部团队的依赖,并尝试在团队中保留所有审批权力。拥有外部依赖关系,例如需要特定利益相关方的批准,或者让另一个单独的团队执行部署会降低流程的速度。这并不是说应该跳过或忽略这些操作,但应该能够由本团队成员完成。再次回到 DevOps 原则, 团队应该包括全栈或 T 型开发人员,他们可以出现在需要执行团队各种任务的地方。
消除这些外部关系的主要原因是,与团队之外的人员相比,与团队中的人员沟通通常更容易。另外,团队中的人员知道发生了什么以及需要做什么,无需上下文的解释。这两个好处都将会提高团队的速度。
如果您无法删除依赖关系,请查看是否可以考虑将相关人员添加到你的团队中。 例如,如果你需要公司业务利益相关方在部署之前批准你的发布,看看你是否可以让你的产品负责人(即 PO)来代表业务方执行此功能。这样的话 SoD 依然存在(因为 PO 通常不直接参与特性的开发)并且团队不再依赖于团队之外的人。
实施安全网比控制重要
维持高水平的风险规避:最大限度地减少交接并实现快速交付的最佳方法之一是实施安全网,而不是控制。这是什么意思呢?
在马戏团中,当空中飞人艺术家表演他们的杂技表演时,他们通常会通过安全网来进行防护。另一种方法是将他们连到安全带上,但这显然会限制他们的运动。另一方面,安全网允许他们尽可能流畅高效地运动,并确保如果出现问题并且碰巧掉落,他们能够安全地落入网中并避免受到严重伤害。
别误会我的意思,在时间和地点上肯定需要控制。例如,在航班起飞前进行例行检查,并且在每次起飞之前都要强制检查,因为在这种情况下我们不能承受任何重大事故,失败的结果将是毁灭性的。不仅是因为物质成本高(飞机并不便宜),更重要的是,生命是无价的。
对于构建软件的人来说,在大多数情况下,如果软件失败,人们并不会因此失去生命。因此,在这些情况下失败是允许的, 只要你可以“安全地”失败,快速恢复并从失败中吸取教训,以便不会再重复这样的失败。
在软件开发方面, 安全网包括对生产环境的质量系统监控。 这允许团队了解系统的当前状态以及在用户做出响应之前处理突发事故或者避免事故产生。在发生重大事故时,能够通过快速回滚来恢复服务,例如 蓝/绿部署是另一种可以应用的安全网。
蓝/绿部署
这种技术是一种众所周知(但利用不足)的云模式,用于最大限度地减少发布的停机时间,并在出现问题时提供快速回滚方式(即安全网)。
Martin Fowler(敏捷宣言的最初共同创造者之一)解释如下:
自动化部署的挑战之一是切换本身:将软件从测试的最后阶段带到生产环境当中。你通常需要快速执行此操作以最大限度地减少停机时间。蓝/绿部署通过确保你拥有两个尽可能相同的生产环境来实现此目的。在任何时候,其中一个,例如蓝色指的是生产环境。在准备软件的新版本时,您将在绿色环境中进行最后的测试阶段。一旦软件在绿色环境中工作,您就切换路由,以便所有传入的请求都进入绿色环境,同时蓝色环境处于空闲状态。
蓝/绿部署还为你提供了快速回滚方式,如果出现任何问题,您可以将路由切换回蓝色环境。
—— Martin Fowler - https://martinfowler.com/bliki/BlueGreenDeployment.html
这里的要点是, 不要等到软件被认为是完美的才允许发布。 在具有 kill-switch 机制下我们允许所有版本投入生产,因为在需要时我们可以快速恢复服务。所以我们强调快速恢复,而不是试图去避免(不可避免的)失败。
译者注:常见的带有故障恢复效果的部署策略还有灰度发布/金丝雀发布,通过将更改先推广到一小部分用户,然后将其推广到整个基础架构并使其可供所有人使用。以保障整体系统稳定的情况下,尽早发现、调整问题。参考:https://martinfowler.com/bliki/CanaryRelease.html
总结一下
在软件交付控制方面,职责分离应该是最后的手段。除非失败可能导致生命损失,或者监管机构强制要求,否则如果你希望获得 DevOps 原则和实践的最大好处,则应避免职责分离。话虽如此,如果你被迫在团队中使用 SoD,那么实现以下技术将允许你成功实现 DevOps ,即使不是完美地实现 DevOps。
- 最大限度地减少交接次数:通过最小化步骤数和所需人员来优化你的工作流。
- 自动化:自动化一切,但必须得在你确认好自动化的内容之后。请记住,持续集成、持续交付和持续部署,这些都是你良师益友。
- 删除外部依赖项:与团队中的人合作更容易,因此请删除或尽量减少外部依赖项。
- 安全网控制:故障恢复,而不是试图完全避免故障。
译后记
作者在文中非常强调自动化的实践,并且强调了,如果需要进行严格的权责分离(这是许多中国团队面临的实际问题),更加需要依赖于自动化,以减少效率的损耗。这与 CODING 的理念不谋而合。我们也认为自动化能帮助研发组织解放研发效能。
CODING 的持续集成和制品库帮助你轻松搞定自动化流水线,实现软件的快速交付。CODING 持续集成(CCI)全面兼容 Jenkins 的持续集成服务,支持 Java、Python、Node.js 等所有主流语言编译环境,并且支持 Docker 镜像的构建。只要几步配置,就可以开启 Git 代码仓库的持续集成。构建产物还可通过 CODING 制品库进行统一管理。目前 CODING 支持 Docker Image、Maven/Jar、Kubernetes Helm、Node.js NPM 包等常见软件包类型。
CODING 帮助您控制每一次从引入代码变更到发布的整个过程,从而更好地优化软件交付的速度和质量。