专栏首页yeedomliu《持续交付:发布可靠软件的系统方法》第5章 部署流水线

《持续交付:发布可靠软件的系统方法》第5章 部署流水线

第5章 部署流水线

5.1 引言

  • 持续集成的主要关注对象是开发团队。持续集成系统的输出通常作为手工测试流程和后续发布流程的输入。在软件的发布过程中,很多浪费来自于测试和运维环节。我们常常看到:
    • 构建和运维团队的人员一直在等待说明文档或缺陷修
    • 测试人员等待“好的”版本构建出来
    • 在新功能开发完成几周之后,开发团队才能收到缺陷报告
    • 开发快完成时,才发现当前的软件架构无法满足该系统的一些非功能需求。
  • 解决方案就是采取一种更完整的端到端的方法来交付软件。我们已经解决了配置管理以及自动化大量构建、部署、测试和发布流程的很多问题。现在,我们通常能通过一键式方式把软件的某个版本部署好,甚至可以将其一键式部署到生产环境中,这样就建立了一个非常有效的反馈环

5.2 什么是部署流水线

  • 从某种抽象层次上讲,部署流水线是指软件从版本控制库到用户手中这一过程的自动化表现形式。将客户或用户脑中的一个想法变成其手中真实可用的特性”这一过程的一部分,而整个流程(从概念到概念兑现)可以用一个价值流图来描述
  • 要理解部署流水线以及代码变更在其上流动的方法,是把它看成一个序列图2
  • 请注意,流水线的输入是版本控制中的某个具体版本。每次变更都会生成一次构建,这个构建像神话中的英雄一样,闯过一系列的测试,希望成为一个能到达生成环境中的发布版本。在这一系列的测试阶段中,每个阶段都从不同的角度评估这个构建版本,且和持续集成一样,它的起点是向版本控制库的每一次提交。

最基本的部署流水线

  • 最后,一定要记住,我们所做的这一切都是为了尽快得到反馈。为了加速这个反馈循环,就必须能够看到每个环境中都部署了哪个版本,每个构建版本在流水线中处于哪个阶段
  • 要能够将某次代码提交、构建版本与其在部署流水线上通过了哪些阶段关联在一起,这一点是非常必要的。因为这样你就能立刻发现是哪次代码提交造成了本次验收测试的失败。

5.3 部署流水线的相关实践

5.3.1 只生成一次二进制包

  • 方便起见,我们将所有可执行代码的集合称作二进制包,例如Jar文件、.NET 程序集和.so文件。有时候代码根本不需要编译,那么这种情况下,二进制包就是指所有源文件的集合。
  • 所以一旦创建了二进制包,在需要时最好是重用,而不是重新创建它们。

为什么二进制包应该具有环境无关性

  • 为每个环境都创建一个二进制包是一种不好的做法。尽管这种方法比较常见,但的确存在几个严重的缺点,不利于部署的灵活性、方便性和系统的可维护性,

5.3.2 对不同环境采用同一部署方式

  • 为了确保构建和部署流程被有效测试,在各种环境中使用相同流程对软件进行部署是非常必要的,这些环境即包括开发人员或分析人员的工作站,也包括测试环境和生产环境。
  • 首先,确保在每个环境上都使用同样的流程来部署;然后一点儿一点儿地把它自动化,直至全部自动化。最终,整个部署过程应该只需要你在部署开始前指定一个目标环境,以及所要部署的程序版本就可以了。

5.3.3 对部署进行冒烟测试

  • 当做应用程序部署时,你应该用一个自动化脚本做一下冒烟测试,用来确保应用程序已经正常启动并运行了。这个测试应该非常简单,比如只要启动应用程序,检查一下,能看到主页面,并在主页面上能看到正确的内容就行了。
  • 一旦有了单元测试之后,这种冒烟测试(部署测试)可能就是你要马上着手做的最重要测试了,甚至可以说是最最重要的测试。

5.3.4 向生产环境的副本中部署

  • Puppet、InstallShield

5.3.5 每次变更都要立即在流水线中传递

  • 部署流水线则使用了不同的方式:每次提交都要触发第一个阶段的执行,后续阶段在第一个阶段成功结束后,立即被触发

5.3.6 只要有环节失败,就停止整个流水线

  • 对于团队来说,最重要的是要接受这样的思想:每次提交代码到版本控制系统中后,都能够构建成功并通过所有的测试。假如在某个环境上的某次部署失败了,整个团队就要对这次失败负责,应该停下手头的工作,把它修复后再做其他事情。

5.4 提交阶段

  • 提交阶段,我们需要做以下几件事。这些任务通常作为一个工作集合运行在构建网格上(大多数持续集成服务器都提供类似功能),这样,提交阶段就能够在一个可接受的时间之内完成(最好在五分钟之内完成,最多不能超过十分钟)。一般来说,提交阶段包含以下步骤:
    • 编译代码(如果所用开发语言需要的话)
    • 运行一套提交测试
    • 为后续阶段创建二进制包
    • 执行代码分析来检查代码的健康状况
    • 为后续阶段做准备工作,比如准备一下后续测试所用的数据库。
  • 第一步是编译源代码的最新版本。如果在编译过程中出现错误,就向在最后一次提交成功之后提交代码的所有人发送通知。
  • 接着,运行一套测试集合。最好优化一下,让它运行得飞快。之所以把这一套测试称为提交阶段的测试,而不是单元测试,原因在于虽然这套测试集中大部分都是单元测试,但同时能够包含一小部分其他类型的测试是非常有用的。
  • 收集一些关于当前代码库的测试覆盖率、可维护性以及安全漏洞方面的信息。为这些度量项设定一个阈值,并像对待测试一样,一旦不满足阈值条件,就让提交阶段失败。比较有用的度量项包括:
    • 测试覆盖率(如果提交测试只覆盖了代码库的5%,那么这些测试发挥不了太大的作用)
    • 重复代码的数量
    • 圈复杂度(cyclomatic complexity)
    • 输入耦合度(afferent coupling)和输出耦合度(efferent coupling)
    • 编译警告的数量
    • 代码风格

提交阶段最佳实践

  • 如果它失败了,开发人员要么快速修复问题,要么将刚提交的代码回滚。
  • 即使在开发过程中只有提交阶段,这也在产品可靠性和质量方面迈出了巨大一步。然而,只有再实现几个必需的阶段后,才能算得上是最基本的部署流水线。

5.5 自动化验收测试之门

  • 全面的提交测试套件对于发现许多种错误来说,是非常优秀的试金石。然而,有很多类型的错误是它无法捕获的。
  • 验收测试阶段的目标是断言应用程序交付了客户期望的价值,并满足了验收条件。它也是一个回归测试套件,用于验证新的修改是否在现有功能中引入了回归缺陷。
  • 这个自动化验收测试关卡是识别候选发布版本过程中第二个重要的里程碑。部署流水线只允许后续阶段(比如需要手工干预的手工部署阶段)获取那些已通过自动化验收测试的构建版本。

自动化验收测试最佳实践

  • 实际上,就像整个团队负责流水线的每一个阶段一样,整个团队都是验收测试的所有者。如果验收测试失败了,整个团队都要停下来,马上修复它。
  • 这一实践的一个重要推论是,开发人员必须能在自己的开发环境中运行自动化验收测试。这样,开发人员在发现验收测试失败后,就很容易在自己的机器上修复它,然后在本地再次运行验收测试来验证修复。
  • 尽管验收测试非常有价值,但它们的创建和维护成本也是非常高的。所以要时刻牢记,自动化验收测试也是回归测试。不要幼稚地对照着验收测试条件,盲目地把所有东西都自动化了。

5.6 后续的测试阶段

  • 但对于很多系统来说,即使有非常全面的自动化测试集合,在发布之前,仍需要某种形式的手工测试

5.6.1 手工测试

  • 测试人员会做一些机器不太擅长而人比较擅长的测试。他们做探索性测试、易用性测试,在不同平台上测试程序的界面是否正确,并着眼于一些不可控制的最坏情况进行测试。自动化验收测试使测试人员节省出更多的时间做那些高价值的活动,而不是测试脚本的人力执行器。

5.6.2 非功能测试

  • 根据我们的经验,如果需要的话,完全可以在部署流水线中创建一个阶段,用于运行这些自动化的非功能测试。
  • 对于高性能应用来说,可以在验收测试阶段通过之后,就运行容量测试,作为该版本整个自动化测试的输出结果。如果这个版本不能通过容量测试,就不能把它看成是可部署的版本。

5.7 发布准备

  • 把这个发布环节视为部署流水线的一个自然结果
  • 我们只需要:
    • 让参与项目交付过程的人共同创建并维护一个发布计划(包括开发人员和测试人员,以及运维人员,基础设施和支持人员)
    • 通过尽可能多的自动化过程最小化人为错误发生的可能性,并从最容易出错的环节开始实现自动化
    • 在类生产环境中经常做发布流程演练,这样就可以对这个流程及其所使用的技术进行调试
    • 如果事情并没有按计划执行,要有撤销某次发布的能力
    • 作为升级和撤销过程的一部分,制定配置迁移和数据迁移的策略。
  • 我们的目标是实现一个完全自动化的发布过程。

5.7.1 自动部署与发布

  • 通过自动化的环境准备和管理、最佳的配置管理实践以及虚拟化技术(如果适用的话),环境准备和维护的成本会显著降低。
  • 使用自动化部署与发布,交付流程就变成了很平常的事儿。

5.7.2 变更的撤销

  • 传统上,人们对新版本的发布常常存在着恐惧心理,原因有两个
    • 害怕引入问题,因为手工的软件发布过程很可能引入难以发现的人为错误,或者部署手册本身就隐藏着某个错误
    • 担心由于发布过程中的一个问题或新版本的某个缺陷,使你原来承诺的发布失败。
  • 通过每天练习发布多次来证明自动化部署系统是可以工作的,这样就可以缓解第一种问题。对于第二个问题,可以准备一个撤销策略。
  • 撤销流程绝不应该与部署流程、增量部署流程或回滚流程有什么不同。

5.7.3 在成功的基础上构建

  • 候选发布版本能够部署到生产环境时,我们就确信:
    • 代码可以编译
    • 代码能够按开发人员的预期运行,因为它通过了单元测试
    • 系统能够满足分析人员或用户预期,因为它通过了所有的验收测试
    • 基础设施的配置和基线环境被恰当地管理了,因为应用程序在模拟的生产环境上通过了测试
    • 系统所有的正确组件都就绪了,因为它是可以部署的
    • 部署脚本也是可以工作的,因为在该版本到这一阶段之前,部署脚本至少在开发环境中用过一次,在验收测试阶段用过一次,在测试环境中用过一次
    • 我们需要部署的所有内容都在版本控制库中,而且不需要手工干预,因为我们已经部署这个系统好几次了。

5.8 实现一个部署流水线

  • 建立一个完整流水线的策略。
    • 对价值流建模,并创建一个可工作的简单框架
    • 将构建和部署流程自动化
    • 将单元测试和代码分析自动化
    • 将验收测试自动化
    • 将发布自动化。

5.8.1 对价值流进行建模并创建简单的可工作框架

  • 第一步就是画出从提交到发布整个过程的价值流图。
  • 第二个阶段用来运行验收测试,第三个阶段用来向类生产环境部署应用,以便用它来做演示。
  • 首先,这些项目应该什么也不做,而只是作为可以被依次触发的占位符。如果是使用“最简单模型”,每当有人提交代码到版本控制系统时,就应该触发提交阶段。当提交阶段通过以后,验收测试阶段就应该被自动触发,并使用提交阶段刚刚创建的二进制包。

5.8.2 构建和部署过程的自动化

  • 实现部署流水线的第一步是将构建和部署流程自动化。构建过程的输入是源代码,输出结果是二进制包。“
  • 部署活动可能包含
    • (1) 为应用程序打包,而如果应用程序的不同组件需要部署在不同的机器上,就要分别打包
    • (2) 安装和配置过程应该实现自动化
    • (3) 写自动化部署测试脚本来验证部署是否成功了。部署流程的可靠性是非常重要的,因为它是自动化验收测试的前提条件。

5.8.3 自动化单元测试和代码分析

  • 开发部署流水线的下一步就是实现全面的提交阶段,也就是运行单元测试、进行代码分析,并对每次提交都运行那些挑选出来的验收测试和集成测试。
  • 它并不需要运行整个应用程序,只需要运行在一个xUnit风格的单元测试框架上。

5.8.4 自动化验收测试

  • 最好也保存一下应用程序的运行日志文件。如果应用程序有图形用户界面的话,也可以在验收测试运行时使用一个像Vnc2swf这样的软件来进行屏幕录像,这对于诊断问题比较有用。
  • 验收测试可分为两种类型:功能测试和非功能测试。在项目初期就开始非功能需求测试(比如测试容量和可扩展性等)是非常关键的,这样你就能得到一些数据,用来分析当前的应用程序是否满足这些非功能需求。

5.8.5 部署流水线的演进

  • 随着项目越来越复杂,价值流图也会演进。
  • 对于流水线来说,还有两个常见的外延:组件和分支。大型应用程序最好由多个组件拼装而成。在这样的项目中,每个组件都应该有一个对应的“迷你流水线”,

5.9 度量

  • 反馈是所有软件交付流程的核心。改善反馈的最佳方法是缩短反馈周期,并让结果可视化。你应该持续度量,并把度量结果以一种让人无法回避的方式传播出去,比如使用张贴在墙上的海报或者用一个专门的计算机显示器以大号粗体字显示结果,这些设备就是信息辐射器。
  • 重要的问题是:度量什么?选择什么样的度量项对团队行为有很大的影响。(这就是所谓的霍桑效应。)
  • 对于软件交付过程来说,最重要的全局度量指标就是周期时间(cycle time)。它指的是从决定要做某个特性开始,直到把这个特性交付给用户的这段时间。
  • 一旦知道了应用程序的周期时间,就能找到最佳办法来缩短它。
    • (1) 识别系统中的约束,也就是构建、测试、部署和发布这个流程中的瓶颈。
    • (2) 确保供应,即确保最大限度地提高流程中这部分的产出。
    • (3) 根据这一约束调整其他环节的产出,即其他资源都不会100%满负荷工作。
    • (4) 为约束环节扩容。如果周期时间还是太长(换句话说,第(2)步和第(3)步都没有什么太多的帮助),就要向该瓶颈环节增加资源了,
    • (5) 理顺约束环节并重复上述步骤,即在系统中找到下一个约束,并重复第(1)步。
  • 尽管周期时间是软件交付中最重要的度量项,但还有一些其他度量项可以对问题起到警报作用。
    • 自动化测试覆盖率
    • 代码库的某些特征,比如重复代码量、圈复杂度、输入耦合度、输出耦合度、代码风格问题等
    • 缺陷的数量。交付速度,即团队交付可工作、已测试过并可以使用的代码的速率
    • 每天提交到版本控制库的次数
    • 每天构建的次数。每天构建失败的次数
    • 每次构建所花的时间,包括自动化测试的时间。

5.10 小结

  • 部署流水线的目的是,让软件交付过程中的每个人都能够看到每个构建版本从提交到发布的整个过程。大家
  • 它应该能够支持人们执行到手工测试环境的一键式部署,并使大家能了解当前每个环境中运行的应用程序究竟是哪个版本,还能够支持一键式发布选定的某个版本,并清楚地标识出这一候选发布版本已成功通过整个流水线,
  • 一旦有了部署流水线,发布流程中的低效环节就会显而易见。

  • 《Lean Software Development: An Agile Toolkit》
  • 《Implementing Lean Software Development: From Concept to Cash》

工具

  • Puppet、InstallShield、Vnc2swf

本文分享自微信公众号 - yeedomliu(yeedom_liu),作者:yeedomliu

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-09-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 《持续交付:发布可靠软件的系统方法》第1章 软件交付的问题

    yeedomliu
  • 《持续交付:发布可靠软件的系统方法》第4章 测试策略的实现

    yeedomliu
  • 《PMP精讲视频》第7章 成本管理

    yeedomliu
  • 使用now.sh部署前端项目

    now.sh是ZEIT推出的一款全球化实时部署服务。ZEIT现在已经改名为Vercel。 网站地址:vercel.com Vercel 是一个云平台静态站点和无...

    不作声
  • Git 如何切换到不同远程仓库

    例如我们有一个项目 USRealEstate,当前使用的是微信的 Git,我们希望切换到 GitHub 上。

    HoneyMoose
  • SAP成都研究院姚瑶:软件质量保证工作的变迁

    大家好,我是来自SAP成都研究院Revenue Cloud 团队的质量工程师 , yoyo。很高兴可以和大家分享我个人的工作体会。每个团队都有QE(Qualit...

    Jerry Wang
  • SAP成都研究院姚瑶:软件质量保证工作的变迁

    大家好,我是来自SAP成都研究院Revenue Cloud 团队的质量工程师 , yoyo。很高兴可以和大家分享我个人的工作体会。每个团队都有QE(Qualit...

    Jerry Wang
  • 3亿人次的实战演习,如何做到丝般顺滑?

    本文介绍的是手机QQ与Qzone两个服务于海量用户的平台级业务,在无损用户服务质量的基准原则下,通过亿量级人次的限时调度实战演习来验证我们的异地容灾架构与快速调...

    织云平台团队
  • 性能测试从零开始实施指南——测试报告篇

    性能测试的目的,是通过模拟真实的业务场景和海量的用户请求及数据对业务系统进行多种场景的测试,来验证各个服务的性能表现是否满足实际的业务需要。

    写博客的老张
  • 每天一道面试题——如何测试银行系统?

    有一次去银行面试,面试官看我简历上有一个金融项目,于是问我:你觉得金融项目跟常规项目的测试有什么区别?

    张树臣

扫码关注云+社区

领取腾讯云代金券