你好,我是石雪峰。从今天开始,专栏正式进入了工程实践的部分。在DevOps的体系中,工程实践所占的比重非常大,而且和我们的日常工作息息相关。正因为如此,DevOps包含了大量的工程实践,很多我们都耳熟能详,比如持续集成、自动化测试、自动化部署等等,这些基本上是实践DevOps的必选项。
可是,还有一些实践常常被人们所忽视,但这并不代表它们已经被淘汰或者是不那么重要了。恰恰相反,它们同样是DevOps能够发挥价值的根基,配置管理(Configuration Management)就是其中之一。它的理念在软件开发过程中无处不在,可以说是整个DevOps工程实践的基础。所以今天我们就来聊一聊配置管理。
说了这么多,那软件配置管理到底是个啥呢?
熟悉运维的同学可能会说,不就是类似Ansible、Saltstack的环境配置管理工具吗?还有人会说,CMDB配置管理数据库也是配置管理吧?这些说法都没错。配置管理这个概念在软件开发领域应用得非常普遍,几乎可以说无处不在,但是刚刚提到的这些概念,都是细分领域内的局部定义。
我今天要讲到的配置管理,是一个宏观的概念,是站在软件交付全生命周期的视角,对整个开发过程进行规范管理,控制变更过程,让协作更加顺畅,确保整个交付过程的完整、一致和可追溯。
看到这里,我估计你可能已经晕掉了。的确,配置管理的理论体系非常庞大。但是没关系,你只需要把四个核心理念记在心中就足够了。这四个理念分别是:版本变更标准化,将一切纳入版本控制,全流程可追溯和单一可信数据源。
版本控制是配置管理中的一个非常核心的概念,而对于软件来说,最核心的资产就是源代码。现在很多公司都在使用类似Git、SVN之类的工具管理源代码,这些工具其实都是版本控制系统。版本描述了软件交付产物的状态,可以说,从第一行软件代码写下开始,版本就已经存在了。
现代软件开发越来越复杂,往往需要多人协作,所以,如何管理每个开发者的版本,并把它们有效地集成到一起,就成了一个难题。实际上,版本控制系统就是为了解决这个问题的。试想一下,如果没有这么一套系统的话,所有代码都在本地,不要说其他人了,就连自己都会搞不清楚哪个是最新代码。那么,当所有人的代码集成到一起的时候,那该是多么混乱啊!
不仅如此,如果线上发生了严重问题,也找不到对应的历史版本,只能直接把最新的代码发布上去,简直就是灾难。
配置管理中的另一个核心概念是变更。我们对软件做的任何改变都可以称之为一次变更,比如一个需求,一行代码,甚至是一个环境配置。版本来源于变更。对于变更而言,核心就是要记录:谁,在什么时间,做了什么改动,具体改了哪些内容,又是谁批准的。
这样看来,好像也没什么复杂的,因为现代版本控制系统基本都具备记录变更的功能。那么,是不是只要使用了版本控制系统,就做到变更管理了呢?
的确,版本控制系统的出现,大大简化了管理变更的成本,至少是不用人工记录了。但是,从另一方面来看,用好版本控制系统也需要有一套规则和行为规范。
比如,版本控制系统需要打通公司的统一认证系统,也就是任何人想要访问版本控制系统,都需要经过公司统一登录的认证。同时,在使用Git的时候,你需要正确配置本地信息,尤其是用户名和邮箱信息,这样才能在提交时生成完整的用户信息。另外,系统本身也需要增加相关的校验机制,避免由于员工配置错误导致无效信息被提交入库。
改动说明一般就是版本控制系统的提交记录,一个完整的提交记录应该至少包括以下几个方面的内容:
这些改动应该遵循一种标准化的格式,并且有相关的格式说明和书写方式,比如有哪些关键字,每一行的长度,变更编号的区隔是使用逗号、空格还是分号等等。如果按照这个标准来书写每次的变更记录,其实成本还是很高的,更不要说使用英文来书写的话,英文的表达方式和内容展现形式又是一个难题。
我跟你分享一个极品的提交注释,你可以参考一下。
switch to Flask-XML-RPC dependency
CR: PBX-2222
The Flask-XML-RPC-Re fork has Python 3 support, but it has a couple
other problems.
test suite does not pass
latest code is not tagged
uncompiled source code is not distributed via PyPI
The Flask-XML-RPC module is essentially dead upstream, but it is
packaged in EPEL 7 and Fedora. This module will get us far enough to
thepoint that we can complete phase one for this project.
When we care about Python 3, we can drop XML-RPC entirely and get the
service consumers to switch to a REST API instead.
(Note, with this change, the Travis CI tests will fail for Python 3.
Thesolution is to drop XML-RPC support.)
这时,肯定有人会问,花这么大力气做这个事情,会不会有点得不偿失呢?从局部来看,的确如此。但是,换个角度想,当其他人看到你的改动,或者是评审你的代码的时候,如果通过提交记录就能清晰地了解你的意图,而不是一脸蒙地把你叫过来,让你再讲一遍,这样节约的时间比当时你书写提交记录的时间要多得多。
所以你看,一套标准化的规则和行为习惯,可以降低协作过程中的沟通成本,一次性把事情做对,这也是标准和规范的重要意义。
当然,如果标准化流程要完全依靠人的自觉性来保障,那就太不靠谱了。毕竟,人总是容易犯错的,会影响到标准的执行效果。所以,当团队内部经过不断磨合,逐步形成一套规范之后,最好还是用自动化的手段保障流程的标准化。
这样做的好处有两点:一方面,可以降低人为因素的影响,如果你不按标准来,就会寸步难行,也减少了人为钻空子的可能性。比如,有时候因为懒,每次提交都写同样一个需求变更号,这样的确满足了标准化的要求,但是却产生了大量无效数据。这时候,你就可以适当增加一些校验机制,比如只允许添加你名下的变更,或者是只允许开放状态的变更号等等。另一方面,在标准化之后,很多重复性的工作就可以自动化完成,标准化的信息也方便计算机分析提取,这样就可以提升流程的流转效率。
可以说,标准化是自动化的前提,自动化又是DevOps最核心的实践。这样看来,说配置管理是DevOps工程实践的基础就一点不为过了吧。
如果说,今天这一讲的内容,你只需要记住一句话,那就是将一切纳入版本控制,这是配置管理的金科玉律。你可能会问,需要将什么样的内容纳入版本控制呢?我会毫不犹豫地回答你:“一切都需要!”比如软件源代码、配置文件、测试编译脚本、流水线配置、环境配置、数据库变更等等,你能想到的一切,皆有版本,皆要被纳入管控。
这是因为,软件本身就是一个复杂的集合体,任何变更都可能带来问题,所以,全程版本控制赋予了我们全流程追溯的能力,并且可以快速回退到某个时间点的版本状态,这对于定位和修复问题是非常重要的。
之前,我就遇到过一个问题。一个iOS应用发灰度版本的时候一切正常,但是正式版本就遇到了无法下载的情况。当时因为临近上线,为了查这个问题,可以说是全员上阵,团队甚至开始互相抱怨,研发说代码没有变化,所以是运维的问题;运维说环境没动过,所以是研发的问题。结果到最后才发现,这是由于一个工具版本升级,某个参数的默认值从“关闭”变成了“打开”导致的。
所以你看,如果对所有内容都纳入版本控制,快速对比两个版本,列出差异点,那么,解决这种问题也就是分分钟的事情,大不了就把所有改动都还原回去。
纳入版本控制的价值不止如此。实际上,很多DevOps实践都是基于版本控制来实现的,比如,环境管理方面推荐采用基础设施即代码的方式管理环境,也就是说把用代码化的方式描述复杂的环境配置,同时把它纳入版本控制系统中。这样一来,任何环境变更都可以像提交代码一样来完成,不仅变更的内容一目了然,还可以很轻松地实现自动化。把原本复杂的事情简单化,每一个人都可以完成环境变更。
这样一来,开发和运维之间的鸿沟就被逐渐抹平了,DevOps的真谛也是如此。所以,现在行业内流行的“什么什么即代码”,其背后的核心都是版本控制。
不过,这里我需要澄清一下,纳入版本控制并不等同于把所有内容都放到Git中管理。有些时候,我们很容易把能力和工具混为一谈。Git只是一种流行的版本控制系统而已,而这里强调的其实是一种能力,工具只是能力的载体。比如,Git本身不擅长管理大文件,那么可以把这些大文件放到Artifactory或者其他自建平台上进行管理。
对自建系统来说,实现版本控制的方式有很多种,比如,可以针对每次变更,插入一组新的数据,或者直接复用Git这种比较成熟的工具作为后台。唯一不变的要求就是,无论使用什么样的系统和工具,都需要把版本控制的能力考虑进去。
另外,在实践将一切纳入版本控制的时候,你可以参考一条小原则。如果你不确定是否需要纳入版本控制,有一个简单的判断方法就是:如果这个产物可以通过其他产物来重现,那么就可以作为制品管理,而无需纳入版本控制。
举个例子,软件包可以通过源代码和工具重新打包生成,那么,代码、工具和打包环境就需要纳入管控,而生成的软件包可以作为制品;软件的测试报告如果可以通过测试管理平台重新自动化生成,那么同样可以将其视为制品,但前提是,测试管理平台可以针对每一个版本重新生成测试报告。
对传统行业来说,全流程可追溯的能力从来不是可选项,而是必选项。像航空航天、企业制造、金融行业等,对变更的管控都是非常严谨的,一旦出现问题,就要追溯当时的全部数据,像软件源代码、测试报告、运行环境等等。如果由于缺乏管理,难以提供证据证明基于当时的客观情况已经做了充分的验证,就会面临巨额的罚款和赔偿,这可不是闹着玩的事情。像最近流行的区块链技术,除了发币以外,最典型的场景也是全流程可追溯。所以说,技术可以日新月异,但很多理念都是长久不变的。
对于配置管理来说,除了追溯能力以外,还有一个重要的价值,就是记录关联和依赖关系。怎么理解这句话呢?我先提个问题,在你的公司里面,针对任意一个需求,你们是否能够快速识别出它所关联的代码、版本、测试案例、上线记录、缺陷信息、用户反馈信息和上线监控数据呢?对于任意一个应用,是否可以识别出它所依赖的环境,中间件,上下游存在调用关系的系统、服务和数据呢?
如果你的回答是“yes”,那么恭喜你,你们公司做得非常好。不过,绝大多数公司都是无法做到这一点的。因为这不仅需要系统与系统之间的关联打通、数据联动,也涉及到一整套完整的管理机制。
DevOps非常强调价值导向,强调团队内部共享目标,这个目标其实就是业务目标。但实际情况是,业务所关注的维度,和开发、测试、运维所关注的维度都各不相同。业务关心的是提出的需求有没有上线,而开发关心的是这个需求的代码有没有集成,运维关心的是包含这个代码的版本是否上线。所以,如果不能把这些信息串联打通,就没有真正做到全流程可追溯。
关于这个问题,我给你的建议是把握源头,建立主线。所谓源头,对于软件开发而言,最原始的就是需求,所有的变更都来源于需求。所以,首先要统一管理需求,无论是开发需求、测试需求还是运维需求。
接下来,要以需求作为抓手,去关联下游环节,打通数据,这需要系统能力的支持,也需要规则的支持。比如,每次变更都要强制关联需求编号,针对不同的需求等级定义差异化流程,这样既可以减少无意义的审批环节,给予团队一定的灵活性,也达到了全流程管控的目标。这是一个比较漫长的过程,但不积跬步,无以至千里,DevOps也需要一步一个脚印地建设才行。
最后,我想单独谈谈单一可信数据源。很多人不理解这是什么东西,我举个例子你就明白了。
有一个网络热词叫作“官宣”,也就是官方宣布的意思。一般情况下,官宣的信息都是板上钉钉的,可信度非常高。可问题是,如果有多个官宣的渠道,信息还都不一样,你怎么知道要相信哪一个呢?这就是单一可信数据源的意义。
试想一下,我们花了很大力气来建设版本控制的能力,但如果数据源本身不可靠,缺乏统一管控,那岂不是白忙一场吗?所以,对于软件开发来说,必须要有统一的管控:
同时,单一可信数据源也要能覆盖企业内部元数据的管控。比如,企业内部经常出现这种情况,同样是应用,在A部门的系统中叫作123,在B部门的系统中叫作ABC,在打通两边平台的时候,这就相当于“鸡同鸭讲”,完全对不上。再比如,信息安全团队维护了一套应用列表,但实际上,在业务系统中,很多应用都已经下线且不再维护了,这样一来,不仅会造成资源浪费,还伴随着非常大的安全风险。
很多时候,类似的这些问题都是因为缺乏统一的顶层规划和设计导致的,这一点,在建立配置管理能力的时候请你格外关注一下。
今天我给你介绍了DevOps工程实践的基础配置管理,以及配置管理的四大理念,分别是版本变更标准化、将一切纳入版本控制、全流程可追溯和单一可信数据源,希望能帮你掌握配置管理的全局概念。
虽然配置管理看起来并不起眼,但是就像那句经典的话一样:“岁月静好,是因为有人替你负重前行。” 对于任何一家企业来说,信息过载都是常态,而配置管理的最大价值正是将信息序列化,对信息进行有效的整理、归类、记录和关联。而软件开发标准和有序,也是协同效率提升的源头,所以,配置管理的重要性再怎么强调都不为过。
你在企业中遇到过哪些配置管理方面的难题呢?你们的配置管理体系又是如何建立的呢?你遇到过因为缺乏单一可信数据源而导致“鸡同鸭讲”的有趣故事吗?
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。
评论