最近我阅读了很多有关DevOps的文章,其中一些非常有趣,然而一些内容也很欠考虑。貌似很多人越来越坚定地在DevOps与chef、puppet或Docker容器的熟练运用方面划了等号。对此我有不同看法。DevOps的范畴远远超过puppet或Docker等工具。
这样的看法甚至让我感觉有些气愤。DevOps在我看来极为重要,过去15年来,我一直在大型机构,主要是大型金融机构中从事工程业务。DevOps是一种非常重要的方法论,该方法将解决一些最大型问题的基本原则和实践恰如其分地融为一体,很好地解决了此类机构的软件开发项目中一种最令人感觉悲凉的失败要素:开发者和运维人员之间的混乱之墙。
请不要误会我的这种观点,除了某些XP实践,大部分此类大型机构对敏捷开发方法论的运用还有很长的路要走,同时还有很多其他原因会导致软件开发项目的失败或延误。
但在我看来,混乱之墙目前依然是他们所面临的最令人沮丧、最浪费时间、同时也相当愚蠢的问题。
与其独自生闷气,我觉得不如说点更实在的东西,写一篇尽可能精准的文章,向大家介绍DevOps到底是什么,能为我们带来什么。长话短说,DevOps并不是某一套工具。DevOps是一种方法论,其中包含一系列基本原则和实践,仅此而已。而所用的工具(或者说“工具链”吧,毕竟用于为这些实践提供支持的工具集有着极高的扩展性)只是为了对这样的实践提供支持。
最终来说,这些工具本身并不重要。相比两年前,目前的DevOps工具链已经产生了翻天覆地的变化,可想而知,两年后还会产生更大的差异。不过这并不重要。重要的是能够合理地理解这些基本原则和实践。
本文并不准备介绍某些工具链,甚至完全不会提到这些工具。网上讨论DevOps工具链的文章已经太多了。我想在本文中谈谈最基本的原则和实践,它们的主要目的,毕竟这些才是对我而言最重要的。
DevOps是一种方法论,归纳总结了面临独一无二的机遇和强有力需求的网络巨头们,结合自身业务本质构思出全新工作方式的过程中所采用的实践,而他们的业务需求也很直接:以史无前例的节奏对自己的系统进行演进,有时候可能还需要以天为单位对系统或业务进行扩展。
虽然DevOps对初创公司来说很明显是不可或缺的,但我认为那些有着庞大的老式IT部门的大企业才是能从这些基本原则和实践中获得最大收益的。本文将试图解释得出这个结论的原因和实现方法。
本文的部分内容已发布为Slideshare演示幻灯片,可在这里浏览:http://www.slideshare.net/JrmeKehrli/devops-explained-72091158
目录
DevOps的真谛到底是什么?
-
简介
1.1 管理信条
1.2 一个典型的IT组织
1.3 运维人员测挫败感
1.4 基础架构自动化
1.5 DevOps:仅此一次,一颗神奇的银子弹
-
基础架构即代码
2.1 概述
2.2 DevOps工具链
2.3 收益
-
持续交付
3.1 从实践中学习
3.2 自动化
3.3 更频繁的部署
3.4 持续交付的前提需求
3.5 零停机部署
-
协作
4.1 混乱之墙
4.2 软件开发流程
4.3 共享工具
4.4 协同工作
-
结论
1. 简介
DevOps所关注的不是工具本身,也不是对chef或Docker的掌握程度。DevOps是一种方法论,是一系列可以帮助开发者和运维人员在实现各自目标(Goal)的前提下,向自己的客户或用户交付最大化价值及最高质量成果的基本原则和实践。
开发者和运维人员之间最大的问题在于:虽然都是企业中大型IT部门不可或缺的,但他们有着截然不同的目的(Objective)。
开发者和运维人员之间目的上的差异就叫做混乱之墙。下文会介绍这个概念的准确定义,以及为什么我认为这种状况很严峻并且很糟糕。
DevOps是一种融合了一系列基本原则和实践的方法论(并从这些实践中派生出了各种工具),意在帮助这些人员向着一个统一的共同目的努力:尽可能为公司提供更多价值。
令人惊奇的是,这个问题竟然有一个非常简单的“银子弹”:让生产端变得敏捷起来!
而这恰恰正是DevOps所要达成的唯一目标!
但在进一步讨论这一点之前,首先需要谈谈其他几件事。
1.1 管理信条
IT管理这场战争的原动力到底是什么?换句话说,在软件开发项目中,管理工作首要的,以及最重要的目的是什么?
有什么想法吗?
我来提供一个线索吧:在建立一家初创公司时,最重要的事情是什么?
当然是要加快上市时间(TTM)!
上市时间(即TTM)是指一件产品从最初的构思到最终可供用户使用或购买这一过程所需要的时间。对于产品很快会过时的行业,TTM是一个非常重要的概念。
在软件工程方面,所采用的方法、业务,以及具体技术几乎每年都会变化,因而TTM就成了一个非常重要的KPI(关键绩效指标)。
TTM通常也会被叫做前置时间(Lead Time)。
第一个问题在于,(很多人认为)在开发过程中TTM和产品质量是两个对立的属性。在下文可以看到,改善质量(进而提高稳定性)是运维人员的目的,而开发者的目的在于降低前置时间(进而提高TTM)。
请容我来解释一下。
IT组织或部门通常会通过两个关键的KPI进行评估:软件本身的质量,因而需要尽可能减少缺陷的数量;此外还有TTM,因而需要将业务构想(通常由业务用户提供)变为最终成果,并以尽可能快的速度提供给用户或客户。
这里的问题在于,大部分情况下这两个截然不同的目的是由两个不同团队提供支持的:负责构建软件的开发者,以及负责运行软件的运维人员。
1.2 一个典型的IT组织
在组织内部负责管理重要IT部门的典型IT组织通常看起来是这样的:
主要由于历史的原因(大部分运维人员来自硬件和电信业务领域),运维人员和开发者分属不同的组织结构分支。开发者属于研发部门,而运维人员大部分时候属于基础架构部门(或专门的运维部门)。
别忘了,他们有着不同的目的:
此外作为旁注,这两个团队有时候会使用不同的预算来运营。开发团队使用构建(Build)预算,运维团队使用运营(Run)预算。不同的预算,对控制权越来越高的需求,以及企业IT成本的缩水,这些因素结合在一起会进一步放大两个团队各自目的的对立性。
(依本人愚见,时至今日,随着人与人之间无时无刻随时随地进行的交互,以及由不同目的推动着企业和社会进行数字化转型,IT预算方面古老的“规划/构建/运行”框架已经不那么合理了,不过这又是另一回事了。)
1.3 运维人员测挫败感
接下来看看运维人员,一起看看典型的运维团队把大部分时间都花在哪里了:
运维团队的时间分配
(来源:Study from Deepak Patil [Microsoft Global Foundation Services] in 2006, via James Hamilton [Amazon Web Services] [http://mvdirona.com/jrh/TalksAndPapers/JamesHamilton_POA20090226.pdf]5)
生产团队有将近一半(47%)的时间花在了与部署有关的工作中:
-
执行实际的部署工作
-
或修复与部署工作有关的问题
这样的KPI其实相当疯狂,但实际上我们早就应该采纳。实际上早在40年前,计算机科学的“原始时代”就已涌现出运维团队,当时计算机主要运用在工业界,运维人员需要手工运行大量命令来执行自己的任务。为了履行职责,他们已经习惯于按照清单运行各种各样的命令或手工流程。
突然有一天他们终于意识到自己“总在做着相同的事情”,然而长达四十多年的工作过程中却几乎没人考虑过变革。
考虑到这一点你会发现,实在是太疯狂了。平均来说,运维人员将近一半的时间都在处理与部署有关的任务!
为了改变这种状况,必须考虑到两个最关键的需求:
-
通过自动化部署将目前这种手工任务所需的时间减少31%。
-
通过产业化措施(类似于通过XP和敏捷实现的软件开发产业化)将需要处理的与这些部署有关的问题减少16%。
1.4 基础架构自动化
在这方面也有一个相当富有启发性的统计结果:
以手工操作的数量所表示的成功部署概率。
这些统计告诉我们:
-
只需手工运行5条命令的情况下,成功部署的概率就已跌至86%。
-
如需手工运行55条命令,成功部署的概率将跌至22%。
-
如需手工运行100条命令,成功部署的概率将趋近于0(仅2%)!
成功部署意味着软件能够按照预期在生产环境中运行。未能成功部署意味着有东西出错,可能需要进行必要的分析才能了解部署过程中哪里出错,是否需要应用某种补丁,或需要修改某些配置。
因此让这一切实现自动化并不惜一切代价避免手工操作似乎是个好主意,对吧?
那么行业里这方面的现状是怎样的:
运维团队的时间分配(来源:IT Ops & DevOps Productivity Report 2013 - Rebellabs -http://pages.zeroturnaround.com/rs/zeroturnaround/images/it-ops-devops-productivity-report-2013%20copy.pdf)
(说实话,这个统计信息比较老了,是2013年的结果,相信现在的结果会有所不同)
然而这也可以让我们明确的知道,在基础架构自动化方面我们还有多远的路要走,并且DevOps的基本原则和实践依然是那么的重要。
网络巨头们当然会通过新的方法和实践及时满足自己的需求,他们早已开始构建自己的工程业务,而正是他们所确立的实践逐渐衍生出当今我们所熟悉的DevOps。
看看这些网络巨头们在这方面目前所处的位置吧,举几个例子:
-
Facebook有数千名开发和运维人员,成千上万台服务器。平均来说一位运维人员负责500台服务器(还认为自动化是可选的吗?)他们每天部署两次(环式部署,Deployment ring的概念)。
-
Flickr每天部署10次。
-
Netflix明确针对失败进行各种设计!他们的软件按照设计从最底层即可容忍系统失败,他们会在生产环境中进行全面的测试:每天通过随机关闭虚拟机的方式在生产环境中执行65000次失败测试…… 并确保这种情况下一切依然可以正常工作。
他们这种做法秘密何在?
1.5 DevOps:仅此一次,一颗神奇的银子弹
他们的秘密很简单:将敏捷扩展至生产端:
DevOps的共存主要是为了扩展敏捷开发实践,进一步完善软件变更在构建、验证、部署、交付等阶段中的流动,同时通过软件应用程序的全面所有权予力跨职能团队完成从设计到生产支持等各环节的工作。
DevOps鼓励软件开发者和IT运维人员之间所进行的沟通、协作、集成和自动化,借此有助于改善双方在交付软件过程中的速度和质量。
DevOps团队更侧重于通过标准化开发环境和自动化交付流程改善交付工作的可预测性、效率、安全性,以及可维护性。理想情况下,DevOps可以为开发者提供更可控的生产环境,帮助他们更好地理解生产基础架构。
DevOps鼓励团队自主进行自己应用程序的构建、验证、交付和支持。
那么核心原则到底是什么?
DevOps的基本原则
下文将介绍最重要的三大基本原则。
2. 基础架构即代码
人总会犯错,因为人脑实在是不擅长处理重复性的任务,相比Shell脚本,人类的速度实在是太慢了。毕竟我们都是人类,因此有必要像处理代码那样考虑和处理有关基础架构的概念!
基础架构即代码(IaC)是大部分通用DevOps实践的前提要求,例如版本控制、代码审阅、持续集成、自动化测试。这一概念涉及计算基础架构(容器、虚拟机、物理机、软件安装等)的管理和供应,以及通过机器可处理的定义文件或脚本对其进行的配置,交互式配置工具和手工命令的使用已经不合时宜了。
这一原则对DevOps的重要性怎么强调都不为过,它可以真正将软件开发相关的实践应用给服务器和基础架构。
云计算使得复杂的IT部署可以继续效仿传统物理拓扑。我们可以相对轻松地对复杂虚拟网络、存储和服务器的构建实现自动化。服务器环境的方方面面,上至基础架构下至操作系统设置,均可编码并存储至版本控制仓库。
2.1 概述
以非常概括的方式来看,基础架构和运维所需实现的自动化程度可通过下图这种架构来表示:
IaC概述
上述架构图中作为示例的工具主要面向不同层的构建工作,实际上DevOps工具链的作用远不止如此。
我觉得在这里可以略微深入地谈谈DevOps的工具链了。
2.2 DevOps工具链
DevOps实际是一种文化上的变迁,代表了开发、运维、测试等环节之间的协作,因此DevOps工具是非常多种多样的,甚至可以由多种工具组成一个完整的DevOps工具链。此类工具可以应用于一种或多种类别,并可体现出软件开发和交付过程的不同阶段:
-
编码:代码开发和审阅,版本控制工具、代码合并工具
-
构建:持续集成工具、构建状态统计工具
-
测试:通过测试和结果确定绩效的工具
-
打包:成品仓库、应用程序部署前暂存
-
发布:变更管理、发布审批、发布自动化
-
配置:基础架构配置和部署,基础架构即代码工具
-
监视:应用程序性能监视、最终用户体验
虽然可用工具有很多,但其中一些环节是组织内部应用DevOps工具链不可或缺的。
诸如Docker(容器化)、Jenkins(持续集成)、Puppet(基础架构构建)、Vagrant(虚拟化平台)等常用、广泛使用的工具都是2016年的DevOps热门工具。
基础架构组件的版本控制、持续集成和自动化测试
基础架构的版本控制能力(而非基础架构的构建脚本或配置文件)及对其进行自动化测试的能力极其重要。DevOps最终会将30年前软件工程领域所采用的同一套XP实践带至生产端。
此外基础架构元素应该能向软件交付物一样进行持续集成。
2.3 收益
DevOps的收益有很多,包括但不限于:
-
可重复性与可靠性:时至今日,构建生产用计算机只需要运行脚本或必要的puppet命令即可。通过恰当地使用Docker容器或Vagrant虚拟机,只需运行一条命令即可配置好包含操作系统层以及所需软件和配置的生产用计算机。当然,随着各种变更或软件开发、持续集成,并自动测试,这套构建脚本或机制也会进行持续集成。最终幸亏有了XP或敏捷,我们在软件开发端所使用的同一套实践也能让运维端获益。
-
生产力:一键部署,一键供应,一键创建新环境……整个生产环境可以通过一条命令或一键点击的方式创建。这样的一条命令也许会运行长达数小时,但在这过程中运维人员可以从事其他更有趣的工作,而无需等待一条命令执行完毕后继续输入下一条命令,毕竟这样的过程有时候可能需要花费几天时间才能完成……
-
恢复时间!:一键点击即可恢复生产环境,就是这么简单。
-
确保基础架构的同质:彻底避免运维人员每次构建环境或安装软件时最终获得的结果与预期有所差异,这是确保基础架构绝对同质(Homogeneous)并且可再现的唯一可行方法。以此为基础,通过对脚本或Puppet配置文件使用版本控制机制,我们甚至可以重建出与上周、上个月,或软件特定版本发布时完全一致的生产环境。
-
维持整齐划一的标准:基础架构标准甚至可以不复存在,代码本身就是标准。
-
让开发者自行完成大部分工作:如果开发者自己突然可以在自己的基础架构上一键点击重建生产环境,他们也就可以自行完成很多与生产环境有关的任务,例如更好地理解生产失败,提供更恰当的配置,实现部署脚本等。
这只是我个人感觉IaC可提供的部分收益,相信还有很多其他收益。
3. 持续交付
持续交付是一种可以帮助团队以更短的周期交付软件的方法,该方法确保了团队可以在任何时间发布出可靠的软件。该方法意在以更快速度更高频率进行软件的构建、测试和发布。
通过对生产环境中的应用程序进行更高频次的增量更新,这种方法有助于降低交付变更过程中涉及的成本、时间和风险。足够简单直接并且可重复的部署流程对持续交付而言至关重要。
注意:持续交付 ≠ 持续部署 - 有时候很多人会把持续交付误认为成持续部署。持续部署是指每个变更可以自动部署到生产环境。持续交付是指团队确保每个变更可以部署至生产环境,但也许并不需要实际部署,这通常可能是出于业务方面的原因。只有成功实现持续交付的前提下,才能进行持续部署。
持续交付的主要想法在于:
-
部署越频繁,对部署流程就会越熟悉,自动化机制就能获得更好的结果。如果同一件事每天需要执行3次,很快你将变的无比娴熟,但很快也会因为日复一日解决同样的问题而感到厌烦。
-
部署越频繁,所部属的变更集就越微不足道,而这些微不足道的内容最有可能出错,甚至可能导致丢失对整个变更集的控制力。
-
部署越频繁,TTR(修复/解决所需时间)指标就会越出色,从业务用户处获得有关功能的各类反馈的速度越快,作出改进以便完美满足对方需求的过程也会越简单(这方面TTR与TTM其实非常相似)。
小规模变更/更高频次(来源:Ops Meta-Metrics: The Currency You Pay For Change - http://fr.slideshare.net/jallspaw/ops-metametrics-the-currency-you-pay-for-change-4608108)
但持续交付并不仅仅是尽可能频繁地构建可发布、生产就绪版本的软件产品那么简单。持续交付包含3个关键实践:
-
从实践中学习
-
自动化
-
更频繁的部署
3.1 从实践中学习
持续交付的关键在于要能从实践中学习。真理并不存在于开发团队中,而在于业务用户中。然而无论花多长时间,没人能真正清楚地表达自己的想法,或者将自己的想法用清晰的文档概括出来。也正是因此,敏捷方法论强调将功能提供给用户,并不惜一切代价从用户处获得尽可能多的反馈。
持续交付与持续部署类似,需要尽可能减少前置时间,这也是尽快从用户处获得“真理”的关键。
但真理绝对不会来自正规形式的用户反馈。我们绝不能尽信自己的用户或寄希望于通过正规形式的反馈了解用户。我们只能相信自己的度量。
痴迷于度量是精益创业(Lean Startup)活动中一个重要的概念,但这一概念对DevOps同样重要。我们应该度量一切!确定最恰当的度量指标可以让团队了解某种方法最终能否成功或失败,了解怎样做可以获得更好的结果,以及哪些最成功的做法同时也蕴含着一定的风险。为了帮助团队做出更明智的决策,在确定要衡量的指标时,一定要抱着“宁多勿少”的原则。
不需要“考虑”,只需要“知道”!“知道”的唯一方法就是度量,度量一切:响应时间、用户思考时间、展示次数、API调用次数、点击率等,但这些并非需要度量的全部。找出所有能让你更进一步了解用户对功能看法的度量指标,对所有这些指标进行度量!
这种方法可以表示为如下形式:
3.2 自动化
自动化已经在上文2. 基础架构即代码一节进行了讨论。
在这里我想强调的是,在没有将与基础架构有关的所有供应和任务实现妥善、全面的自动化之前,持续交付根本无从谈起。
这一点很重要,因此有必要再重复一遍:环境的搭建和生产就绪版本软件的部署只需要一键点击,只需要运行一条命令,整个过程应该自动完成。否则根本无法设想能一天多次部署同一个软件。
在下文的3.5 零停机部署一节中,还将介绍有助于自动化交付的其他重要技术。
3.3 更频繁的部署
DevOps的信条在于:
“越是困难的事,需要更频繁地进行!”
敏捷思维中,困难任务更要迎难而上,更频繁地去做,这中想法非常重要。
自动化测试、重构、数据库迁移、面向客户的产品规格、规划、发布 - 所有这些活动都要尽可能频繁地进行。
原因主要有三点:
-
首先,随着要做的工作量逐渐增加,这些任务也会变的愈加困难,但如果能拆解为小块,则会变的相对容易些。以数据库迁移为例:一些涉及大量表的大规模数据库迁移工作很麻烦,容易出错。但如果一次只迁移一部分,则可以相对较容易地成功完成整个迁移任务。此外还可以轻松地将多个小规模的迁移任务安排成一定的序列,在将一个艰难的大任务拆解为一系列容易实现的小目标后,处理起来就简单多了。(这也是数据库重构的本质)
-
第二个原因在于反馈。大部分敏捷思维关注的是设置反馈环路,借此让我们更快速地学习了解。反馈已经是极限编程(Extreme Programming)中一个非常重要,蕴含巨大价值的概念。在诸如软件开发等复杂流程中,我们需要更频繁地检查自己的最新进展,并进行必要的纠正。为此我们必须尽一切可能创建反馈环路,并提高反馈的频率,这样才能更快速地酌情做出调整。
-
第三个原因是实践。对于任何活动,越频繁地从事就越能获得完善。实践可以帮助我们理清整个流程,让我们更熟悉代表有事情出错的征兆。只要认真琢磨自己从事的工作,就能提炼出近一步完善所需的实践。对于软件开发,也有可能实现一定程度的自动化。一旦有人将某件事做了多次,就可以更容易地确定该如何进行自动化,更重要的是,这样的人在对这些事情实现自动化方面将有更大的动机。此时自动化尤为重要,因为可以加快速度并降低出错的概率。
掌握整个流程
那么这就产生了一个问题:使用DevOps方法时,该选择怎样的交付频率?
这个问题没有标准答案,而是取决于产品、团队、市场、公司、用户、运维需求等各种因素。
我认为最佳答案应该是:如果不能实现至少每两周一次交付,或在冲刺阶段结束时交付,那么连敏捷都谈不上,DevOps又从何谈起呢?
DevOps鼓励我们尽可能频繁的交付。在我看来,你需要对团队进行培训,让他们能够做到尽可能频繁的交付。我在我的团队中使用的一种较为可行的方法是在QA环境中每天交付两次。交付过程是完全自动化的:每天两次,中午和午夜各一次,计算机启动起来,构建软件组件,运行集成测试,构建并启动虚拟机,部署软件组件,对其进行配置,运行功能测试等。
3.4 持续交付的前提需求
在改为使用持续交付方式之前,需要满足哪些要求?
我草拟的需求清单如下:
-
对软件组件的开发和平台的供应和设置进行持续集成。
-
TDD - 测试驱动的开发。这一点还有待商榷……但始终还是需要面对:TDD是目前唯一能通过单元测试对代码和分支进行可接受程度覆盖的方法(单元测试使得问题的修复过程比集成测试或功能测试容易很多)。
-
代码审阅!至少要进行代码审阅……如果能进行结对编程(Pair programming)当然就更好了。
-
软件的持续审计 - 例如使用Sonar。
-
在生产级环境实现功能测试的自动化。
-
更强大的非功能测试自动化(性能、可用性等)。
-
独立于目标环境的自动化打包和部署。
另外在管理重大功能和演进时,还需要具备健全的软件开发实践,例如零停机部署技术。
3.5 零停机部署
“零停机部署(ZDD)可在不中断现有服务的情况下部署新版系统。”
通过ZDD方式部署应用程序时,可在确保用户不会遭遇应用程序停机的前提下将新版应用引入生产环境。从用户和公司的角度来看,这应该是最佳部署方式,因为可以在不造成任何中断的情况下引入新功能并修复Bug。
下文将介绍4种技术:
-
功能开关(Feature Flipping)
-
摸黑启动(Dark launch)
-
蓝/绿部署(Blue/Green Deployment)
-
金丝雀发布(Canari release)
功能开关
功能开关可供我们在软件运行过程中启用/禁用相应的功能。这种技术其实非常容易理解和使用:为生产版本提供一个能彻底禁用某项功能的配置,并只在对应功能彻底完工可以正常工作后才将该属性激活。
举例来说,若要将某个应用程序内的一个功能全局禁用或激活:
或者如果要真对具体用户实现类似目的:
摸黑启动
摸黑启动的目的在于通过生产环境进行负载模拟!
在测试环境中,通常很难为软件模拟出成百上千万用户规模的负载。
如果不进行切实的负载测试,就无法知道基础架构能否承受住最终面临的压力。
此时并不需要模拟负载,而是可以实际部署这样的功能,然后看看在不影响可用性的前提下到底会发生什么。
Facebook将这种做法称之为功能的“摸黑启动”。
假设我们要将一个有5亿用户使用的静态搜索字段变成一个包含自动补全功能的字段,借此让用户可以更快速获得搜索结果。为该功能构建一个Web服务,并且希望模拟所有用户同时输入文字,向该Web服务生成大量请求的场景。
此时即可通过摸黑启动策略为现有表单添加一个隐藏的后台进程,通过该进程将输入的搜索关键字发送给新增的自动补全服务,并自动发送多次。
就算新增的Web服务彻底崩溃了,也不会造成任何实质损害。网页上可以完全忽略服务器错误。而就算该服务崩溃了,我们至少还可以对该服务进行优化和完善,直到能承受如此大量的负载。
这就等于在现实世界中进行了一次负载测试。
蓝/绿部署
蓝/绿部署是指为下一版产品构建另一个完整的生产环境。开发和运维团队可以在这个单独的生产环境中放心地构建下一版产品。
当下一版产品全部完成后,可以修改负载均衡器的配置,以透明的方式将用户自动重定向至新发布的下一版。
随后可将上一版的生产环境回收,用于构建下下一版的产品。
以此类推。
(来源:Les Patterns des Géants du Web – Zero Downtime Deployment - http://blog.octo.com/zero-downtime-deployment/)
这是一种相当有效简单的方法,但问题在于这种方式需要双倍的基础架构以及更多的服务器等。
假设一下Facebook希望将包含成千上万台服务器的环境“照原样再来一套”……
其实还有更好的方法。
金丝雀发布
从本质来看,金丝雀发布与蓝/绿部署非常类似,但无需准备额外的一套生产环境。
这种方式的目标在于以增量的方式将用户切换至新版本:随着越来越多的服务器从当前版本迁移至下一版,相同比例的用户也会被同时迁移。
通过这种方式,每个生产环境都能获得与负载需求相匹配的服务器数量。
首先,只将少量服务器和少部分用户迁移至下一版,借此还可以在无须冒险影响所有用户的前提下对新版进行测试。
当所有服务器最终从当前版迁移至下一版后,发布工作已经完成,又可以从头开始准备下下一版了。
金丝雀部署(来源:Les Patterns des Géants du Web – Zero Downtime Deployment -http://blog.octo.com/zero-downtime-deployment/)
4. 协作
敏捷软件开发破除了需求分析、测试和开发之间的一些隔阂。部署、运维和维护等其他活动与软件开发过程中的其他环节也存在类似的分隔。DevOps方法意在破除所有这些隔阂,鼓励开发和运维人员之间的协作。
如果没有培养出正确的文化,就算有最棒的工具,DevOps对你而言也不过是另一个热门词汇罢了。
DevOps文化的主要特征在于开发和运维角色之间日益增加的协作。这是一种在团队内部以及组织层面上很重要的文化变迁,通过这样的变迁才能促进更好的协作。
这种方式解决了一个非常重要的问题,而这个问题完全可以用下面这个网络流行话来体现:
开发工作已完成/现在这是运维的问题了
(来源:DevOps Memes @ EMCworld 2015 - http://fr.slideshare.net/bgracely/devops-memes-emcworld-2015)
团队合作对DevOps是如此的重要,大部分方法论所要实现的最终目标总的来说可以通过两个C来实现:协作(Collaboration)和沟通(Communication)。虽然单纯做到这些距离真正的DevOps工作环境还有很大的差距,但任何公司只要能坚持这两个C,就等于迈出了最正确的第一步。
但为什么会那么难做到?
4.1 混乱之墙
因为有一堵混乱之墙:
在传统开发周期中,开发团队将新发布的软件“隔墙扔给”运维人员,意味着自己的工作已经顺利完成。
运维人员接手开发者的成果,准备开始进行部署。运维人员手工修改由开发者提供的部署脚本,当然更多时候这些脚本都是运维人员自己维护的。
运维人员还需要手工修改配置文件,以反映生产环境的需求,而生产环境往往与开发或QA环境有很大差异。
就算最理想的情况,运维人员可能只是做了一些在上一个环境中已经做过的重复工作,而最糟糕的情况,可能会引入或发现新的Bug。
随后IT运维团队开始讨论他们所认为的,目前最正确的部署流程,然而由于开发和运维在脚本、配置、流程,甚至环境等方面的差异,基本上等同于要从零开始将所有工作重新执行一遍。
当然这一过程中不可避免会遇到问题,他们联系开发者希望进行排错。运维称开发者提供的代码本身有问题,开发者则回应称代码在自己的环境中一切正常,因此错误肯定源自运维端。
由于配置、文件位置,以及面临这种状态所执行的操作与自己的预期等因素存在较大差异,开发者甚至很难对这样的问题进行诊断。变更窗口留下的时间所剩无几,当然也没什么足够靠谱的方法将环境回滚至上一个正常状态。
那么原本应该一帆风顺的部署过程,为什么最后却变成了“众志成城”的应急演习?必须经历大量指责和错误才能最终让生产环境恢复可用状态?
这种情况经常发生,经常!
DevOps来救场了
通过在共同的业务目的情境中让开发和运维角色与流程变的一致,DevOps有助于促进IT的统一。开发和运维都需要明确,自己是统一业务流程的一份子。DevOps思维确保了无论组织结构是怎样的,个体决策与行为需要尽力为统一的业务流程提供支持和促进作用。
亚马逊CTOWerner Vogel甚至在2014年说过:
“谁开发,谁运行。”
4.2 软件开发流程
下图简要描述了敏捷软件开发流程通常的样子。
最开始,业务代表与产品负责人以及架构团队合作定义软件,这一过程可能会使用Story Mapping和用户故事,或者使用更完整的规范。
随后开发团队通过短暂的开发冲刺开发出软件,并在每个冲刺结束后将生产就绪版本的软件发布给业务用户,进而收集反馈并尽可能频繁地调整方向。
最后,经历过每个新的里程碑后,将软件部署给整个业务线更广泛的用户群体。
软件开发流程
DevOps造成的最大挑战在于需要理解运维人员是软件的另一个用户群体!因此他们也应该被全面纳入软件开发流程中。
在预定的时间里,运维应该给出自己的非功能需求,就如同业务用户给出自己的功能需求一样。开发团队应该按照同等程度的重要性和优先级处理这种非功能需求。
在实现的过程中,运维应该持续提供反馈和非功能测试规范,就像业务用户针对功能特性提供反馈一样。
最后,运维和业务用户一样,成为了软件的用户。
有运维人员参与的软件开发流程
通过采用DevOps方法,运维可以全面融入软件开发流程中。
4.3 共享工具
在传统的大型企业中,运维团队和开发团队分别使用专用的,没有什么交集的工具集。
运维人员通常并不想了解开发团队所使用的SCM系统以及持续集成环境。他们认为这些并非自己的本职工作,害怕自己在触及这些系统后会被开发者的各种请求所淹没。毕竟他们为了照料生产系统就有忙不完的工作了。
另一方面,开发者通常无法访问生产系统的日志和监视日志,有时这是因为没有这样的意愿,有时则是因为制度或安全方面的顾虑。
这种状况需要改变!DevOps应运而生。
共享工具
这个目标其实很难实现。举例来说,出于制度或安全方面的原因,日志可能会被实时匿名化,同时需要对监管工具进行必要的保护,以避免未经培训或本应被禁止的开发者更改生产环境的配置。因此实现这一目标需要付出大量时间和成本资源。但这样做所能获得的收益远大于所需进行的投入,这种方法对整个公司的投资回报非常明显。
4.4 协同工作
DevOps的一种基本哲学是认为,开发者和运维人员必须定期进行密切的合作。
这就意味着他们必须将对方视作重要的利益相关者,并积极主动地寻求合作。
受到XP实践中“现场客户”的启发,敏捷开发者受此激励可以与业务进行更紧密的合作,自律的敏捷者还可以更进一步将这样的实践运用给更广泛的利益相关者,例如可以让开发者与所有其他相关者进行合作,包括运维和支持人员。
这是一条双行道:运维和支持人员也必须愿意与开发者进行密切的合作。
协同工作
此外还可以通过协作:
-
让运维人员参与敏捷仪式(每日Scrum、冲刺规划、再次冲刺等)
-
让开发者参与生产环境的推出任务
-
在开发和运维之间打造统一的持续改进目标
5. 结论
DevOps是一次革命,主要是为了消除拥有大规模IT部门的大型企业中,开发团队和运维团队之间由于历史原因产生的隔阂与孤立所造成的混乱现状。
在我15年的职业生涯中,2/3的时间就职于此类大行机构,其中大部分是金融机构,每天我都在见证者这堵混乱之墙的存在。例如我经常会听到这样的说法:
-
“在我的Tomcat上工作很正常,很抱歉,但我完全不懂你所用的Websphere,帮不上你了。”(开发者说)
-
“我们真的不能从生产数据库中给你提取这张表,里面包含了与客户有关的机密数据。”(运维人员说)每天都会遇到其他很多类似的对话……天天如此!
好在DevOps日渐成熟,越来越多传统企业也在开始逐渐走上正途,开始接受DevOps的原则和实践。但还有很多企业无动于衷。
那么对于那些小规模的,开发和运维职能之间通常不会产生那么大分歧的企业呢?
这样的企业应用DevOps原则和实践,例如自动化部署、持续交付和功能开关,一样能获益匪浅。
我认为DevOps原则可以总结为:
DevOps实际上是向着大规模敏捷(Scaling Agility)迈出的另一步