DevOps 实战笔记--学习笔记记录

DevOps 实战笔记--学习笔记记录

[TOC]

本文为极客时间《DevOps 实战笔记》的学习笔记, 原教程链接.

基础理论篇

01丨DevOps的“定义”:DevOps究竟要解决什么问题?

背景

如何快速地持续交付高质量的软件,满足用户的多样化需求,并借此提升企业的利润和市场占有率。

软件开发过程的改进,除了依赖于技术进步,还依赖于流程、理念、文化等全方位的改进,而这正是 DevOps 带给软件开发方式的一场革命。

教程目的

如何梳理出一套清晰的 DevOps 理念和完整的知识体系?如何获得一线大厂的实践经验,让 DevOps 真正落地?如何获得一条渐进式的 DevOps 学习曲线,让自己在正确的方向上不断增值?

定义

DevOps(开发 Development 与运维 Operations 的组合词)是一种文化、一场运动或实践,强调在自动化软件交付流程及基础设施变更过程中,软件开发人员与其他信息技术(IT)专业人员彼此之间的协作与沟通。它旨在建立一种文化与环境,使构建、测试、软件发布得以快速、频繁以及更加稳定地进行。

DevOps 究竟要解决的是什么问题

瀑布式开发模式将软件交付过程划分成几个阶段,从需求到开发、测试和运维,它的理念是软件开发的规模越来越大,必须以一种工程管理的方式来定义每个阶段,以及相应的交付产物和交付标准,以期通过一种重流程,重管控,按照计划一步步推进整个项目的交付过程。

软件开发活动需要在项目一开始就确定项目目标、范围以及实现方式,而这个时间点往往是我们对用户和市场环境信息了解最少的时候,这样做出来的决策往往带有很大的不确定性,很容易导致项目范围不断变更,计划不断延期,交付上线时间不断推后,最后的结果是,即便我们投入了大量资源,却难以达到预期的效果。

敏捷开发的思潮开始盛行。它的核心理念是,既然我们无法充分了解用户的真实需求是怎样的,那么不如将一个大的目标不断拆解,把它变成一个个可交付的小目标,然后通过不断迭代,以小步快跑的方式持续开发。与此同时,将测试工作从研发末端的一个独立环节注入整个开发活动中,对开发交付的内容进行持续验证,保证每次可交付的都是一个可用的功能集合,并且由于质量内建在研发环节中,交付功能的质量也是有保障的。

敏捷之所以更快,根本原因在于持续迭代和验证节省了大量不必要的浪费和返工。

DevOps 最开始想要打破的就是开发和运维之间的对立和隔阂。

DevOps 是通过平台(Platform)、流程(Process)和人(People)的有机整合,以 C(协作)A(自动化)L(精益)M(度量)S(共享)文化为指引,旨在建立一种可以快速交付价值并且具有持续改进能力的现代化 IT 组织。

02丨DevOps的价值:数字化转型时代,DevOps是必选项?

我们所身处的是一个VUCA的时代,VUCA 是指易变性(Volatility)、不确定性(Uncertainty)、复杂性(Complexity)和模糊性(Ambiguity),它代表了这个时代的典型特征。 “工业革命消灭了绝大多数的手工业群体,却催生了程序员这个现存最大的手工业群体”。

4 个核心指标统计行业内高效能团队和低效能团队之间的差距:

部署频率:指应用和服务向生产环境部署代码的频率。

变更前置时间:指代码从提交到成功运行在生产环境的时长。

服务恢复时间:指线上应用和服务出现故障到恢复运行的时长。

变更失败率:指应用和服务在生产环境部署失败或者部署后导致服务降级的比例。

实施 DevOps,一方面可以通过种种流程优化和自动化能力,改善软件开发团队的工作节奏,另一方面,也可以让大家关注同一个目标,彼此信任,高效协作,调动员工的积极性和创新能力,从而让整个团队进入一种积极创造价值的状态,而这所带来的影响远非建设一两个工具平台可比拟的。

03丨DevOps的实施:到底是工具先行还是文化先行?

工具和自动化就是提升效率最直接的手段,让一切都自动化可以说是 DevOps 的行为准则。一切软件交付过程中的手动环节,都是未来可以尝试进行优化的方向。

很多公司引入了完整的敏捷项目管理工具,但是却以传统项目管理的方式来使用这套工具,效率跟以前相比并没有明显的提升。

我们需要先改变行为,再通过行为来改变文化。而改变行为最关键的,就是要建立一种有效的机制。就像我一直强调的那样,机制就是人们愿意做,而且做了有好处的事情。

平台化的力量

平台除了有用户量、认可度、老板加持等因素之外,还会有 3 个显著特征。
吸附效应:平台会不断地吸收中小型的工具,逐渐成为一个能力集合体。

规模效应:平台的成本不会随着使用方的扩展而线性增加,能够实现规模化。

积木效应:平台具备基础通用共享能力,能够快速搭建新的业务实现。

人 + 流程 = 文化

流程 + 平台 = 工具

平台 + 人 = 培训赋能

04丨DevOps的衡量:你是否找到了DevOps的实施路线图?

任何技术的成熟,都是以模型和框架的稳定为标志的。比如,软件开发领域的 CMMI 模型(软件能力成熟度模型)、运维行业的 ITIL 模型等。《跨越鸿沟》,这本书中提出了一个“技术采纳生命周期定律”。

一个参考的发展流程:

在实际参考模型和框架的时候,应该尽量遵循以下步骤和原则:
1.识别差距

2.锚定目标: 数字化转型的核心在于优化软件交付效率。

3.关注能力: 模型和框架是能力和实践的集合,也就是道法术器的“术”这个层面,所以在应用模型的过程中,核心的关注点应该在能力本身,而不是单纯地比较数字和结果。
4.持续改进

经典的部署引力图:

可以看出,当软件发布的频率从 100 天 1 次进化到 1 天 100 次的时候,分支策略、测试能力、软件架构、发布策略、基础设施能力,以及数据库能力都要进行相应的改动。比如分支策略要从长线分支变成基于特性的主干开发模式,而架构也要从大的单体应用,不断解耦和服务化。

引用一下 ITILV4 的指导原则,包括:关注价值、关注现状、交互式流程和反馈、协作和可视化、自动化和持续优化、极简原则和关注实践

落地实践篇

05丨价值流分析:关于DevOps转型,我们应该从何处入手?

价值流图

VSM 是 Value Stream Mapping 的缩写,也就是我们常说的价值流图。它起源于传统制造业的精益思想,用于分析和管理一个产品交付给用户所经历的业务流、信息流,以及各个阶段的移交过程。说白了,VSM 就是要说清楚在需求提出后,怎么一步步地加工原材料,进行层层的质量检查,最终将产品交付给用户的过程。
VSM 中有哪些关键要素和概念呢?有 3 点是你必须要了解的。

前置时间(Lead Time,简称 LT)。它是指一个需求从提出(典型的就是创建一个需求任务)的时间点开始,一直到最终上线交付给用户为止的时间周期。这部分时间直接体现了软件开发团队的交付速率,并且可以用来计算交付吞吐量。DevOps 的核心使命之一就是优化这段时长。

增值活动时间不增值活动时间(Value Added Time/Non-Value Added Time,简称 VAT/NVAT)。在精益思想中,最重要的就是消除浪费,也就是说最大化流程中那些增值活动的时长,降低不增值活动的时长。在软件开发行业中,典型的不增值活动有很多,比如无意义的会议、需求的反复变更、开发的缺陷流向下游带来的返工等。

完成度和准确度(% Complete/Accurate,简称 %C/A)。这个指标用来表明工作的质量,也就是有多少工作因为质量不符合要求而被下游打回。这里面蕴含了大量的沟通和返工成本,从精益的视角来看,也是一种浪费。

一般建议采用需求前置时间开发前置时间两个指标进行衡量。

各个环节提升价值的图解例子如下:

VSM 具有非常丰富的价值:

  1. 看见全貌。对于全局交付的建模,最终也会体现到软件持续交付流水线的建设上。
  2. 识别问题。
  3. 促进沟通。
  4. 驱动度量。
  5. 价值展现。

VSM 图解:

06 | 转型之路:企业实施DevOps的常见路径和问题

两种轨迹,一种是自底向上,一种是自顶向下。寻求管理层的认可和支持都是一个必选项。

通用路径

第 1 步:寻找合适的试点项目贴近核心业务倾向敏捷业务改进意愿优先。

第 2 步:寻找团队痛点“木桶原理”就行了,即最短的木板决定了团队的容量。

第 3 步:快速建立初期成功,最关键的就是识别一个改进点,定义一个目标。

第 4 步:快速展示和持续改进。

DevOps 转型的 J 型曲线:

在转型初期,建立一个专职的转型工作小组还是很有必要的。这个团队主要由 DevOps 转型关联团队的主要负责人、DevOps 专家和外部咨询顾问等牵头组成,一般是各自领域的专家或者资深成员,相当于 DevOps 实施的“大脑”,主要负责制定 DevOps 转型项目计划、改进目标识别、技术方案设计和流程改造等。除了核心团队管理团队工具团队也很重要。

07 | 业务敏捷:帮助DevOps快速落地的源动力

在现在这个多变的时代,没人能够准确地预测需求的价值。所以,交付能力的提升,可以帮助业务以最小的成本进行试错,将新功能快速交付给用户。同时,用户和市场的情况又能够快速地反馈给业务方,从而帮助业务校准方向。而业务的敏捷能力高低,恰恰体现在对功能的设计和需求的把握上,如果不能灵活地调整需求,专注于最有价值的事情,同样会拖累交付能力,导致整体效率的下降。也就是说,在这样一种快速迭代交付的模式下,业务敏捷和交付能力二者缺一不可。所以,开发更少的功能,聚焦用户价值,持续快速验证,就成了产品需求管理的核心思想。关于需求分析,比较常见的方法就是影响地图。影响地图是通过简单的“Why-Who-How-What”分析方法,实现业务目标和产品功能之间的映射关系。

例子如下:

需求这么多,优先级要怎么安排呢?卡诺模型(Kano Model),是日本大师授野纪昭博士提出的一套需求分析方法,它对理解用户需求,对其进行分类和排序方面有着很深刻的洞察。

卡诺模型将产品需求划分为五种类型:

  • 兴奋型:指超乎用户想象的需求,是可遇不可求的功能。比如用户想要一个更好的功能手机,乔布斯带来了 iPhone,这会给用户带来极大的满足感。
  • 期望型:用户的满意度会随着这类需求数量的增多而线性增长,做得越多,效果越好,但难以有质的突破。比如,一个电商平台最开始是卖书,后面逐步扩展到卖电脑、家居用品等多个类别。用户更多的线性需求被满足,满意度自然也会提升。
  • 必备型:这些是产品必须要有的功能,如果没有的话,会带来非常大的影响。不过有这些功能的话,也没人会夸你做得有多好,比如安全机制和风控机制等。
  • 无差别型:做了跟没做一样,这就是典型的无用功。比如你花了好大力气做了一个需求,但是几乎没有用户使用,这个需求就属于无差别型。
  • 反向型:无中生有类需求,实际上根本不具备使用条件,或者用户压根不这么想。这类需求做出来以后,通常会给用户带来很大的困扰,成为被吐槽的对象。

对于五类需求来说,核心要做到 3 点:

  • 优先规划期望型和必备型需求,将其纳入日常的交付迭代中,保持一定的交付节奏;
  • 识别无差别型和反向型需求,这些对于用户来说并没有产生价值。如果团队对需求的分类有争议,可以进一步开展用户调研和分析。
  • 追求兴奋型需求,因为它会带来产品的竞争壁垒和差异化。不过,对于大公司而言,经常会遇到创新者的窘境,也就是坚持固有的商业模式,而很难真正投入资源创新和自我颠覆。这就要采用精益创业的思想,采用 MVP(最小可行产品)的思路,进行快速验证,并且降低试错成本,以抓住新的机遇。

在以往进行需求讨论的时候,往往有两个不可取的极端:

  • 一种是一句话需求,典型的“给你一个眼神,你自己体会”的方式,反正我就要做这件事,至于为什么做、怎么做一概不管,你自己看着办;

  • 另一种是上来就深入实现细节,讨论表字段怎么设计、模块怎么划分,恨不得撸起袖子就跟研发一起写代码。

用户故事则是以用户的价值为核心,圈定一种角色,表明通过什么样的活动,最终达到什么样的价值。团队在讨论需求的时候,采用一种讲故事的形式,代入到设定的用户场景之中,跟随用户的操作路径,从而达成用户的目标,解决用户的实际问题。这样做的好处在于,经过团队的共同讨论和沟通,产品、研发和测试对需求目标可以达成共识,尤其是对想要带给用户的价值达成共识。

用户故事的粒度同样需要进行拆分,拆分的原则是针对一类用户角色,交付一个完整的用户价值,也就是说用户故事不能再继续拆分的粒度。当然,在实际工作中,拆分的粒度还是以迭代周期为参考

检验用户故事拆分粒度是否合适,可以遵循 INVEST 原则

  • Independent(独立的):减少用户故事之间的依赖,可以让用户故事更加灵活地验证和交付,而避免大批量交付对于业务敏捷性而言至关重要。
  • Negotiable(可协商的):用户故事不应该是滴水不漏、行政命令式的,而是要抛出一个场景描述,并在需求沟通阶段不断细化完成。
  • Valuable(有价值的):用户故事是以用户价值为核心的,所以每个故事都是在对用户交付价值,所以要站在用户的视角思考问题,避免像最近特别火的那句话一样:“我不要你觉得,我要我觉得。
  • Estimatable(可评估的):用户故事应该可以粗略评估工作量,无论是故事点数还是时间,都可以。如果是一个预研性质的故事,则需要进一步深挖可行性,避免不知道为什么做而做。
  • Small(小的):用户故事应该是最小的交付颗粒度,所以按照敏捷开发方式,无论迭代还是看板,都需要在一个交付周期内完成。
  • Testable(可测试的):也就是验收条件,如果没有办法证明需求已经完成,也就没有办法进行验收和交付。

采用客观有效的反馈机制就成了必选项。

  • 从技术层面来说,一个业务需求的背后,一般都会关联一个埋点需求。所谓埋点分析,是网站分析的一种常用的数据采集方法。设计良好的埋点功能,不仅能帮助采集用户操作行为,还能识别完整的上下文操作路径,甚至进行用户画像的聚类和分析,帮助识别不同类型用户的行为习惯。

  • 从用户层面来说,众测机制用户反馈渠道是比较常见的两种方式,核心就是既要听用户怎么说,也要看用户怎么做。

08/9| 精益看板:精益驱动的敏捷开发方法

两种常见的敏捷框架:

  • Scrum
  • 精益看板

拉动式生产,从后端消费者的需求出发,向前推导,需要什么就生产什么,而不是生产出来一大堆没人要的东西,从而达到减低库存、加速半成品流动和灵活响应变化的目的。

有关丰田生产方式的图片,它演示了整个丰田生产方式的运作过程。

加快价值流动是精益看板的核心。

在软件开发中,这个价值可能是一个新功能,也可能是缺陷修复,体验优化。根据利特尔法则,我们知道:平均吞吐率 = 在制品数量 / 平均前置时间。其中,在制品数量就是当前团队并行处理的工作事项的数量如果交付周期比需求变化周期更长,那就意味着紧急任务增多。比如老板发现一个线上缺陷,必须高优先级修复,类似的紧急任务增多,就会导致在制品数量进一步增多。这样一来,团队就陷入了一个向下螺旋,这对团队的士气和交付预期都会造成非常不好的影响,以至于有些团队 90% 的精力都用来修复问题了,根本没时间交付需求和创新。更加严重的问题是,这个时候,业务部门对 IT 部门的信任度就会直线下降。业务部门往往会想:“既然无法预测需求的交付实践,那好吧,我只能一次性压给你一大堆需求。”这样一来,就进一步导致了在制品数量的上升。

精益看板的实践方法分为了五个步骤。

  • 第一步:可视化流程;
  • 第二步:定义清晰的规则;
  • 第三步:限制在制品数量;
  • 第四步:管理工作流程;
  • 第五步:建立反馈和持续改进。

第一步:可视化流程–看板:

看板的主要构成元素可以简单概括成“一列一行”。
看板的竖向队列,是按照价值流转的各个主要阶段进行划分的,比如常见的需求、开发、测试、发布等。对识别出来的每一列进一步可以划分成“进行中”和“已完成”两种状态,这也是精益看板拉动式生产的一个显著特征。对于列的划分粒度可以很细,比如开发阶段可以进一步细分成设计、编码、自测、评审、提测等环节,或者就作为一个单独的开发环节存在。

划分的标准主要有两点:

  1. 是否构成一个独立的环节。比如对于前后端分离的开发来说,前端开发和后端开发就是两个独立的环节,一般由不同的角色负责,这种就比较适合独立阶段。

  2. 是否存在状态的流转和移交。看板是驱动上下游协同的信号卡.

看板横向的泳道。泳道用于需求与需求之间划清界限。泳道还可以按照不同维度划分。比如,有的看板设计中会加入紧急通道,用于满足紧急需求的插入。另外,非业务类的技术改进需求,也可以在独立泳道中进行。

第二步:定义清晰的规则

  1. 可视化规则。在上一讲中,我们提到,看板中的主要构成元素是“一列一行”。实际上,看板中卡片的设计也有讲究,

    主要有 3 点。

    • 卡片的颜色:用于区分不同的任务类型,比如需求(绿色)、缺陷(红色)和改进事项(蓝色);
    • 卡片的内容:用于显示任务的主要信息,比如电子看板 ID 号,需求的名称、描述、负责人、预估工作量和停留时长等;
    • 卡片的依赖和阻塞状态:用于提起关注,比如在卡片上通过张贴不同的标志,表示当前卡片的健康程度,对于存在依赖和阻塞状态的卡片,需要团队高优先级协调和处理。
  2. 显式化规则。看板除了要让人看得懂,还要让人会操作。
    这些规则包括:

  • 谁来负责整理和移动卡片?
  • 什么时间点进行卡片操作?
  • 卡片的操作步骤是怎样的?
  • 什么时候需要线下沟通?
  • 哪些标识代表当前最高优先级的任务?
  • 看板卡片的填充规则是怎样的?
  • 谁来保障线下和线上看板的状态一致性?

第三步:限制在制品数量

要想做到业务敏捷,就得想发就发,做完一个上一个。DevOps 所倡导的是“You build it,you run it”的理念,这也是亚马逊公司最为经典的团队理念。

第四步:管理工作流程

在看板方法中,常见的有三种会议,分别是每日站会队列填充会议发布规划会议

与 Scrum 方法的“夺命三连问”(昨天做了什么?今天计划做什么?有什么困难或者阻塞?)相比,看板方法的站会则略有不同。因为,第二步制定了清晰的规则,团队的现状已经清晰可见,只需要同步重点任务。

看板方法更加关注两点:

  • 待交付的任务。
  • 紧急、缺陷、阻塞和长期没有更新的任务。

每日站会

要尽量保持高效,对于一些存在争议的问题,或者是技术细节的讨论,可以放在会后单独进行。同时,会议的组织者也要尽量观察每日站会的执行效果,如果出现停顿或者不顺畅的情况,那就意味着规则方面有优化空间。

队列填充会议

队列填充会议的目标有两点:一个是对任务的优先级进行排序,一个是展示需求开发的状态。

其他内容略过。

10 | 配置管理:最容易被忽视的DevOps工程实践基础

配置管理

一个宏观的概念,是站在软件交付全生命周期的视角,对整个开发过程进行规范管理,控制变更过程,让协作更加顺畅,确保整个交付过程的完整、一致和可追溯。

四个核心理念

  1. 版本变更标准化,将一切纳入版本控制,全流程可追溯和单一可信数据源

    版本变更标准化配置管理中的另一个核心概念是变更。版本来源于变更。对于变更而言,核心就是要记录:谁,在什么时间,做了什么改动,具体改了哪些内容,又是谁批准的

    改动说明一般就是版本控制系统的提交记录,一个完整的提交记录应该至少包括以下几个方面的内容:

    • 提交概要信息:简明扼要地用一句话说明这个改动实现了哪些功能,修复了哪些问题;

    • 提交详细信息:详细说明改动的细节和改动方式,是否有潜在的风险和遗留问题等;

    • 提交关联需求:是哪次变更导致的这次提交修改,还需要添加上游系统编号以关联提交和原始变更。
      遵循一种标准化的格式,并且有相关的格式说明和书写方式,比如有哪些关键字,每一行的长度,变更编号的区隔是使用逗号、空格还是分号等等。

      一套标准化的规则和行为习惯,可以降低协作过程中的沟通成本,一次性把事情做对,这也是标准和规范的重要意义。

  2. 将一切纳入版本控制
    比如软件源代码、配置文件、测试编译脚本、流水线配置、环境配置、数据库变更等等一切,皆有版本,皆要被纳入管控。比如,环境管理方面推荐采用基础设施即代码的方式管理环境,也就是说把用代码化的方式描述复杂的环境配置,同时把它纳入版本控制系统中。这样一来,任何环境变更都可以像提交代码一样来完成,不仅变更的内容一目了然,还可以很轻松地实现自动化。把原本复杂的事情简单化,每一个人都可以完成环境变更。
    如果这个产物可以通过其他产物来重现,那么就可以作为制品管理,而无需纳入版本控制。
    举个例子,软件包可以通过源代码和工具重新打包生成,那么,代码、工具和打包环境就需要纳入管控,而生成的软件包可以作为制品;软件的测试报告如果可以通过测试管理平台重新自动化生成,那么同样可以将其视为制品,但前提是,测试管理平台可以针对每一个版本重新生成测试报告。

  3. 全流程可追溯
    对于配置管理来说,除了追溯能力以外,还有一个重要的价值,就是记录关联和依赖关系。针对任意一个需求,需要能够快速识别出它所关联的代码、版本、测试案例、上线记录、缺陷信息、用户反馈信息和上线监控数据等。对于任意一个应用,要可以识别出它所依赖的环境,中间件,上下游存在调用关系的系统、服务和数据等。
    把握源头,建立主线。所谓源头,对于软件开发而言,最原始的就是需求,所有的变更都来源于需求。

  4. 单一可信数据源

    对于代码来说,要有统一的版本控制系统,不能代码满天飞;

    对于版本来说,要有统一的渠道,不能让人随便本地打个包就传到线上去了;

    对于开发依赖的组件来说,要有统一的源头,不能让来路不明的组件直接集成到系统中。

配置管理的最大价值正是将信息序列化,对信息进行有效的整理、归类、记录和关联。

11 | 分支策略:让研发高效协作的关键要素

主干开发,分支发布。

开发团队共享一条主干分支,所有的代码都直接提交到主干分支上,主干分支就相当于是一个代码的全量合集。在软件版本发布之前,会基于主干拉出一条以发布为目的的短分支。

以发布为目的。这条分支存在的意义不是开发新功能,而是对现有功能进行验收,并在达到一定的质量标准后对外发布。一般来说,新功能不会基于这条分支提交,只有一些 Bugfix 会集成进来。所以,对于这种发布分支会有比较严格的权限管控。

短分支。这条发布分支一般不会存在太长时间,只要经过回归验证,满足发布标准后,就可以直接对外发布,这时,这条分支的历史使命也就结束了。除非上线之后发现一些紧急问题需要修复,才会继续在这条分支上修改验证,并将改动同步回主干分支。所以,只要在主干分支和发布分支并行存在的时间段内,所有发布分支上的改动都需要同步回主分支,这也是我们不希望这条分支存在时间过长的原因,因为这会导致重复工作量的线性累计。

对于以版本节奏驱动的软件项目来说,这种分支策略非常常见,比如客户端产品,或者是那种需要在客户终端升级的智能硬件产品,像智能手机、智能电视等。

这种模式的优势有三个:

  1. 对于研发团队来说,只有一条主线分支,不需要在多条分支间切换。
  2. 在发布分支拉出之后,主干分支依然处于可集成状态,研发节奏可以保持在一个相对平稳的状态。
  3. 发布分支一般以版本号命名,清晰易懂,线上哪个版本出了问题,就在哪个分支上修复。

不过,这种模式也存在着缺点和挑战:

  • 它对主线分支的质量要求很高。如果主线分支出了问题,就会 block 所有开发团队的工作。
  • 它对团队协作的节奏要求很高。如果主线分支上的功能没有及时合入,但是业务方又坚持要在指定版本上线这个功能,这就会导致发布分支“难产”。
  • 甚至有些时候,会被迫允许部分未开发完成的功能在发布分支上继续开发,这会给发布分支的质量和稳定性造成很大的挑战。在主线和发布分支并存期间,有可能会导致两边提交不同步的情况。

这些问题的解决方法包括以下几点:

  • 建立提交的准入门禁,不允许不符合质量标准的代码合入主线。
  • 采用版本火车的方式,加快版本的迭代速度,功能“持票上车”,如果跟不上这个版本就随下个版本上线。
  • 另外,可以采用功能开关、热修复等手段,打破版本发布的固定节奏,以一种更加灵活的方式对外发布。
  • 通过自动化手段扫描主线和发布分支的差异,建立一种规则。比如 Hotfix 必须主线和发布分支同时提交,或者发布分支上线后,由专人反向同步等。

分支开发,主干发布

当开发接到一个任务后,会基于主干拉出一条特性开发分支,在特性分支上完成功能开发验证之后,通过 Merge request 或者 Pull request 的方式发起合并请求,在评审通过后合入主干,并在主干完成功能的回归测试。开源社区流行的 GitHub 模式其实就是属于这种。

根据特性和团队的实际情况,还可以进一步细分为两种情况:

  1. 每条特性分支以特性编号或需求编号命名,在这条分支上,只完成一个功能的开发;

  2. 以开发模块为单位,拉出一条长线的特性分支,并在这条分支上进行开发协作。

两者的区别就在于特性分支存活的周期,拉出时间越长,跟主干分支的差异就越大,分支合并回去的冲突也就越大。所以,对于长线模式来说,要么是模块拆分得比较清晰,不会有其他人动这块功能,要么就是保持同主干的频繁同步。随着需求拆分粒度的变小,短分支的方式其实更合适。

这种模式下的优势也有两点:

  • 分支开发相对比较独立,不会因为并行导致互相干扰。同时,特性只有在开发完成并验收通过后才会合入主干,对主干分支的质量起到了保护作用;
  • 随着特性分支的流行,在这种模式下,分支成了特性天然的载体。一个特性所关联的所有代码可以保存在一条特性分支上,这为以特性为粒度进行发布的模式来说提供了一种新的可能性。也就是说,如果你想要发布哪个特性,就可以直接将特性分支合并到发布分支上,这就让某一个特性变得“可上可下”,而不是混在一大堆代码当中,想拆也拆不出来。
    特性发布虽然看起来很好,但是有三个前置条件:
    • 第一个是特性拆分得足够小。
    • 第二是有强大的测试环境作支撑,可以满足灵活的特性组合验证需求。
    • 第三是要有一套自动化的特性管理工具。

缺点:

  • 这非常考验团队特性拆分的能力。如果一个特性过大,会导致大量并行开发的分支存在,分支的集成周期拉长,潜在的冲突也会增多。

  • 分支长期存在也会造成跟主线差异过大的问题。

所以,特性的粒度和分支存活的周期是关键要素。

根据经验来看,分支存活的周期一般不要超过一周。

对特性分支的命名规范要求很高。

由于大量特性分支的拉出,整个代码仓库会显得非常乱。面对一大堆分支,谁也说不清到底哪个还活着,哪个已经没用了。所以,如果能够跟变更管理系统打通,自动化创建分支就最好了。特性分支的原子性和完整性,保证一个特性的关联改动需要提交到一条分支上,而不是到处都是。同时,特性分支上的提交也需要尽量清晰,典型的就是原子性提交

主干开发,主干发布

对于持续交付而言,最理想的情况就是,每一次提交都能经历一系列的自动化环境并部署到生产环境上面,而这种模式距离这个目标就更近了一点。

如果想要做到主干分支在任何时间都处于可发布状态,那么,这就对每一次提交的代码质量要求非常高。

为了保证主干分支的质量,自动化验收手段是必不可少的,因此,每一次代码提交都会触发完整的编译构建、单元测试、代码扫描、自动化测试等过程。

在代码合入主干后,会进行按需发布,先是发布到内部环境,也就是只有 Facebook 的员工才能看到这个版本,如果发现问题就立刻修复,如果没有问题,再进一步开放发布给 2% 的线上生产用户,同时自动化检测线上的反馈数据。直到确认一切正常,才会对所有用户开放。

最后,通过分支策略和发布策略的整合,注入自动化质量验收和线上数据反馈能力,最终将发布频率从固定的每天 2 次,提升到每天多次,甚至实现了按需发布的模式。Facebook 最新的分支策略如图所示:

分支策略代表了研发团队的行为准则,每个团队都需要磨合出一套适合自己的模式来。

12 | 持续集成:你说的CI和我说的CI是一回事吗?

CI 是 Continuous Integration 的缩写,也就是持续集成.

软件集成是一件高风险的、不确定的事情,国外甚至有个专门的说法,叫作“集成地狱”。

CI 本身源于肯特·贝克(Kent Beck)在 1996 年提出的极限编程方法(Extreme Programming,简称 XP)。是一种软件开发方法,作为敏捷开发的方法之一,目的在于通过缩短开发周期,提高发布频率来提升软件质量,改善用户需求响应速度。
马丁·福勒(Martin Fowler)的一篇博客中的当前最为业界公认的 CI 的定义之一:

CI 是一种软件开发实践,团队成员频繁地将他们的工作成果集成到一起(通常每人每天至少提交一次,这样每天就会有多次集成),并且在每次提交后,自动触发运行一次包含自动化验证集的构建任务,以便尽早地发现集成问题。

CI 采用了一种反常规的思路来解决软件集成的困境,其核心理念就是:越是痛苦的事情,就要越频繁地做
如果开发周期末端的一次性集成有这么大的风险和不确定性,那不如把集成的频率提高,让每次集成的内容减少,这样即便失败,影响的也仅仅是一次小的集成内容,问题定位和修复都可以更加快速地完成。这样一来,不仅提高了软件的质量,也大大降低了最后阶段的返工所带来的浪费,还提升了软件交付效率。

如何判断在践行 CI: 是否做到了3 个问题。

  1. 每一次代码提交,是否都会触发一次完整的流水线?
  2. 每次流水线是否会触发自动化的测试环节?
  3. 如果流水线出现了问题,是否能够在 10 分钟之内修复?

第一阶段:快速集成

这是对 CI 核心理念的最好诠释,也就是集成速度做到极致,每次变更都会触发 CI。当然,这里的变更有可能是代码变更,也有可能是配置、环境、数据变更。这样,所有的元数据变更都会被版本管理系统捕获,并通过事件或者 Webhook 的方式通知持续集成平台。
如果想做到每次提交都触发持续集成的话

  • 首先就需要打通版本控制系统和持续集成系统,比如 GitLab 和 Jenkins 的集成实施提交触发流水线。

  • 还需要一些前置条件。

    • 统一的分支策略。

    • 清晰的集成规则。

      比如,对于研发特性分支而言,目的主要是快速验证和反馈,那么速度就是不可忽视的因素,所以这个层面的持续集成,主要以验证打包和代码质量为主;而对于系统集成分支而言,它的目的不仅是验证打包和代码质量,还要关注接口和业务层面的正确性,所以集成的步骤会更加复杂,成本也会随之上升。所以,根据分支策略选择合适的集成规则,对于 CI 的有效运转来说非常重要。

    • 标准化的资源池。

      资源池作为 CI 的基础设施,重要性不言而喻。

      • 资源池需要实现环境标准化,也就是任何任务在任何节点都具备可运行的能力,这个能力就包括了工具、配置等一系列要素。如果 CI 任务在一个节点可以运行,跑到另外一个节点就运行失败,那么 CI 的公信力就会受到影响。
      • 资源池的并发吞吐量应该可以满足集中提交的场景,可以动态按需初始化的资源池就成了最佳选择。当然,同时还要兼顾成本因素,因为大量资源的投入如果没有被有效利用,那么造成的浪费是巨大的。
    • 足够快的反馈周期。

第二阶段:质量内建

  • 匹配合适的测试活动。

    对于不同层级的 CI 而言,同样需要根据集成规则来确定需要注入的质量活动。比如,最初级的提交集成就不适合那些运行过于复杂、时间太长的测试活动,快速的代码检查和冒烟测试就足以证明这个版本已经达到了最基本的要求。而对于系统层的集成来说,质量要求会更高,这样一来,一些接口测试、UI 测试等就可以纳入到 CI 里面来。

  • 树立测试结果的公信度。

    自动化测试的目标是帮助研发提前发现问题,但是,如果因为自动化测试能力自身的缺陷或者环境不稳定等因素,造成了 CI 的大量失败,那么,这个 CI 对于研发来说就可有可无了。所以,我们要对 CI 失败进行分类分级,重点关注那些异常和误报的情况,并进行相应的持续优化和改善。

  • 提升测试活动的有效性。

    考虑到 CI 对于速度的敏感性,那么如何在最短的时间内运行最有效的测试任务,就成了一个关键问题。显然,大而全的测试套件是不合时宜的,只有在基础功能验证的基础上,结合与本次 CI 的变更点相关的测试任务,发现问题的概率才会大大提升。所以,根据 CI 变更,自动识别匹配对应的测试任务也是一个挑战。

第三阶段:建立持续集成的文化

人不是关键,建立机制才是关键。什么是机制呢?机制就是一种约定,人们愿意遵守这样的行为,并且做了会得到好处

对于 CI 而言,保证集成主线的可用性,其实就是团队成员间的一种约定。这不在于谁出的问题谁去修复,而在于我们是否能够保证 CI 的稳定性,足够清楚问题的降级路径,并且主动关注、分析和推动问题解决。
另外,团队要建立清晰的规则,比如 10 分钟内没有修复则自动回滚代码,比如当 CI“亮红灯”的时候,团队不再提交新的代码,因为在错误的基础上没有办法验证新的提交,这时需要集体放下手中的工作,共同恢复 CI 的状态。只有团队成员深信 CI 带给团队的长期好处远大于短期投入,并且愿意身体力行地践行 CI,这个“10 分钟”规则才有可能得到保障,并落在实处。

13 | 自动化测试:DevOps的阿克琉斯之踵

业务功能的累加导致测试范围不断扩大,但这跟测试时长的压缩是矛盾的。说白了,就是要测试的内容越来越多,但是测试的时间却越来越短。

自动化测试适用于以下几种典型场景:

  • 有大量机械的重复操作,并且会反复执行的场景,比如批量的回归测试;
  • 有明确的设计规范且相对稳定的场景,比如接口测试;
  • 大批量、跨平台的兼容性测试,比如覆盖多种版本和多种机型的测试,几十个机型还可以接受,如果覆盖成百上千个机型,就只能依靠自动化了;
  • 长时间不间断执行的测试,比如压力测试、可用性测试等。

这些典型场景往往都具备几个特征:设计明确、功能稳定、可多次重复、长期大批量执行等,核心就是通过自动化手段来解决测试成本的问题。但这并不意味着手工测试就没有价值了。相反,当人从重复性劳动中解放出来后,就可以投入到更有价值的测试活动中,比如探索性测试、易用性测试、用户验收测试等,这些都属于手工测试的范畴。

自动化测试建设也面临着一些问题。

  • 投入产出比:很多需求基本上只会上线一次(比如促销活动类需求),那么,实现自动化测试的成本要比手动测试高得多,而且以后也不会再用了,这显然有点得不偿失。
  • 上手门槛:自动化测试依赖代码方式实现,要开发一套配置化的测试框架和平台,对架构设计和编码能力都有很大的要求。但是,测试人员的编码能力一般相对较弱。
  • 维护成本高:无论是测试环境、测试用例还是测试数据,都需要随着需求的变化不断进行调整,否则就很容易因为自动化测试过时,导致执行失败。测试设备投入高

自动化测试的设计

面对这么多种测试类型,到底要从哪里启动自动化测试的建设呢?

经典的测试三角形。这个模型描述了从单元测试、集成测试到 UI 测试的渐进式测试过程。越是靠近底层,用例的执行速度就越快,维护成本也越低。而在最上层的 UI 层,执行速度要比单元测试和接口测试要慢,比手工测试要快,相应的维护成本要远高于单元测试和接口测试。

单元测试更多是由开发主导的,开发领导的态度就决定了运行的效果。

UI 测试更加关注模块集成后的联动逻辑,是集成测试最有效的手段。一方面,现代软件架构无论是分层还是服务调用模式,对接口的依赖程度都大大增加。另一方面,与单元测试相比,接口测试调用的业务逻辑更加完整,并且具备清晰的接口定义,适合采用自动化的方式执行。

自动化测试的开发

对于企业的实际业务来说,不仅需要单接口的执行,还需要相对复杂的多接口,而且带有逻辑的执行,这就依赖于调用接口的编排能力,甚至是内建的 Mock 服务。

不仅如此,测试数据、用例、脚本的管理,测试过程中数据的收集、度量、分析和展示,以及测试报告的发送等,都是一个成熟的自动化测试框架应该具备的功能。

自动化测试结果分析

当前比较常用的方式是覆盖率,不过问题是,测试覆盖率提升就能发现更多的缺陷吗?在这么高的覆盖率基础上,自动化测试发现的问题占比仅仅在 5% 左右。那么,花了这么大力气建设的自动化测试,最后仅仅发现了 5% 的有效问题,这是不是说明自动化测试的投入产出比不高呢?实际上,说自动化测试是为了发现更多的缺陷,这是一个典型的认知误区。在实际项目中,手工测试发现的缺陷数量要比自动化测试发现的缺陷数量多得多。

自动化测试更多是在帮助守住软件质量的底线,尤其是应用在回归测试中,自动化测试可以确保工作正常的已有功能不会因为新功能的引入而带来质量回退。可以这么说,如果自动化测试覆盖率足够高,那么软件质量一定不会差到哪儿去。

自动化测试误报率 = 非开发变更引入的问题用例数量 / 测试失败的用例数量

测试误报率是体现自动化测试稳定性的一个核心指标。
要如何解决测试误报率高呢?依赖于自动化测试结果的分析。

对自动化测试的问题进行分类。你要弄清楚一次失败是环境问题、网络问题、功能变更,还是系统缺陷?你需要将失败的用例归纳到这些分类之中。

当一个类别的问题非常多的时候,你可以考虑进行拆分,比如网络问题,你可以拆分为网络不可达、延迟超时、域名解析错误等等。

增加已有分类的自动识别能力。比如,对于捕获到的常见异常,可以根据异常信息自动上报到对应的错误分类,从而简化人工识别和归类错误的工作量。

提升自动化测试工具和环境的健壮性,对已知问题增加一定的重试机制。持续积累和丰富错误分类,有针对性地开展改进工作,从而不断提升自动化测试的稳定性。

14 | 内建质量:丰田和亚马逊给我们的启示

不应该将质量依赖于检验工作,因为检验工作既昂贵,又不可靠。最重要的是,检验工作并不直接提升产品质量,只是为了证明质量有缺陷。而正确的做法是将质量内建于整个流程之中,并通过有效的控制手段来证明流程自身的有效性。

因为测试只能基于已知的产品设计进行验证,但那些潜在的风险有可能连开发自己都不知道。

另外,由于测试存在的意义在于发现更多的缺陷,有些团队的考核指标甚至直接关联缺陷提交数量,以及缺陷修复数量。那么,这里的前提就是假设产品是存在缺陷的。于是,测试团队为了发现问题而发现问题,在研发后面围追堵截,这也造成了开发和测试之间的隔阂和对立,这显然不是 DevOps 所倡导的状态。

关于内建质量,有个经典的案例就是丰田公司的安灯系统,也叫作安灯拉绳。丰田的汽车生产线上方有一条绳子,如果生产线上的员工发现了质量问题,就可以拉动安灯系统通知管理人员,并停止生产线,以避免带有缺陷的产品不断流向下游其实,这背后的理念就是“Fail fast”,即快速失败。如果工人发现了有缺陷的产品,却要经过层层审批才能停止生产线,就会有大量带有缺陷的产品流向下游,所以,停止生产线并不是目的,及时发现问题和解决问题才是目的。内建质量扭转了看待产品质量的根本视角,也就是说,团队所做的一切不是为了验证产品存在问题,而是为了确保产品没有问题。

内建质量有两个核心原则

  1. 问题发现得越早,修复成本就越低;
  2. 质量是每个人的责任,而不是质量团队的责任。

在软件交付的各个环节中注入质量控制的能力。

  • 在需求环节,可以定义清晰的需求准入规则,比如需求的价值衡量指标是否客观、需求的技术可行性是否经过了验证、需求的依赖是否充分评估、需求描述是否清晰、需求拆分是否合理、需求验收条件是否明确等等。通过前置需求质量控制,可以减少不靠谱的需求流入。在很多公司,“一句话需求”和“老板需求”是非常典型的例子。由于没有进行充分沟通,研发就跟着感觉走,结果交付出来的东西完全不是想要的,这就带来了返工浪费。
  • 在开发阶段,代码评审和持续集成就是一个非常好的内建质量的实践。在代码评审中,要尽量确认编码是否和需求相匹配,业务逻辑是否清晰。另外,通过一系列的自动化检查机制,来验证编码风格、风险、安全漏洞等。

从实践的角度来说,每个环节都可以控制质量,那么,我们要优先加强哪个环节呢?研发环节作为整个软件产品的源头,是内建质量的最佳选择。

内建质量的实施步骤

第一步:选择适合的检查类型
以持续集成阶段的代码检查为例,除了有单元测试、代码风格检查、代码缺陷和漏洞检查、安全检查等等,还有各种各样的检查工具。但实际上,这些并不是都需要的。至少在刚开始实践的时候,如果一股脑全上,那么研发基本上就不用干活了。所以,选择投入产出比相对比较高的检查类型,是一种合理的策略。

第二步:定义指标并达成一致确定检查类型之后,就要定义具体的质量指标了。质量指标分两个层面,一个是指标项,一个是参考值指标项是针对检查类型所采纳的具体指标,比如单元测试覆盖率这个检查项,可采纳的指标就包括行、指令、类、函数等。那么,我们要以哪个为准呢?这个一般需要同研发负责人达成一致,并兼顾行业的一些典型做法,比如单测行覆盖率就是一个比较好的选择。
质量门禁就类似一道安全门,通过门禁时进行检查,如果不满足指标,则门禁报警,禁止通过。这就跟交警查酒驾一样,酒精含量如果超过一定的指标,就会触发报警。参考值的定义是一门艺术。对于不同的项目,甚至是同一个项目的不同模块来说,我们很难用“一刀切”的方式定义数值。我比较推荐的做法是将静态指标和动态指标结合起来使用。静态指标就是固定值,对于漏洞、安全等问题来说,采取零容忍的态度,只要存在就绝不放过。而动态指标是以考查增量和趋势为主。

第三步:建立自动化执行和检查能力按照快速失败的原则,质量门禁的生效节点要尽量靠近指标数据的产生环节。比如,如果要检查编码风格,最佳的时间点是在研发本地的 IDE 中进行,其次是在版本控制系统中进行并反馈结果,而不是到了最后发布的时间点再反馈失败。

现代持续交付流水线平台都具备质量门禁的功能,常见的配置和生效方式有两种:在持续交付平台上配置规则,也就是不同指标和参考值组合起来,形成一组规则,并将规则关联到具体的执行任务中。这样做的好处是,各个生成指标数据的子系统只需要将数据提供给持续交付平台就行了,至于门禁是否通过,完全依靠持续交付平台进行判断。另外,一般配置规则的都是质量人员,提供这样一个单独的入口,可以简化配置成本。具体的实现逻辑,如图所示:

在各个子系统中配置质量门禁。比如,在 UI 自动化测试平台上配置门禁的指标,当持续交付平台调用 UI 自动化测试的时候,直接反馈门禁判断的结果。如果检查不通过,则流水线直接失败。

第四步:定义问题处理方式
在实际执行的过程中,质量门禁的结果可能存在多种选项,比如失败、告警、人工确认等。这些都需要在制定规则的时候定义清楚,通过一定的告警值和人工确认方式。

第五步:持续优化和改进

15 | 技术债务:那些不可忽视的潜在问题

技术债务,就是指团队在开发过程中,为了实现短期目标选择了一种权宜之计,而非更好的解决方案,所要付出的代价。

这个代价就是团队后续维护这套代码的额外工作成本,并且只要是债务就会有利息,债务偿还得越晚,代价也就越高。带来技术债务的原因有很多,除了压力之下的快速开发之外,还包括不明真相的临时解决方案、新员工技术水平不足,和历史债务累积下来的无奈之举等。总之,代码维护的时间越长,引入的技术债务就会越多,从而使团队背上沉重的负担。

如何对代码的技术债务进行分类呢?

我们可以借用“Sonar Code Quality Testing Essentials”一书中的代码“七宗罪”,也就是复杂性、重复代码、代码规范、注释有效性、测试覆盖度、潜在缺陷和系统架构七种典型问题。

除了低质量的代码问题之外,还有很多其他类型的技术债务,比如不合理的架构、过时的技术、冷门的技术语言等等。

如何量化技术债务?

目前业界比较常用的开源软件,就是 SonarQube。在 SonarQube 中,技术债是基于 SQALE 计算出来的。关于SQALE,全称是 Software Quality Assessment based on Lifecycle Expectations,一种开源算法。
计算出来的技术债务会因为开启的规则数量和种类的不同而不同。级别的算法完全是基于技术债务比例得来的。简单来说,就是根据当前代码的行数,计算修复技术债务的时间成本和完全重写这个代码的时间成本的比例。在极端情况下,一份代码的技术债务修复时长甚至比完全推倒重写还要长,这就说明代码已经到了无法维护的境地。所以在具体实践的时候,也会格外重视代码的 SQALE 级别的健康程度。

技术债务比例 = 修复已有技术债务的时间 / 完全重写全部代码的时间

如果你想知道评级的计算方法,也可以层层展开,查看详细的数据。比如,持续集成能力,它是由持续集成频率、持续集成时长、持续集成成功率、问题修复时长等多个指标共同组成的。如果在度量过程中,你发现持续集成的整体评分不高,就可以点击进去查看每个指标的数据和状态,以及详细的执行历史。这种数据关联和下钻的能力对构建数据度量体系而言非常重要。

想解决技术债务,有哪些步骤呢?

在解决技术债务的过程中,要遵循 4 条原则。

  • 共识:团队内部要对技术债务的危害、解决项目的目标、规则的选择和制定达成一致意见。

  • 可见:通过搭建开源的 Sonar 平台,将代码扫描整合进持续交付流水线中,定期或者按需执行,让技术债务变得可视化和可量化。不仅如此,Sonar 平台还能针对识别出来的问题,给出建议的解决方法,这对于团队快速提升编码水平,大有帮助。

  • 止损:针对核心业务模块,对核心指标类型,比如 vulnerability,缺陷的严重和阻塞问题设定基线,也就是控制整体数量不再增长。

  • 改善:创建技术优化需求,并在迭代中留出一定的时间修复已有问题,或者采用集中突击的方式搞定大头儿,再持续改进。

在刚开始解决技术债务的时候,最大的问题不是参考指标太少,而是太多了。所以团队需要花大量时间来 Review 规则。关于这个问题,两条建议:

第一,参考代码质量平台的默认问题级别。一般来说,阻塞和严重的问题的优先级比一般问题更高,这也是基于代码质量平台长时间的专业积累得出的结论。

第二,你可以参考业界优秀公司的实践经验,比如很多公司都在参考阿里巴巴的 Java 开发手册,京东也有自己的编码规约。

16 | 环境管理:一切皆代码是一种什么样的体验?

环境管理的挑战

  1. 环境种类繁多。

    软件关联的环境种类越来越多,比如开发环境、测试环境、UAT 用户验收测试环境、预发布环境、灰度环境、生产环境等。

  2. 环境复杂性上升现代应用的架构逐渐从单体应用向微服务应用转变。

    随着服务的拆分,各种缓存、路由、消息、通知等服务缺一不可,任何一个地方配置出错,应用都有可能无法正常运行。这还不包括各种服务之间的依赖和调用关系,这就导致很多企业部署一套完整环境的代价极高,甚至变成了不可能完成的任务。

  3. 环境一致性难以保证。

  4. 环境交付速度慢由于职责分离

    环境的申请流程一般都比较冗长。

  5. 环境变更难以追溯

基础设施即代码就是用一种描述性的语言,通过文本管理环境配置,并且自动化完成环境配置的方式。

典型的就是以 CAPS 为代表的自动化环境配置管理工具,也就是 Chef、Ansible、Puppet 和 Saltstacks 四个开源工具的首字母缩写。通过将所有环境的配置过程代码化,每个环境都对应一份配置文件,可以实现公共配置的复用。

其次,环境的配置过程,完全可以使用工具自动化批量完成。

最后,既然环境配置变成了代码,自然可以直接纳入版本控制系统中进行管理,享受版本控制的福利。任何环境的配置变更都可以通过类似 Git 命令的方式来实现,不仅收敛了环境配置的入口,还让所有的环境变更都完全可追溯。当版本控制系统遇上基础设施即代码,就形成了一种绝妙的组合,那就是 GitOps。

基础设施即代码的实践,通过人人可以读懂的代码将原本复杂的技术简单化,这样一来,即便是团队中不懂运维的角色,也能看懂和修改这个过程。这不仅让团队成员有了一种共同的语言,还大大减少了不同角色之间的依赖,降低了沟通协作成本。

开发运维打通的 GitOps 实践

GitOps 就是基于版本控制系统 Git 来实现的一套解决方案,核心在于基于 Git 这样一个统一的数据源,通过类似代码提交过程中的拉取请求的方式,也就是 Pull Request,来完成应用从开发到运维的交付过程,让开发和运维之间的协作可以基于 Git 来实现。

虽然 GitOps 最初是基于容器技术和 Kubernetes 平台来实现的,但它的理念并不局限于使用容器技术,实际上,它的核心在于通过代码化的方式来描述应用部署的环境和部署过程。

生成一个包含全部工具依赖的 Docker 镜像,并分发给开发团队。在开发时仅需要拉起一个容器,将代码目录挂载进去,就可以生成一个完全标准化的研发环境。当工具版本升级时,可以重新制作一个新的镜像,开发本地拉取后,所有的工具就升级完成了,这大大简化了研发环境的维护成本。
在 Dockerfile 中,环境配置部分同样采用 Ansible 的方式完成。
KSync 可以建立本地工作空间和远端容器目录的关联,并自动同步代码。谷歌也开源了一套基于容器开发自动部署工具Skaffold.

17 | 部署管理:低风险的部署发布策略

部署是一组技术实践,表示通过技术手段,将本次开发测试完成的功能实体(比如代码、二进制包、配置文件、数据库等)应用到指定环境的过程,包括开发环境、预发布环境、生产环境等。部署的结果是对服务器进行变更,但是这个变更结果不一定对外可见。

发布,也就是 Release,更偏向一种业务实践,也就是将部署完成的功能正式生效,对用户可见和提供服务的过程。

要在保障一定的质量水平的前提下,尽量加快发布节奏,并通过低风险发布手段,以及线上测试和监控能力,尽早地发现问题,并以一种最简单的手段来快速恢复。

这里面有几个关键词:一定的质量水平,低风险发布手段,线上测试和监控,以及快速恢复。测试能力的向前、向后延伸,一方面,提供了工具和平台以帮助开发更容易地进行自测;另一方面,加强针对线上监控埋点等类型的测试,可以保证线上问题可以快速暴露,正常获取辅助分析用户行为的数据,这会全面提升整体的发布质量。

低风险的发布手段
典型的包括以下几种:

  1. 蓝绿部署

    为应用准备两套一模一样的环境,一套是蓝环境,一套是绿环境,每次只有一套环境提供线上服务。这里的蓝和绿,只是用于区分两套环境的标志而已。在新版本上线时,先将新版本的应用部署到没有提供线上服务的环境中,进行上线前验证,验证通过后就达到了准备就绪的状态。在发布时间点,只要将原本指向线上环境的路由切换成另外一套环境,整个发布过程就完成了。一般来说,这种方式的实现成本比较高。

  2. 灰度发布,也叫金丝雀发布。

    与蓝绿部署相比,灰度发布更加灵活,成本也更低,所以,在企业中是一种更为普遍的低风险发布方式。灰度发布有很多种实现机制,最典型的就是采用一种渐进式的滚动升级来完成整个应用的发布过程。当发布新版本应用时,根据事先设计好的灰度计划,将新应用部署到一定比例的节点上。当用户流量打到这部分节点的时候,就可以使用新的功能了。

  3. 暗部署

    随着 A/B 测试的兴起,暗部署的方式也逐渐流行起来。所谓暗部署,就是在用户不知道的情况下进行线上验证的一种方法。

该如何做线上验证呢?

  1. 采用灰度发布、用户众测等方式

    逐步观察用户行为并收集用户数据,以验证新版本的可用性是否符合预期。这里的主要实践之一就是埋点功能。

  2. 用户反馈。用户运营和舆情监控系统
    用于按照“关键字”等自动爬取各个主流渠道的产品信息。一旦发现负面的反馈,就第一时间进行止损。

18 | 混沌工程:软件领域的反脆弱

什么是混沌工程?

简单来说,混沌工程要解决的,就是复杂环境下的分布式系统的反脆弱问题。尽可能在这些故障和缺陷发生之前,通过一系列的实验,在真实环境中验证系统在故障发生时的表现。故障演练就是针对以往发生过的问题进行有针对性地模拟演练。通过事先定义好的演练范围,然后人为模拟事故发生,触发应急响应预案,快速地进行故障定位和服务切换,并观察整个过程的耗时和各项数据指标的表现。

全链路压测对于一次完整的压测来说,大致的过程是这样的:

首先,准备压测计划,调试压测脚本和环境,对压测容量和范围进行预估;

然后,为了保证线上流量不受影响完成机房线路切换,确保在压测过程中没有线上真实流量的引入;

接着,根据预定义的压测场景执行压测计划,观察流量峰值并动态调整;

最后,在压测完成后,再次进行流量切换并汇总压测结果,识别压测问题。在压测过程中,除了关注 QPS 指标之外,还要关注 TP99、CPU 使用率、CPU 负载、内存、TCP 连接数等,从而客观地体现出大流量下服务的可用性。

从业务层面来说,面对多变的环境因素,完善的服务降级预案系统兜底机制也是必不可少的。
Netflix 公司著名的“混乱猴子(Chaos Monkey)”,就是用来随机关闭生产环境的实例的工具。

在引入混沌工程的实践之前,首先需要确保现有的服务已经具备了弹性模式,并且能够在应急响应预案和自动化工具的支撑下尽早解决可能出现的问题。

19 | 正向度量:如何建立完整的DevOps度量体系?

DevOps 希望做到的就是持续、快速和高质量的价值交付。价值可以是一个功能特性,可以是用户体验的提升,也可以是修复阻塞用户的缺陷。

好的指标大多具备一些典型的特征。

  1. 明确受众。
  2. 直指问题。
  3. 量化趋势。按照 SMART 原则,好的指标应该是可以衡量的,而且是可以通过客观数据来自证的。
  4. 充满张力。指标不应该孤立存在,而是应该相互关联构成一个整体。好的指标应该具有一定的张力,向上可以归并到业务结果,向下可以层层分解到具体细节。

定义指标有哪些原则?

  • 全局指标优于局部指标

  • 综合指标优于单一指标

  • 结果指标优于过程指标

  • 团队指标优于个人指标

  • 灵活指标优于固化指标

哪些指标最重要?

如何开启度量工作?

  • 第 1 步:细化指标。

    一个完整的指标,除了定义之外,还需要明确指标名、指标描述、指标级别(团队级 / 组织级)、指标类型、适用场景范围及目标用户、数据采集方式和标准参考值。

  • 第 2 步:收集度量数据。

  • 第 3 步:建立可视化平台。

  • 第 4 步:识别瓶颈并持续改进。度量是把双刃剑,做得不好反而会伤害团队的士气。如果本末倒置,把度量结果跟个人的绩效相绑定,就很容易使度量这个事情变了味道。很多大公司反反复复地在建立度量体系,就是因为前一个体系被人摸透,变成了数字游戏,于是就失去了原有的目的,只能推倒重来。还是那句话,度量只是一种手段,而非目的。

20 | 持续改进:PDCA体系和持续改进的意义

始终能够找到新的突破,持续追求更好的状态。
每家公司面临的问题都不一样,从 0 到 1 的过程相对比较简单,可以对照着工程实践,快速地引入工具,建立流程,补齐能力短板。但是,从 1 到 N 的过程,就需要团队根据业务需要,自行识别改进目标了。
这就需要有团队来负责收集和总结这些常见的错误,并提取关键错误信息和常见解决方法,形成一个案例库。同时,在构建系统中嵌入一个自动化服务,下次再有人遇到编译错误的时候,就可以自动匹配案例库,并给他推送一个问题分析报告和解决建议,帮助团队成员快速解决问题。

平台工具篇

21 | 开源还是自研:企业DevOps平台建设的三个阶段

DevOps 平台的产品与业务方向的产品不同,它要解决的就是一线研发交付团队的实际问题。普通的产品经理没有研发交付的背景,很难理解研发交付的困境,而研发交付团队又缺少产品经理的技能和思路。所以,这个领域的人才少之又少,基本只能靠内部培养。

当企业决定引入 DevOps 工具的时候,无外乎有三种选择:

  1. 直接使用开源工具;
  2. 采购商业工具;
  3. 自己研发工具。

DevOps 平台建设的三个阶段。

  • 阶段一:从无到有引入开源工具和商业工具,快速补齐现有的能力短板。

    核心原则就是选择主流工具。需求管理工具 Jira;知识管理工具 Confluence;版本控制系统 GitLab;持续集成工具 Jenkins;代码质量工具 SonarQube;构建工具 Maven/Gradle;制品管理 Artifactory/Harbor;配置管理工具 Ansible;配置中心 Apollo;测试工具 RF/Selenium/Appium/Jmeter/TestNG;安全合规工具 BlackDuck/Fortify;

  • 阶段二:从小到大使用半自建工具和定制商业工具,来解决自己的问题。

    半自建工具有哪些注意事项呢?,主要有两点:设计时给扩展留出空间;实现时关注元数据治理。

  • 阶段三:从繁到简。

我们要解决的主要问题有 3 点:

  1. 平台太多。

    做一件事情,需要各种切来切去;

  2. 平台太复杂。

    想要实现一个功能,需要对相关人员进行专业培训,他们才能做对;

  3. 平台价值说不清。

    比如,使用平台,能带来多大价值?能给团队和业务带来多大贡献?

对于这个阶段,建议是:

  • 使用整合工具来化繁为简,统一界面,简化操作,有效度量。
  • 区分平台和工具,让平台脱颖而出。所谓自服务,就是用户可以自行登录平台实现自己的操作,查看自己关心的数据,获取有效的信息。

企业要建设 DevOps 平台,有什么经验总结吗?回答是“四化”:标准化、自动化、服务化和数据化。实际上,这些也是指导平台建设的核心理念。

  • 标准化:一切皆有规则,一切皆有标准;
  • 自动化:干掉一切不必要的手工操作环节,能一键完成的,绝不操作两次;
  • 服务化:面向用户设计,而不是面向专家设计,让每个人都能在没有外界依赖的前提下,完成自己的工作;
  • 数据化:对数据进行收集、汇总、分析和展示,让客观数据呈现出来,让数据指导持续改进。

22 | 产品设计之道:DevOps产品设计的五个层次

DevOps 产品设计体验的五个层次:战略存在层、能力圈层、资源结构层、角色框架层和感知层。

  • 第一个层次:战略存在层同类产品的经验并不能作为自己产品的战略。

    要把战略建立在不变的事物上。而是始终着眼于那些长久不变的事物之上,也就是多、快、好、省。效率、质量、成本和安全。

  • 第二个层次:能力圈层主航道和护城河理论挂在嘴边。

    所谓主航道,就是产品的核心能力,直接反射了产品战略的具体落地方式。对于流水线产品来说,这个能力来源于对软件交付过程的覆盖,而不论你将来开发任何产品,这条主路径都是无法回避的。那么,产品就有了茁壮成长的环境和土壤。而护城河就是你这个产品的不可替代性,或者是为了替代你的产品需要付出的高额代价。

  • 第三个层次:资源结构层产品蕴含的资源除了这些看得见、摸得着的机器以外,还有很多方面,比如,硬实力方面的,像速度快、机器多、单一领域技术沉淀丰富,又比如,强制性的,像审批入口、安全规则,还有软性的用户习惯,数据积累等等。

  • 第四个层次:角色框架层不要让你的产品只有专业人士才会使用。

  • 第五个层次:感知层不可否认,这是一个看脸的时代,但是产品终究是给人用的,而不是给人看的。所以,很多人甚至强调,对于内部产品来说,UI 完全不重要,家丑不外扬就好了。

23/4 | 持续交付平台:现代流水线必备的十大特征

  • 特性一:打造平台而非能力中心
    持续交付流水线平台和垂直业务平台分开,并定义彼此的边界。所谓的垂直业务平台,就是指单一专业领域的能力平台,比如自动化测试平台、代码质量平台、运维发布平台等等,这些也是软件交付团队日常打交道最频繁的平台。流水线平台只专注于流程编排、过程可视化,并提供底层可复用的基础能力。垂直业务平台则专注于专业能力的建设、一些核心业务的逻辑处理、局部环节的精细化数据管理等。
    流水线平台仅作为任务的调度者、执行者和记录者,并不需要侵入垂直业务平台内部。

  • 特性二:可编排和可视化

    所谓的流程可编排能力,就是指用户可以自行定义软件交付过程的每一个步骤,以及各个步骤之间的先后执行顺序。编排的前提是系统提供了可编排的对象,这个对象一般称为原子。原子的设计是流水线平台的精髓,因为原子体现了平台的通用性、可复用性和独立性。

  • 特性三:流水线即代码
    流水线代码化的好处不言而喻:借助版本控制系统的强大功能,流水线代码和业务代码一样纳入版本控制系统,可以简单追溯每次流水线的变更记录。。甚至是,在版本的 Release Notes 中也增加流水线、环境的变更记录信息。一旦发生异常,这些信息会大大提升问题的定位速度。

  • 特性四:流水线实例化
    作为软件交付流程的建模,流水线跟面向对象语言里面的类和实例非常相似。一个类可以初始化多个对象,每个对象都有自己的内存空间,可以独立存在,流水线也要具备这种能力。首先,流水线需要支持参数化执行。其次,流水线的每一次执行,都可以理解为是一个实例化的过程。最后,流水线需要支持并发执行能力。

  • 特性五:有限支持原则

    流水线的设计目标,应该是满足大多数、常见场景下的快速使用,并提供一定程度的定制化可扩展能力,而不是满足所有需求。

  • 特性六:流程可控

    流水线的主要作用是驱动软件交付过程的效率提升和状态可视化。其实,流水线是要覆盖端到端的流程,但这并不是说,一定要有一条流水线跑通从代码提交开始到软件发布为止的全流程。实际上,在企业中,往往是多条流水线覆盖不同的环节,比如开发阶段流水线、集成阶段流水线,以及部署阶段流水线。这些流水线一起覆盖了整个软件交付流程。

  • 特性七:动静分离配置化

    将需要频繁调整或者用户自定义的内容,保存在一个静态的配置文件中。然后,系统加载时通过读取接口获取配置数据,并动态生成用户可见的交互界面。
    定义一个通用的数据结构是设计标准化的系统的最佳实践。

  • 特性八:快速接入
    在建设流水线平台的时候,能否快速地实现外部平台能力的接入,就成了一个必须要解决的问题。经典的解决方式就是提供一种插件机制,来实现平台能力的接入。自动化生成平台关联的原子代码。首先,流水线平台需要定义一套标准的接入方式。以接口调用类型为例,接入平台需要提供一个任务调用接口、一个状态查询接口以及一个结果上报接口。

  • 特性九:内建质量门禁

    要完成质量规则制定、门禁数据收集和检查,以及门禁结果报告的完整闭环。

  • 特性十:数据采集聚合

    满足用户对最基本的结果数据的查看需求。

25 | 让数据说话:如何建设企业级数据度量平台?

对于不同的元数据平台,数据获取的方式也是千差万别的。

挑战一:大量数据源平台对接,如何从这些种类繁多的平台中提取有用的数据,并且保证数据源接入的隔离性,做到灵活接入呢?我给你的建议还是采用流水线设计的思路,那就是插件化,只不过,这次要实现的插件是数据采集器。

挑战二:海量数据存储分析第一个典型特征就是数据量大。
挑战三:度量视图的定制化显示。

26 | 平台产品研发:三个月完成千人规模的产品要怎么做?

27 | 巨人的肩膀:那些你不能忽视的开源工具

28 | 迈向云端:云原生应用时代的平台思考

云原生的来自于 CNCF 的官方定义:Cloud native computing uses an open source software stack to deploy applications as microservices, packaging each part into its own container, and dynamically orchestrating those containers to optimize resource utilization.

总结一下这里面的关键字:开源软件、微服务应用、容器化部署和动态编排。那么,简单来说,云原生应用就是将微服务风格的架构应用,以容器化的方式部署在云平台上。

DevOps 实战笔记--学习笔记记录

https://www.chuxin911.com/devops_practice_note_20220407/

作者

cx

发布于

2022-04-07

更新于

2022-07-16

许可协议