更新时间:2024-11-08 GMT+08:00
分享

如何构建高效的持续交付能力

持续集成、持续交付、持续部署、以及持续发布,到底是什么含义?

在回答之前,请大家先思考一个问题 :什么是交付过程最痛苦的事情?

集成的过程,测试的过程,以及部署与发布,都很痛苦,否则不会有敏捷与DevOps的各种方法与实践来解决这些问题,但是这些过程又都非常重要。

就此问题,引用《极限编程》里面的四句话来回答:

  1. 如果集成是重要的(集成的目的在于测试),那么我们将在一天中多次集成并测试。
  2. 如果测试是好的,那么所有人都应该始终进行测试。
  3. 如果设计是好的,那么我们应该把它当做日常事务的一部分。
  4. 如果迭代短些好,那么我们将使迭代时间非常短,秒、分钟或小时,而不是周、月或年。

因此,给出的对策是:如果一件事非常重要,那么我们就把它做到最好。

频繁地沟通

我们来解读第一句话:“如果集成是重要的(集成的目的在于测试),那么我们将在一天中多次集成并测试。”

代码交付是一种沟通,代码的交付过程事实上是开发人员之间的沟通:“我修改了什么代码,是为了什么,你们谁帮我review一下,谁也在改同样的文件,谁merge一下。”

来源:Jez Humble - continuous delivery

从沟通的角度上来说,当然是越频繁越好,那么自然是下面这张图会更适合,而这张图,就是持续集成的场景。

软件版本管理

软件版本管理,即SCM,为什么前所未有的受到重视?

每个公司通常会有一个Build Manager的角色,他不是manager,他管的是代码库、分支策略以及编译构建服务器。

版本管理的目的是版本控制,回溯历史信息;帮助团队之间进行协作,跨团队,甚至跨时区、跨国家;研发过程的管理,包括变更、审批以及相关的流程等,以及问题发生后的追踪。简单而言,就是为了回答,如何重现一个环境:到底是谁,在什么时候,修改了什么,是为了什么。从版本分支的管理,看到的是软件的发布机制,这是持续交付的核心。

此外,发布的过程,也是开发与运维之间的协同与沟通,这正是DevOps试图解决的问题。

版本管理的目标:为了确保即使是在发生灾难性事件的时候,也可以重复且精确的、最好还能快速的,恢复生产环境。那么所有为了达成这一目标的资源,都应该纳入版本控制系统。

  • CodeArts软件版本管理

    为了将所有资源纳入版本控制系统中,在CodeArts上提供了代码托管、软件发布库、私有依赖库等功能。

    • 代码托管服务基于Git,项目的开发代码可以上传至CodeArts进行代码托管,统一管理。
    • 软件发布库可用来存储构建好的软件包,实现软件包版本管理,提升发布质量和效率,实现产品的持续发布。
    • 私有依赖库可用于将项目当中的依赖包上传至此库中,以方便云端构建,并进行版本控制,避免环境差异化。

分支策略

不论是主干开发模式,还是Git Flow、Github Flow、Gitlab Flow,事实上背后都是研发与交付的模式体现。选择哪种分支策略,与团队的能力成熟度,与自身的业务模式,与客户的管控要求,都息息相关。

下图中,左边是2006年写成的持续集成的原则,直到今天,这些原则都依然适用,而且绝大多数企业和团队都没有做到。右边是持续交付一书中列出的持续集成必选的实践,同样的经典。

需要注意的是,我们不只是要关注这些原则和实践本身,更重要的,是关注它们背后之间的关联。

持续测试

第二句话来了:如果测试是好的,那么所有人都应该始终进行测试。这句话,我们今天叫做持续测试。

今天测试人员感觉到前所未有的危机感。

以前,测试人员归属于QA部门。从这个角度来说,只要是归属于质量保障的范围,都可视为测试人员的职责范围。

如今,有几条有关有效质量控制的建议:

  • 让听得到炮声的人做出决策,而不是远离一线的管理者。
  • Build Quality In,所有人都有责。
  • 测试与架构相关,包括技术架构,以及组织架构。
  • 测试的过程,是从失败中学习的过程。
  • 自动化,自动化,自动化,尽可能的自动化一切该自动化的,但又不要过度的依赖于自动化,不要过度追求自动化。

下图是测试金字塔,核心是从关注测试的数量转向关注测试的质量。尤其是在持续集成之下,测试执行要求是快速闭环的。越往下的,隔离性越高,定位问题就越容易,反馈也会越快,因此应该要发现更多的问题,投入更多的精力;越往上的,反馈周期越长,运行效率越低,修复和维护的成本都很高,复杂性也随之升高,应该做的频度越少。

事实上,我们有双层的金字塔结构,上面是线上环境的测试,包括拨测、捣乱猴子测试,以及各类的性能和安全测试。

刚才说应该测试前移,投入更多的在短周期的活动;同时又说,测试要延展到生产环境,覆盖发布和线上的运行阶段。事实上,测试应该向两端延展,测试活动应该是真正贯穿在整个产品生命周期的。从这点上来讲,测试人员如果还是用原先的方法和手段,是无法处理好问题的。

那么,缺陷成本是越来越大么?我们所有的教育都告诉我们是的,包括说要从源头来保障质量,缺陷随着时间的推移,修复的成本越高;变化的成本随时间的推移而以指数级上升。但同时,敏捷又说要拥抱变化,精益建议要推迟决策,这是不是矛盾呢?

《DevOps软件架构师行动指南》中提出,问题不在于变化,因为变化总是要发生的;问题在于发生变化时,是否有能力来应对。

决定是否易于修改的因素有:

  • 简单的设计,这也是极限编程的建议。
  • 松耦合的架构,频繁并主动的修改设计。
  • 锻炼组织的工程能力。
  • 以及构筑快速反馈、快速应对变化的能力。

测试是越多越好么?自动化测试呢?

  • 处于探索阶段的产品,不确定性极高,此时投入过多精力去搞测试,一味地追求测试覆盖率等指标,最后发现市场方向不对,要推翻重做,那么前面投入的测试就全是浪费,此时应该以手工测试为主。
  • 当发现市场正确,快速投入人力和物力,此刻需要的是产品的快速增长,需要开始引入关键的自动化测试来保障效率和质量。
  • 到产品稳定阶段,自动化测试的目的是回归,保障质量的稳定。

那么问题又来了,测试能防范所有的问题么?当然不能,这里有两种安全,一种是试图发现尽可能多的,甚至是消除错误的部分,达到绝对的安全,这过于理想,不可实现;所以我们推荐的是第二种,弹性安全,尤其是适用于云化的场景,即便是发生了错误,我们需要追求的是快速恢复的能力。

  • CodeArts测试管理

    为了对测试用例等进行可回溯的统一管理,我们需要用到测试用例管理工具。

    在CodeArts中,测试管理支持手工测试和接口测试。很好的帮我们解决了这一问题。

    • 接口测试可以自动化集成到流水线当中。
    • 所有的测试用例都可以关联到工作项当中。

架构解耦、团队解耦

第三句话:如果设计是好的,那么我们应该把它当做日常事务的一部分。

架构做的不好,留下的是技术债务。技术债务都是不好的么?当然也不是。

技术债务如同3X曲线,在早期应该有意识的去背负一些债务,来换取时间窗口,来撬动杠杆。当然这个应该是有意而为之的事情,不是懵懂无知的。随后,需要将偿还技术债务的活动,制度化,常规化。

为了持续集成、持续测试的进行,需要进行架构解耦。除了技术架构层面的,当然还有组织架构。从功能型组织,竖井的工作模式,部门墙林立,变为产品型的组织,每个产品或服务作为独立的利润中心,阿米巴模式。

康威定律说组织架构与技术架构相互对应,《赋能》里面提到的分布式的小型团队,事实上是进一步的去中心化,甚至都没有稳定的小团队。

持续交付

最后一句话:如果迭代短些好,那么我们将使迭代时间非常短,秒、分钟或小时,而不是周、月或年。

如果做到这一点,事实上就是持续交付。

持续集成、持续交付、持续部署,还是傻傻分不清楚?

持续交付是指团队确保每个变更可以部署至生产环境,但也许并不需要实际部署,通常是出于业务方面的原因。

所以核心是技术决策,与业务决策的分离。持续部署,是一个技术行为,持续交付是业务行为,交付的是业务价值。是否需要持续的部署到生产环境,是由业务形态决定的,而技术层面,反而是一蹴而就的事情。

进一步的,甚至部署到了生产环境,也可以不意味着正式发布。通过技术手段,我们可以将部署与发布解耦,通过特性开关、灰度上线等技术手段,可以赋能业务进行A/B测试,灰度发布等业务行为,这是技术赋能业务的最典型场景,也是最有力的支撑。

最终,持续交付归结为一句话,痛苦的事情反复做

下图所示的持续交付的原则中,红体字描述的,是最与技术无关的一个实践,却也是最重要的核心理念:提前并频繁的做让人感到痛苦的事。

小结

在开始行动之前,首先应思考需要解决的是什么问题,而不是去问应该采纳何种方式。

不应去问持续集成应该怎么做,TDD应该怎么做。那些都是解决方案域的东西,而应先搞清楚自身现存什么问题。正如去医院看病,不是直接找医生开药,而是应该问清楚自己是什么病,再对症开具体的药。

实践的目的是为了解决具体问题,而不是解决所有问题。

所以说,大部分问题是文化的问题,而不是一个DEVOPS的问题。文化可以化解一切,而一切的根因又归结于文化。

相关文档