mirror of
https://github.com/cheetahlou/CategoryResourceRepost.git
synced 2025-11-16 22:23:45 +08:00
del
This commit is contained in:
211
极客时间专栏/geek/DevOps实战笔记/平台工具篇/21 | 开源还是自研:企业DevOps平台建设的三个阶段.md
Normal file
211
极客时间专栏/geek/DevOps实战笔记/平台工具篇/21 | 开源还是自研:企业DevOps平台建设的三个阶段.md
Normal file
@@ -0,0 +1,211 @@
|
||||
<audio id="audio" title="21 | 开源还是自研:企业DevOps平台建设的三个阶段" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/81/87/817c1e9aa6397e9a6f4d1a8a49a6ef87.mp3"></audio>
|
||||
|
||||
你好,我是石雪峰,从今天开始,专栏正式进入了“平台工具篇”。
|
||||
|
||||
在这个全新的章节,我重点想讲三个方面的内容:
|
||||
|
||||
- 帮助你梳理企业内部DevOps平台的实施路径,理清平台建设的主体脉络;
|
||||
- 给你分享一些核心平台的建设经验,这些经验都来自于生产一线;
|
||||
- 给你分析一下DevOps平台的发展方向和热门趋势,让你在进行平台建设时,能够跟上潮流。
|
||||
|
||||
我想跟你说的是,**没有人天生就是DevOps平台的产品经理,但每一个人都能成为DevOps平台的产品经理**。
|
||||
|
||||
因为,DevOps平台的产品与业务方向的产品不同,它要解决的就是**一线研发交付团队的实际问题**。
|
||||
|
||||
普通的产品经理没有研发交付的背景,很难理解研发交付的困境,而研发交付团队又缺少产品经理的技能和思路。所以,这个领域的人才少之又少,基本只能靠内部培养,我希望你能通过专栏的学习,摸索出一些产品设计的门道。
|
||||
|
||||
好了,今天,我们就来聊一聊企业DevOps平台建设的话题。
|
||||
|
||||
就像我之前提到的那样,在企业内部推行DevOps,工具不是万能的,但是没有工具,却是万万不能的。
|
||||
|
||||
当企业决定引入DevOps工具的时候,无外乎有三种选择:直接使用开源工具;采购商业工具;自己研发工具。
|
||||
|
||||
你可能会说,如果有能力,当然是选自研工具啊,自主可控,又有核心竞争力。可是,在DevOps状态报告中,却有一些不同的发现。
|
||||
|
||||
那些倾向于使用完全自建工具的企业,效能水平往往不高。所谓的完全自建工具,是指不依赖于开源解决方案,整个工具完全由自己来实现。而那些大部分采用开源工具的企业,效能水平反而不差。
|
||||
|
||||
这就有点反常理了。企业花了这么大的时间和精力来建设内部工具,到最后却没有达到预期的效果,究竟是为什么呢?
|
||||
|
||||
在我看来,这是因为没有找到企业内部平台建设的正确路径。**我们要在正确的时候,做正确的事情,太超前,或者太落后,都是会有问题的**。
|
||||
|
||||
那么,接下来,我就跟你聊聊企业DevOps平台建设的三个阶段。
|
||||
|
||||
## 阶段一:从无到有
|
||||
|
||||
在这个阶段,企业的DevOps平台建设处于刚刚起步的状态,在整个交付过程中,还有大量的本地操作和重复性的操作。
|
||||
|
||||
另外,企业内部一般也没有一个成体系的工具团队,来专门负责平台能力建设。
|
||||
|
||||
那么,对于这个阶段,**我给你的建议是:引入开源工具和商业工具,快速补齐现有的能力短板**。
|
||||
|
||||
所谓能力短板,其实就是当前交付工具链体系中缺失的部分,尤其是高频操作,或者是涉及多人协作的部分,比如,需求管理、持续集成等。
|
||||
|
||||
无论是开源工具,还是商业工具,基本都是比较成熟的、拿来即用的,这种“即战力”是当前企业最需要的。因为,工具的引入解决了从无到有的问题,可以直接提升单点效率。这也是在DevOps转型初期,团队的效率能够飞速提升的主要原因。
|
||||
|
||||
看到这里,你可能会问两个问题:“如何选择工具?”“为什么商业工具也是可选项?”
|
||||
|
||||
其实,这也是团队在引入工具的初期,最头疼的两个典型问题,我们一一来看下。
|
||||
|
||||
### 如何选择工具?
|
||||
|
||||
现在,以DevOps为名的工具太多了。想要在这么多工具中,选择一款合适的,你要怎么做呢?
|
||||
|
||||
有的人可能会把相关工具的功能列表拉出来,然后逐项比对,看哪个工具的功能更加强大。其实,我觉得,在从无到有的阶段,不需要这么复杂,**核心原则就是选择主流工具**。
|
||||
|
||||
主流工具就是业内大家用得比较多的,在各种分享文章里面高频出现的,使用经验一搜一大把的那种工具。我给你提供一些工具,你可以参考一下:
|
||||
|
||||
- 需求管理工具Jira;
|
||||
- 知识管理工具Confluence;
|
||||
- 版本控制系统GitLab;
|
||||
- 持续集成工具Jenkins;
|
||||
- 代码质量工具SonarQube;
|
||||
- 构建工具Maven/Gradle;
|
||||
- 制品管理Artifactory/Harbor;
|
||||
- 配置管理工具Ansible;
|
||||
- 配置中心Apollo;
|
||||
- 测试工具RF/Selenium/Appium/Jmeter/TestNG;
|
||||
- 安全合规工具BlackDuck/Fortify;
|
||||
- ……
|
||||
|
||||
在初期,工具要解决的大多是单点问题,主流工具意味着更好的可扩展性,比如有完整的接口列表,甚至对其他工具已经内置了插件支持。
|
||||
|
||||
另外,很多开发实践都是基于主流工具来设计的。业内对于这些工具摸索得也比较深,有很多现成的实践经验,这些都对应了快速补齐能力短板的目标。
|
||||
|
||||
我之前见过一家大型金融机构,他们也在考虑将代码管理从SVN切换到Git。但是,他们选择的Git平台既不是开源的GitLab、Gerrit,也不是商业化的主流工具,而是一个听都没听过的开源工具。
|
||||
|
||||
这个工具的操作流程跟一般工具都不太一样,配套的评审、集成功能也都不够完善。最后,这家机构还是改用主流工具了。
|
||||
|
||||
### 为什么商业工具也是可选项?
|
||||
|
||||
随着开源工具的成熟和完善,越来越多的公司,甚至是传统企业,都开始积极拥抱开源,似乎开源就是代表未来的趋势。
|
||||
|
||||
那么,是不是只选择开源工具就行了,不用考虑商业工具了呢?我觉得,这种想法也是比较片面的。
|
||||
|
||||
商业工具的优势一直都存在,比如,专业性、安全性、扩展性、技术支持力度等。其实,很多开源工具都有商业版本。
|
||||
|
||||
比如,很多公司即便有开源的Nexus,制品管理工具Artifactory也都是标配。因为,Artifactory无论是在支持的制品类型、分布式部署、附加制品安全漏洞检查,还是在与外部工具的集成等方面,都有着明显的优势。
|
||||
|
||||
另外,像Jira这种需求和缺陷管理工具,与Confluence深度集成的话,足够满足绝大多数公司的需求。
|
||||
|
||||
再举个例子,安卓开发最常见的Gradle工具,它的商业版本可以直接让你的编译速度提升一个数量级。在最开始时,你可能觉得够用就行,但是当你开始追求极致效率的时候,这些都是核心竞争力。
|
||||
|
||||
选择商业工具的理由有很多,不选的理由大多就是一个字:贵。针对这个问题,我要说的是,**要分清一笔支出到底是成本,还是投资**。
|
||||
|
||||
就跟购买黄金一样,虽然也花了钱,但这是一笔投资,未来可以保值和增值,甚至是变现。对于商业工具来说,也是同样的道理。如果一款商业工具可以大幅提升团队效率,最后的产出可能远超最开始的投资。如果我们组建一个团队,仿照商业工具,开发一套自研工具,重复造轮子的成本也可能一点不少。所以,重点就是要看怎么算这笔账。
|
||||
|
||||
## 阶段二:从小到大
|
||||
|
||||
经过了第一个阶段,企业交付链路上的工具基本都已经齐全了。团队对于工具的需求开始从够用到好用进行转变。另外,随着业务发展,团队扩大,差异化需求也成了摆在面前的问题。再加上,人和数据都越来越多,工具的重要性与日俱增。
|
||||
|
||||
那么,工具的稳定性、可靠性,以及大规模使用的性能问题,也开始凸显出来。
|
||||
|
||||
对于这个阶段,**我给你的建议是:使用半自建工具和定制商业工具,来解决自己的问题**。
|
||||
|
||||
所谓半自建工具,大多数情况下,还是基于开源工具的二次开发,或者是对开源工具进行一次封装,在开源工具上面实现需要的业务逻辑和交互界面。
|
||||
|
||||
比如,基于Jenkins封装一套自己的构建打包平台,完全可以利用Jenkins API和插件扩展实现。我附上了一幅架构示意图,你可以参考一下。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/fa/de/fad880b4dbd8464e3ccd37886f42c0de.png" alt="">
|
||||
|
||||
那么,半自建工具有哪些注意事项呢?虽然各个领域的工具职能千差万别,但从我的经验来看,主要有两点:**设计时给扩展留出空间;实现时关注元数据治理**。
|
||||
|
||||
### 设计时给扩展留出空间
|
||||
|
||||
刚开始建设平台的时候,很容易就事论事,眼前有什么问题,就提供什么功能。这固然是比较务实的态度,但对于平台而言,还是要有顶层设计,给未来留出扩展性。这么说可能比较抽象,我来给你举几个实际的例子,也是我们之前踩过的“坑”。
|
||||
|
||||
**案例一:**
|
||||
|
||||
平台的初期设计没有考虑租户的特性,只是为了满足单一业务的使用。当功能比较成熟,想要对外输出的时候,我们发现,要重新在更高的维度插入租户,导致系统需要进行大幅改造,不仅功能页面需要调整,连权限模型都要重新设计。
|
||||
|
||||
如果在设计平台之初,就考虑到未来的扩展需求,把单一业务实现为一个平台租户,会不会更好些呢?
|
||||
|
||||
**案例二:**
|
||||
|
||||
为了满足快速上线的需要,我们对Jenkins进行了简单封装,实现了在线打包平台。但是,打包页面的参数都“写死”在了页面中。另外,每接入一个项目,就需要单独实现一个页面。后来,面对上百个应用的接入所带来的差异化需求,平台只能推倒重来。
|
||||
|
||||
如果最开始在设计的时候,就采用接口获取的方式,将参数实现配置化,会不会更好些呢?
|
||||
|
||||
除此之外,在技术选型的时候,前后端分离的开发方式、主流的技术栈选型、一些典型的设计模式、相对统一的语言类型,其实都有助于平台空间的后续扩展。
|
||||
|
||||
**功能可以快速迭代,人员可以快速进入团队,形成战斗力,在设计平台的时候,这些都是需要思考的问题**。
|
||||
|
||||
当然,**顶层规划,不代表过度设计**。我只是说,要在可以预见的范围内,预留一些空间,从而规避后期的尴尬。
|
||||
|
||||
### 实现时关注元数据治理
|
||||
|
||||
所谓元数据,也就是常说的meta-data,可以理解为钥匙链,这些数据可以串起整个平台的数据结构。比如应用名称、模块名称、安全ID等等。
|
||||
|
||||
各个平台在组织数据结构的时候,都需要用到这些元数据,而且一旦使用了,轻易都不好改变。因为,在数据模型里面,这些元数据很有可能已经作为各种主键、外键的约束存在了。
|
||||
|
||||
对于单一平台来说,怎么维护这些元数据,都没什么大问题,但是,对于后续平台间的打通而言,这些元数据就成了一种标准语言。如果平台间的语言不通,就需要加入大量的翻译处理过程,这就导致系统性耦合加大,连接变得脆弱。
|
||||
|
||||
比如,同样是购物车模块,在我的平台里面叫购物车,而在你的平台里面叫shopping-cart,而且还按照平台划分,比如shopping-cart-android、shopping-cart-ios,甚至还有一些特性维度,比如shopping-cart-feature1等等。显然,想让两边的数据对齐,并不容易。
|
||||
|
||||
**当然,元数据的治理并不是单一平台能够解决的事情,这同样需要顶层规划**。
|
||||
|
||||
比如,在公司内部建立统一的CMDB,在其中统一管理应用信息。或者,建立应用创建审批流程,通用一个标准化流程,来管控应用的生命周期,同时管理应用的基础信息。这些都属于技术债务,做得越晚,还债的成本就越高。
|
||||
|
||||
## 阶段三:从繁到简
|
||||
|
||||
到了第三个阶段,恭喜你已经在DevOps平台建设方面有了一定的积累,在各个垂直领域也积累了成功案例。那么,在这个阶段,我们要解决的主要问题有3点:
|
||||
|
||||
- 平台太多。做一件事情,需要各种切来切去;
|
||||
- 平台太复杂。想要实现一个功能,需要对相关人员进行专业培训,他们才能做对;
|
||||
- 平台价值说不清。比如,使用平台,能带来多大价值?能给团队和业务带来多大贡献?
|
||||
|
||||
对于这个阶段,**我给你的建议是:使用整合工具来化繁为简,统一界面,简化操作,有效度量。**
|
||||
|
||||
整合工具,就是包含了开源工具、半自研工具、商业工具的集合。
|
||||
|
||||
**你要提供的不再是一个工具,而是一整套的解决方案;不是解决一个问题,而是解决交付过程中方方面面的问题。**
|
||||
|
||||
### 企业工具平台治理
|
||||
|
||||
如果最开始没有一个顶层规划,到了这个时候,企业内部大大小小的工具平台应该有很多。你需要做的第一步,就是**平台化治理工作**。
|
||||
|
||||
首先,你要识别出来有哪些工具平台,使用情况是怎样的,比如有哪些业务在使用,实现了哪些功能。
|
||||
|
||||
如果要把所有工具平台收编起来,这不是一件容易的事情,甚至超出了技术的范畴。尤其是对很多大企业来说,工具平台是很多团队的根基,如果不需要这个平台,就意味着团队的重心也得调整。
|
||||
|
||||
所以,我给你的第一条建议是比较温和可行的,那就是,**找到软件交付的主路径**。用一个平台覆盖这条主路径,从而串联各个单点上的能力,让一些真正好的平台能够脱颖而出。而要做到这个事情,就需要**持续交付流水线**了。
|
||||
|
||||
这些年来,我一直在从事持续交付平台的建设,也总结了很多经验。我会在后面的内容中,跟你好好聊聊,如何设计一个现代的持续交付流水线平台。
|
||||
|
||||
流水线平台与一体化平台之间,还是有很大差距的。毕竟,各种工具平台的设计思路、操作路径、界面风格,差别很大。
|
||||
|
||||
所以,在实际操作的过程中,我给你的第二条建议就是,**区分平台和工具,让平台脱颖而出**。
|
||||
|
||||
比如,测试环境存在大量的工具,而一整套测试平台,实际上可以满足测试方方面面的需求,也就是说,测试人员只要在这个平台上工作就够了。当企业内部繁杂的工具收敛为几个核心平台之后,对于用户来说,就减少了界面切换的场景,可以通过平台和平台对接完成日常工作。
|
||||
|
||||
### 打造自服务的工具平台
|
||||
|
||||
到了这个阶段,**自服务**就成了平台建设的核心理念。
|
||||
|
||||
**所谓自服务,就是用户可以自行登录平台实现自己的操作,查看自己关心的数据,获取有效的信息**。
|
||||
|
||||
而想要实现自服务,**简化操作**是必经之路。说白了,如果一件事情只要一键就能完成,这才是真正地实现了自服务。
|
||||
|
||||
这么说可能有点夸张。但是,打破职能间的壁垒,实现跨职能的赋能,依靠的就是平台的自服务能力。很多时候,当你在埋怨“平台设计得这么简单,为啥还是有人不会用”的时候,其实这只能说明一个问题,就是**平台依然不够简单**。
|
||||
|
||||
之前,Jenkins社区就发起过一个项目,叫作“5 Click,5 Minutes”,意思是希望用户只需要5次点击,花5分钟时间,就能完成一个Jenkins服务的建立。
|
||||
|
||||
这个项目的结果,就是现在的Jenkins创建导航,通过把建立服务的成本降到最低,从而帮助更多的用户上手使用。
|
||||
|
||||
你看,用户体验是否简单,与技术是否高深无关,重点在于是否能够换位思考。所以,在建设平台的时候,要始终保有一份同理心。
|
||||
|
||||
## 总结
|
||||
|
||||
企业内部的平台化建设是个长期问题,如果你要问我,企业要建设DevOps平台,有什么经验总结吗?我的回答就是“四化”:**标准化、自动化、服务化和数据化**。实际上,这些也是指导平台建设的核心理念。
|
||||
|
||||
- 标准化:一切皆有规则,一切皆有标准;
|
||||
- 自动化:干掉一切不必要的手工操作环节,能一键完成的,绝不操作两次;
|
||||
- 服务化:面向用户设计,而不是面向专家设计,让每个人都能在没有外界依赖的前提下,完成自己的工作;
|
||||
- 数据化:对数据进行收集、汇总、分析和展示,让客观数据呈现出来,让数据指导持续改进。
|
||||
|
||||
## 思考题
|
||||
|
||||
最后,关于平台化建设,你有什么私藏的好工具吗?可以分享一下吗?
|
||||
|
||||
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。
|
||||
|
||||
|
||||
128
极客时间专栏/geek/DevOps实战笔记/平台工具篇/22 | 产品设计之道:DevOps产品设计的五个层次.md
Normal file
128
极客时间专栏/geek/DevOps实战笔记/平台工具篇/22 | 产品设计之道:DevOps产品设计的五个层次.md
Normal file
@@ -0,0 +1,128 @@
|
||||
<audio id="audio" title="22 | 产品设计之道:DevOps产品设计的五个层次" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/e8/e1/e8639c970b8feb98631186660bd31de1.mp3"></audio>
|
||||
|
||||
你好,我是石雪峰。
|
||||
|
||||
在上一讲中,我们聊到了企业DevOps平台建设的三个阶段。那么,一个平台产品到底做到什么样,才算是好的呢?不知道你有没有想过这个问题,反正做产品的这些年来,我一直都在思考这个事儿。直到我听到了梁宁的专栏里面讲到的用户体验的五层要素,才发现,**无论什么产品,其实都是为了解决一群特定的人在特定场景的特定问题**。
|
||||
|
||||
那么,回到我们的DevOps产品,我们可以借鉴一下梁宁老师的思路,来看看DevOps产品设计体验的五个层次:**战略存在层、能力圈层、资源结构层、角色框架层和感知层**。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/fd/8c/fd05c31feebb1fd92c845a9347e5cd8c.png" alt="">
|
||||
|
||||
这么多专有名词一股脑地蹦出来,估计你头都大了吧?没关系,接下来我会逐一解释一下。
|
||||
|
||||
## 第一个层次:战略存在层
|
||||
|
||||
在决定开发一个DevOps产品的时候,我们首先要回答的根本问题就是,这个产品解决了什么样的痛点问题?换句话说,我们希望用户通过这个产品得到什么?显然,目标用户和痛点问题的不同,会从根本上导致两套DevOps产品之间相距甚远。
|
||||
|
||||
举个例子,业界很多大公司在内部深耕DevOps平台很多年,有非常多很好的实践。但是,当他们准备把这些内部平台对外开放,提供给C端用户使用的时候,会发现存在着严重的水土不服问题。
|
||||
|
||||
有些时候,内外部产品团队有独立的两套产品,对外提供的产品版本甚至比对内的版本要差上几年。这就是用户群体的不同造成的。C端用户相对轻量级,需要的功能大多在具体的点上,而企业内部因为多年的积累,有大量的固有流程、系统、规则需要兼顾。所以,整套产品很重,甚至是完全封闭的一套体系,难以跟用户现有的平台进行打通。
|
||||
|
||||
所以,我见过很多产品团队,他们对自己初期的产品定位并非在用户需求本身,而是在同类竞争对手身上。也就是说,他们先从模仿业界做得比较好的同类产品开始,从产品设计、功能模块到用户交互等,一股脑地参考同类产品,美其名曰“至少先赶上业界主流水平再说”。于是乎,团队开足马力在这条路上渐行渐远。
|
||||
|
||||
当然,借鉴同类产品的先进经验,这个做法本身并没有什么问题,毕竟,这些经验已经经过市场和用户的检验,至少走偏的风险不大。可问题是,**同类产品的经验并不能作为自己产品的战略**。
|
||||
|
||||
亚马逊的CEO贝佐斯就说过一句特别著名的话:“**要把战略建立在不变的事物上。**”比如,如果竞争对手推出了一项新的功能,或者他们改变了自己的方向,那么我们的战略是否要随之变化,继续迎头赶上呢?这是一个值得产品团队深思的问题。
|
||||
|
||||
以我所在的电商行业为例,我们的产品始终在强调用户体验,但好的产品设计和用户体验绝不是因为友商做了什么花哨的改变,而是始终着眼于那些长久不变的事物之上,也就是**多、快、好、省**。因为,不管什么时候,用户选择在你的平台购物,肯定不会是因为你的产品比其他家的要贵吧?同样的道理,对于DevOps产品来说,也是这样。
|
||||
|
||||
那么,有没有永远不变的内容可以作为DevOps产品的战略定位呢?显然也是有的,那就是:**效率、质量、成本和安全**。归根结底,**产品的任何功能都是要为战略服务的**。比如,构建加速,要解决的就是效率问题,而弹性资源池,自然更加关注成本方面的问题。在任何时候,如果你的产品能在某个点上做到极致,那么恭喜你,你就找到了自己产品的立身之本。
|
||||
|
||||
**明确目标用户,定义刚性需求,服务于典型场景,并最终在某一个点上突出重围,这就是我们在准备做DevOps产品的时候首先要想清楚的问题**。无论是对内产品,还是对外产品,道理都是一样的。
|
||||
|
||||
## 第二个层次:能力圈层
|
||||
|
||||
战略很好,但是不能当饭吃。为了实现战略目标,我们需要做点什么,这就是需要产品化的能力。所谓产品化,就是将一个战略或者想法通过产品分析、设计、实验并最终落地的过程。
|
||||
|
||||
很少公司会有魄力一上来就投入百人团队开发DevOps产品,大多数情况下,都是一两个有志青年搭建起草台班子,从一个最简单的功能开始做起。资源的稀缺性决定了我们永远处于喂不饱的状态,而在这个时候,最重要的就是所有为,有所不为。
|
||||
|
||||
我们一定要明确,哪些是自己产品的核心竞争力,而哪些是我们的边界和底线,现阶段是不会去触碰的。当我们用这样一个圈子把自己框起来的时候,至少在短期内,目标是可以聚焦的。
|
||||
|
||||
当然,随着产品的价值体现,资源会随之而扩充,这个时候,我们就可以调整、扩大自己的能力圈。但说到底,**这些能力都是为了实现产品战略而存在的,这一点永远不要忘记**。
|
||||
|
||||
我还是拿个实际的案例来说明这个问题。之前在企业内部启动持续交付流水线项目的时候,我们这个草台班子总共才4个人,而我们面对的是千人的协同开发团队。在每个业务领域内部,都有很多的产品工具平台在提供服务,缺少的就是平台间的打通。
|
||||
|
||||
对于企业而言,一套完整覆盖端到端的研发协作平台看起来很美,但是,要做这么一套东西,投入巨大不说,还会同现有的工具平台产生冲突,这样就变成了一个零和游戏。
|
||||
|
||||
所谓零和游戏,就是所有玩家资源总和保持固定,只是在游戏过程中,资源的分配方式发生了改变。
|
||||
|
||||
就现在的这个例子来说,如果平台潜在用户总量是一定的,有一方向前一步,必定有另外一方向后一步,这显然不是我们这个“小虾米团队”现阶段能做到的。
|
||||
|
||||
所以,我们就给自己的产品定义了一个能力圈,它的边界就在于不去替换现有的工具平台,而是只专注于做链路打通的事情。这样一来,既有平台仍然可以单独提供服务,也可以通过标准化的方式提供插件,对接到我们的平台上来,我们的平台就成了它们的另外一套入口,有助于用户规模的扩大。
|
||||
|
||||
而对于我们自己来说,这些平台能力的注入,也扩展了我们自己的能力圈外沿,这些既有平台的用户就成了我们的潜在用户群体。这种双赢的模式,后来被证明是行之有效的,平台获得了很大的成功。
|
||||
|
||||
在跟很多朋友交流产品思路的时候,我总是把**主航道和护城河理论**挂在嘴边。**所谓主航道,就是产品的核心能力,直接反射了产品战略的具体落地方式**。对于流水线产品来说,这个能力来源于对软件交付过程的覆盖,而不论你将来开发任何产品,这条主路径都是无法回避的。那么,产品就有了茁壮成长的环境和土壤。而**护城河就是你这个产品的不可替代性,或者是为了替代你的产品需要付出的高额代价**。
|
||||
|
||||
还是引用流水线产品的例子,我们的护城河一方面来源于用户数据的沉淀,另一方面就在于这些外部能力的接入。你看,随着接入平台的增多,我们自身产品的护城河也越发难以逾越,这就是对于能力圈更加长远的考量了。
|
||||
|
||||
## 第三个层次:资源结构层
|
||||
|
||||
为什么做和做什么的问题,我们已经解决了,接下来,我们就要掂量掂量自己在资源方面有哪些优势了。
|
||||
|
||||
资源这个事儿吧,就像刚才提到的,永远是稀缺的,但这对于所有人来说都是公平的。所以,**对资源的整合和调动能力就成了核心竞争力**。当你没有竞争对手的时候,用户选择你的产品并不是什么难事,因为既然解决了一个痛点问题,又没有更好的选择,用一用也无妨。
|
||||
|
||||
可现实情况是,无论是企业内部,还是外部,我们都身处在一个充满竞争的环境,最开始能够吸引用户的点,说起来也很可笑,很多时候就在于让用户占了你的资源的便宜,也就是用户认为你的产品有一些资源是他们不具备的。
|
||||
|
||||
举个例子,在很长一段时间内,App的构建和打包都是基于本地的一台电脑来做的,这样做的风险不用多说,但是大家也没什么更好的选择。尤其是面对iOS这种封闭的生态环境,想要实现虚拟化、动态化也不是一句话的事情,甚至有可能触犯苹果的规则红线。
|
||||
|
||||
这时,如果你的产品申请了一批服务器,并且以标准化的方式部署在了生产机房,那么这些资源就成了产品的核心能力之一。
|
||||
|
||||
随着越来越多的用户跑来占便宜,产品对于大规模资源的整合能力就会不断提升,从而进一步压低平均使用成本,这就形成了一个正向循环。
|
||||
|
||||
产品蕴含的资源除了这些看得见、摸得着的机器以外,还有很多方面,比如,硬实力方面的,像速度快、机器多、单一领域技术沉淀丰富,又比如,强制性的,像审批入口、安全规则,还有软性的用户习惯,数据积累等等。
|
||||
|
||||
对于内部DevOps产品来说,还有一项资源是至关重要的,那就是**领导支持**。这一点我们已经在专栏[第6讲](https://time.geekbang.org/column/article/154695)中深入讨论过了,我就不再赘述了。
|
||||
|
||||
## 第四个层次:角色框架层
|
||||
|
||||
当用户开始使用你的产品时,不要忘了,他们是来解决问题的,而每一个问题背后都存在一个场景,以及在这个场景中用户的角色。脱离这个场景和角色的设定,单纯讨论问题是没有意义的。
|
||||
|
||||
所以,我们总说,**要站在用户的角度来看待问题,要在他们当时的场景下,去解决他们的问题,而不是远远地观望着,甚至以上帝视角俯视全局**。
|
||||
|
||||
举个例子,当你和其他部门在为了一个功能设计争得面红耳赤,差点就要真人PK的时候,你们的领导走进了会议室,你猜怎样,瞬间气氛就缓和起来,似乎刚才什么也没发生过。这难道是因为我们的情绪管理能力很强吗?其实不然,这主要是因为我们身处的场景发生了变化,我们的角色也发生了改变。
|
||||
|
||||
再举个产品的例子,当我们在开发流水线产品的时候,为了满足用户不同分支构建任务的需求,我们提供了分支参数的功能。但是,在收集反馈的时候,全都是负面声音,难道这是个“伪需求”吗?
|
||||
|
||||
其实不是。通过实际数据,我们可以看到,很多用户已经开始使用这个功能了。这不是得了便宜又卖乖吗?问题就在于,**我们没有站在用户当时的角色框架下,来思考这个问题**。
|
||||
|
||||
因为,分支功能是需要用户手动输入的,但分支名又长又容易出错,每次都要从另外一个系统或者本地复制粘贴。当这个场景出现一次的时候并不是什么大事,但是,如果每个人每天都要做几十次的话,这就是大问题了。其实,解决思路很简单,增加历史信息或者自动关联的功能就可以啦。
|
||||
|
||||
所以你看,有时候我们不需要多么伟大的创造和颠覆,基于核心场景的微创新也能起到正向的作用。
|
||||
|
||||
说到底,其实就是一句话:**不要让你的产品只有专业人士才会使用。**
|
||||
|
||||
为了兼容灵活性,很多产品都提供了很多配置,但是,对于当时这个场景来说,绝大多数配置,都是没人关心的。**产品应该提供抽象能力屏蔽很多细节,而不是暴露很多细节,甚至,好的产品自身就是使用说明书**。这一点,在注意力变得格外稀缺的现在,重要性不可忽视。
|
||||
|
||||
## 第五个层次:感知层
|
||||
|
||||
现在,我们来看看最后一个层次:**感知层**,这也是距离用户最近的一个层次。
|
||||
|
||||
不可否认,这是一个看脸的时代,但是产品终究是给人用的,而不是给人看的。所以,很多人甚至强调,对于内部产品来说,UI完全不重要,家丑不外扬就好了。
|
||||
|
||||
可是,换位思考一下,你希望自己每天打交道的是一个设计凌乱、完全没有美感的产品吗?
|
||||
|
||||
答案很有可能是否定的。可这对于很多DevOps的产品经理来说,是最难的一点。这是因为,没有人天生就是DevOps产品经理,很多人都是半路出家,做开发的,做测试的,甚至是当老板的。
|
||||
|
||||
让不专业的人做专业的事情,结果可想而知,好多产品功能的设计都堪称是“反人类”的。
|
||||
|
||||
关于这个层次,我提供两点建议:
|
||||
|
||||
<li>
|
||||
**多跟前端工程师交流**。现在的前端框架已经非常成熟了,基于模板,我们可以快速地搭建出一个平台。而且,模板的框架自身,也蕴含着很多的设计思想。
|
||||
</li>
|
||||
<li>
|
||||
**多学习一些基本的设计原则**。你可以参考[Element官网](https://element.eleme.cn/)上的设计理念章节,里面谈到了**一致、反馈、效率和可控**四个方面,每个方面又涉及很多细节。参照着成熟的产品,再对照这些基本设计理念,你放心,你会进步神速的。
|
||||
</li>
|
||||
|
||||
## 总结
|
||||
|
||||
今天,我们介绍了DevOps产品设计的五个层次,包括:战略存在层、能力圈层、资源结构层、角色框架层和感知层。其实,当用户吐槽你的产品,或者产品迟迟没有提升的时候,我们可能就要沉下心来,对照着这五个层次,来看看问题到底出在哪里了。
|
||||
|
||||
## 思考题
|
||||
|
||||
你有用到过什么好的DevOps产品吗?它们有哪些功能,让你眼前一亮,不由得为这个产品点赞吗?
|
||||
|
||||
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,欢迎你把文章分享给你的朋友。
|
||||
|
||||
|
||||
225
极客时间专栏/geek/DevOps实战笔记/平台工具篇/23 | 持续交付平台:现代流水线必备的十大特征(上).md
Normal file
225
极客时间专栏/geek/DevOps实战笔记/平台工具篇/23 | 持续交付平台:现代流水线必备的十大特征(上).md
Normal file
@@ -0,0 +1,225 @@
|
||||
<audio id="audio" title="23 | 持续交付平台:现代流水线必备的十大特征(上)" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/ee/00/ee1ca66e80d23a855f2689b6d2ce1100.mp3"></audio>
|
||||
|
||||
你好,我是石雪峰。
|
||||
|
||||
作为DevOps工程实践的集大成者和软件交付的“理想国”,持续交付对企业的DevOps落地起到了举足轻重的作用。我接触过的企业全都在建设自己的流水线平台,由此可见,**流水线是持续交付中最核心的实践,也是持续交付实践最直接的体现**。
|
||||
|
||||
那么,如何建设一个现代流水线平台呢?这个平台,应该具备哪些特性呢?
|
||||
|
||||
根据我自己在企业内部建设落地流水线平台的经验,以及业界各家公司的平台设计理念,我提取、总结了现代流水线设计的十大特性。
|
||||
|
||||
在接下来的两讲中,我会结合平台设计,给你逐一拆解这些特性背后的理念,以及如何把这些理念落地在平台设计中。我把这十个特性汇总在了下面的这张图片里。今天,我先给你介绍下前五个特性。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/dd/b0/dd73fb488bc5fb93e0148107e1e470b0.png" alt="">
|
||||
|
||||
## 特性一:打造平台而非能力中心
|
||||
|
||||
与其他DevOps平台相比,流水线平台有一个非常典型的特征,那就是,**它是唯一一个贯穿软件交付端到端完整流程的平台**。正因为这样,流水线平台承载了整个软件交付过程方方面面的能力,比如,持续集成能力、自动化测试能力、部署发布能力,甚至是人工审批的能力等。
|
||||
|
||||
那么,我们把软件交付过程中所需要的能力都直接做到流水线平台上,是不是就可以了呢?
|
||||
|
||||
这个想法是好的,但是在企业中,这并不具备可操作性。因为软件交付的每一个环节都是一项非常专业的工作,比如,仅仅是自动化测试能力这一项做好,就需要一个具备专业技能的团队的长期投入。
|
||||
|
||||
而且,把所有能力都做到流水线平台中,会使平台变得非常臃肿。再说了,我们也很难组建一个这么大的团队,来实现这个想法。
|
||||
|
||||
另外,企业的DevOps平台建设并不是一两天的事情。每家企业内部都有很多固有平台,这些平台长期存在,已经成为了团队软件交付日常操作的一部分。如果全部推倒重来,不仅会打破团队的习惯,影响短期效率,还会带来重复建设的巨大成本,这并不利于流水线平台的快速落地。
|
||||
|
||||
那么,既然这条路走不通,流水线平台如何定位才比较合理呢?我认为,**正确的做法是,将持续交付流水线平台和垂直业务平台分开,并定义彼此的边界**。
|
||||
|
||||
所谓的垂直业务平台,就是指**单一专业领域的能力平台**,比如自动化测试平台、代码质量平台、运维发布平台等等,这些也是软件交付团队日常打交道最频繁的平台。
|
||||
|
||||
流水线平台只专注于**流程编排、过程可视化,并提供底层可复用的基础能力**。比如,像是运行资源池、用户权限管控、任务编排调度流程等等。
|
||||
|
||||
垂直业务平台则专注于**专业能力的建设、一些核心业务的逻辑处理、局部环节的精细化数据管理等**。垂直业务平台可以独立对外服务,也可以以插件的形式,将平台能力提供给流水线平台。
|
||||
|
||||
这样一来,我们就可以**快速复用现有的能力,做到最小成本的建设**。随着能力的不断扩展,流水线平台支持的交付流程也会变得非常灵活。
|
||||
|
||||
借用《持续交付2.0》中的一句话来说,**流水线平台仅作为任务的调度者、执行者和记录者,并不需要侵入垂直业务平台内部**。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/c9/fd/c9f4c396592a37694fbbe05e354ea7fd.png" alt="">
|
||||
|
||||
这样设计的好处很明显。
|
||||
|
||||
从流水线平台的角度来看,通过集成和复用现有的垂直业务能力,可以快速拓展能力图谱,满足不同用户的需求。
|
||||
|
||||
从垂直业务平台的角度来看,它们可以持续向技术纵深方向发展,把每一块的能力都做精、做透,这有助于企业积累核心竞争力。另外,流水线可以将更多用户导流到平台中,让垂直业务平台接触更多的用户使用场景。
|
||||
|
||||
不仅如此,在执行过程中,流水线携带了大量的软件开发过程信息,比如本次任务包含哪些需求,有哪些变更,这些信息可以在第一时间通知垂直业务平台。垂直业务平台拿到这些过程信息之后,可以通过精准测试等手段,大大提升运行效率。这里的核心就是**构建一个企业内部DevOps平台的良好生态**。
|
||||
|
||||
业界很多知名的软件设计都体现了这个思路。比如,Jenkins的插件中心、GitHub的Marketplace。它们背后的理念,都是基于平台,建立一种生态。
|
||||
|
||||
我之所以把这个特性放在第一个来介绍,就是因为,**这直接决定了流水线平台的定位和后续的设计理念**。关于具体怎么设计平台实现能力的快速接入,我会在第八个特性中进行深入介绍。
|
||||
|
||||
## 特性二:可编排和可视化
|
||||
|
||||
在现代软件开发中,多种技术栈并存,渐渐成为了一种常态。
|
||||
|
||||
举个最简单的例子,对于一个前后端分离的项目来说,前端技术栈和后端技术栈显然是不一样的;对于微服务风格的软件架构来说,每个模块都应该具备持续交付的能力。
|
||||
|
||||
所以,传统的标准化软件构建发布路径已经很难满足多样化开发模式的需要了。这样看来,流水线平台作为软件交付的过程载体,流程可编排的能力就变得必不可少了。
|
||||
|
||||
**所谓的流程可编排能力,就是指用户可以自行定义软件交付过程的每一个步骤,以及各个步骤之间的先后执行顺序**。说白了,就是“我的模块我做主,我需要增加哪些交付环节,我自己说了算”。
|
||||
|
||||
但是,很多现有的“流水线”平台采用的还是几个“写死”的固定阶段,比如构建、测试、发布,以至于即便有些技术栈不需要进行编译,也不能跳过这个环节。
|
||||
|
||||
我之前就见过一家企业,他们把生成版本标签的动作放在了上线检查阶段。我问了之后才知道,这个步骤没有地方可以放了,只能被临时扔在这里。你看,这样一来,整个交付过程看起来的样子和实际的样子可能并不一样,这显然不是可视化所期待的结果。
|
||||
|
||||
流程可编排,需要平台前端提供一个可视化的界面,来方便用户定义流水线过程。典型的方式就是,**将流水线过程定义为几个阶段,每个阶段按顺序执行。在每个阶段,可以按需添加步骤,这些步骤可以并行执行,也可以串行执行**。
|
||||
|
||||
前端将编排结果以一种标准化的格式进行保存(一般都是以JSON的形式),传递给后端处理。后端流程引擎需要对用户编排的内容进行翻译处理,并传递给执行器,来解释运行即可。
|
||||
|
||||
你可以参考一下下面这张流程编排的示意图。在实际运行的过程中,你可以点击每一个步骤,查看对应的运行结果、日志和状态信息。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/76/e1/765961df0fff0efd529cc5d1f70a62e1.png" alt="">
|
||||
|
||||
从表面上看,这主要是在考验平台前端的开发能力,但实际上,**编排的前提是系统提供了可编排的对象,这个对象一般称为原子**。
|
||||
|
||||
所谓原子,就是一个能完成一项具体的独立任务的组件。这些组件要具备一定的通用性,尽量与业务无关。
|
||||
|
||||
比如下载代码这个动作,无论是前端项目,还是后端项目,做的事情其实都差不多,**核心要实现的就是通过几个参数,完成从版本控制系统拉取代码的动作**。那么,这就很适合成为一项原子。
|
||||
|
||||
**原子的设计是流水线平台的精髓,因为原子体现了平台的通用性、可复用性和独立性**。
|
||||
|
||||
以我们比较熟悉的Jenkins为例,一个原子就是流水线中的一个代码片段。通过封装特性,将实现隐藏在函数实现内部,对外暴露调用方法。用户只需要知道如何使用,不需要关心内部实现。
|
||||
|
||||
要想自己实现一个原子,其实并不复杂,在Jenkins中添加一段Groovy代码就行了。示例代码如下:
|
||||
|
||||
```
|
||||
// sample_atom_entrance.groovy
|
||||
def Sample_Atom(Map map) {
|
||||
new SampleAtom(this).callExecution(map)
|
||||
}
|
||||
|
||||
|
||||
// src/com/sample/atoms/SampleAtom.groovy
|
||||
class SampleAtom extends AbstractAtom {
|
||||
|
||||
|
||||
SampleAtom(steps) {
|
||||
super(steps)
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
def execute() {
|
||||
// Override execute function from AbstractAtom
|
||||
useAtom()
|
||||
}
|
||||
|
||||
private def useAtom(){
|
||||
steps.echo "RUNNING SAMPLE ATOM FUNCTION..."
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## 特性三:流水线即代码
|
||||
|
||||
这些年来,“什么什么即代码”的理念已经深入人心了。在应用配置领域,有 Configuration As Code,在服务器领域,有 Infrastructure As Code……流水线的设计与实现,同样需要做到 Pipeline As Code,也就是流水线即代码。
|
||||
|
||||
比如,Jenkins 2.0 中引入的 Jenkinsfile 就是一个典型的实现。另外,Gitlab中提供的GitlabCI,同样是通过一种代码化的方式和描述式的语言,来展示流水线的业务逻辑和运行方式。
|
||||
|
||||
流水线代码化的好处不言而喻:**借助版本控制系统的强大功能,流水线代码和业务代码一样纳入版本控制系统,可以简单追溯每次流水线的变更记录**。
|
||||
|
||||
在执行流水线的过程中,如果流水线配置发生了变化,同样需要体现在本次流水线的变更日志里面。甚至是,在版本的Release Notes中也增加流水线、环境的变更记录信息。一旦发生异常,这些信息会大大提升问题的定位速度。
|
||||
|
||||
当然,如果只是想要实现流水线变更追溯,你也可以采用其他方式。比如,将流水线配置存放在后台数据库中,并在每次流水线任务执行时,记录当时数据库中的版本信息。
|
||||
|
||||
实际上,流水线即代码的好处远不止于此。因为**它大大地简化了流水线的配置成本,和原子一样,是构成现代流水线的另外一个支柱**。
|
||||
|
||||
我跟你分享一个流水线即代码的示例。在这个例子中,你可以看到,整个软件交付流程,都以一种非常清晰的方式描述出来了。即便你不是流水线的专家,也能看懂和使用。
|
||||
|
||||
```
|
||||
image: maven:latest
|
||||
|
||||
|
||||
stages:
|
||||
- build
|
||||
- test
|
||||
- run
|
||||
|
||||
|
||||
variables:
|
||||
MAVEN_CLI_OPTS: "--batch-mode"
|
||||
GITLAB_BASE_URL: "https://gitlab.com"
|
||||
DEP_PROJECT_ID: 8873767
|
||||
|
||||
|
||||
build:
|
||||
stage: build
|
||||
script:
|
||||
- mvn $MAVEN_CLI_OPTS compile
|
||||
|
||||
|
||||
test:
|
||||
stage: test
|
||||
script:
|
||||
- mvn $MAVEN_CLI_OPTS test
|
||||
|
||||
|
||||
run:
|
||||
stage: run
|
||||
script:
|
||||
- mvn $MAVEN_CLI_OPTS package
|
||||
- mvn $MAVEN_CLI_OPTS exec:java -Dexec.mainClass="com.example.app.A
|
||||
|
||||
```
|
||||
|
||||
## 特性四:流水线实例化
|
||||
|
||||
作为软件交付流程的建模,流水线跟面向对象语言里面的类和实例非常相似。一个类可以初始化多个对象,每个对象都有自己的内存空间,可以独立存在,流水线也要具备这种能力。
|
||||
|
||||
**首先,流水线需要支持参数化执行**。
|
||||
|
||||
通过输入不同的参数,控制流水线的运行结果,甚至是控制流水线的执行过程。
|
||||
|
||||
比如,一条流水线应该满足不同分支的构建需要,那么,这就需要将分支作为参数提取出来,在运行时,根据不同的需要,手动或者自动获取。
|
||||
|
||||
考虑到这种场景,在平台设计中,你可以事先约定一种参数的格式。这里定义的标准格式,就是**以“#”开头,后面加上参数名称**。通过在流水线模板中定义这样的参数,一个业务可以快速复用已有的流水线,不需要重新编排,只要修改运行参数即可。
|
||||
|
||||
**其次,流水线的每一次执行,都可以理解为是一个实例化的过程。**
|
||||
|
||||
每个实例基于执行时间点的流水线配置,生成一个快照,这个快照不会因为流水线配置的变更而变更。如果想要重新触发这次任务,就需要根据当时的快照运行,从而实现回溯历史的需求。
|
||||
|
||||
**最后,流水线需要支持并发执行能力。**
|
||||
|
||||
这就是说,流水线可以触发多次,生成多个运行实例。这考察的不仅是流水线的调度能力、队列能力,还有持久化数据的管理能力。
|
||||
|
||||
因为,每次执行都需要有独立的工作空间。为了加速流水线运行,需要在空间中完成静态数据的挂载,比如代码缓存、构建缓存等。有些流水线平台不支持并发,其实就是因为没有解决好这个问题。
|
||||
|
||||
## 特性五:有限支持原则
|
||||
|
||||
流水线的设计目标,应该是满足**大多数、常见场景下的快速**使用,并提供一定程度的定制化可扩展能力,而不是满足所有需求。
|
||||
|
||||
在设计流水线功能的时候,我们往往会陷入一个怪圈:我们想要去抽象一个通用的模型,满足所有的业务场景,但是我们会发现,业务总是有这样或者那样的特殊需求。这就像是拿着一张大网下水捞鱼,总是会有漏网之鱼,于是,网做得越来越大。对于平台来说,平台最后会变得非常复杂。
|
||||
|
||||
比如,拿最常见的安卓应用构建来说,目前绝大多数企业都在使用Gradle工具,通用命令其实只有两步:
|
||||
|
||||
```
|
||||
gradle clean
|
||||
gradle assemblerelease / gradle assembledebug
|
||||
|
||||
```
|
||||
|
||||
但是,在实际的业务场景中,应用A用到了Node.js,需要安装npm;应用B用到了Git-lfs大文件,需要先执行安装指令;应用C更甚,需要根据选项,配置执行Patch模式和完整打包模式。
|
||||
|
||||
如果试图在一个框架中满足所有人的需求,就会让配置和逻辑变得非常复杂。无论是开发实现,还是用户使用,都会变得难以上手。
|
||||
|
||||
以Jenkins原生的Xcode编译步骤为例,这个步骤提供了53个参数选项,满足了绝大多数场景的需求,但是也陷入到了参数的汪洋大海中。
|
||||
|
||||
所以,**流水线设计要提供有限的可能性,而非穷举所有变量因素**。
|
||||
|
||||
在设计参数接口的时候,我们要遵循“奥卡姆剃刀法则”,也就是,“如无必要,勿增实体”。如果有用户希望给原子增加一个变量参数,那么,我们首先要想的是,这个需求是不是90%的人都会用到的功能。如果不是,就不要轻易放在原子设计中。
|
||||
|
||||
你可能会问,这样的话,用户的差异化诉求,该如何满足呢?其实,这很简单,你可以**在平台中提供一些通用类原子能力**,比如,执行自定义脚本的能力、调用http接口的能力、用户自定义原子的能力,等等。只要能提供这些能力,就可以满足用户的差异化需求了。
|
||||
|
||||
## 总结
|
||||
|
||||
在这一讲中,我给你介绍了现代流水线设计的前五大特性,分别是打造平台而非能力中心、可编排和可视化、流水线即代码、流水线实例化,以及有限支持原则。在下一讲中,我会继续介绍剩余的五大特性,敬请期待。
|
||||
|
||||
## 思考题
|
||||
|
||||
你所在的企业有在使用流水线吗?你觉得,流水线还有什么必不可少的特性吗?
|
||||
|
||||
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,也欢迎你把文章分享给你的朋友。
|
||||
|
||||
|
||||
195
极客时间专栏/geek/DevOps实战笔记/平台工具篇/24 | 持续交付平台:现代流水线必备的十大特征(下).md
Normal file
195
极客时间专栏/geek/DevOps实战笔记/平台工具篇/24 | 持续交付平台:现代流水线必备的十大特征(下).md
Normal file
@@ -0,0 +1,195 @@
|
||||
<audio id="audio" title="24 | 持续交付平台:现代流水线必备的十大特征(下)" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/23/b4/2356db3d895ce9e66900ab057ef303b4.mp3"></audio>
|
||||
|
||||
你好,我是石雪峰。今天,我来接着跟你聊聊现代流水线必备的十大特性的下半部分,分别是流程可控、动静分离配置化、快速接入、内建质量门禁和数据采集聚合。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/dd/b0/dd73fb488bc5fb93e0148107e1e470b0.png" alt="">
|
||||
|
||||
## 特性六:流程可控
|
||||
|
||||
在上一讲中,我提到过,流水线是覆盖软件交付端到端完整过程的平台,也就是说,流水线的主要作用是**驱动软件交付过程的效率提升和状态可视化**。
|
||||
|
||||
在线下交流的时候,我发现,不少同学对这个概念的理解都存在着一些误区,他们觉得需要建设一条大而全的流水线,在这条流水线上完成软件交付的所有过程。
|
||||
|
||||
其实,流水线是要覆盖端到端的流程,但这并不是说,一定要有一条流水线跑通从代码提交开始到软件发布为止的全流程。实际上,在企业中,往往是多条流水线覆盖不同的环节,比如开发阶段流水线、集成阶段流水线,以及部署阶段流水线。这些流水线一起覆盖了整个软件交付流程。
|
||||
|
||||
这就体现了流水线的流程可控性,**流水线可以为了满足不同阶段的业务目标而存在,并且每条流水线上实现的功能都不相同**。为了达到这个目的,流水线需要支持多种触发方式,比如定时触发、手动触发、事件触发等。其中,**事件触发就是实现持续集成的一个非常重要的能力**。
|
||||
|
||||
以Gitlab为例,你可以在代码仓库中添加Webhook,Webhook的地址就是触发流水线任务的API,这个API可以通过Gitlab的API实现自动注册。
|
||||
|
||||
需要注意的是,**要实现Webhook的自动注册,访问Gitlab的账号时必须要有对应代码仓库的Master级别权限,否则是无法添加成功的**。
|
||||
|
||||
当注册完成Webhook,代码仓库捕获到对应的事件后,比如代码Push动作,会自动调用Webhook,并且将本次代码提交的基础信息(比如分支、提交人等)传递给注册地址。
|
||||
|
||||
流水线平台接收到接口访问后,可以根据规则过滤请求,最典型的就是**触发分支信息**。当满足规则条件后,则执行流水线任务,并将结果再次通过Gitlab的API写回到代码仓库中。这样一来,每次提交历史都会关联一个流水线的执行记录,可以用于辅助代码合并评审。
|
||||
|
||||
我画了一张流程图,它展示了刚刚我所描述的过程以及调用的接口信息。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/c0/e2/c06719043cb3a22f6dd7da3b71a044e2.png" alt="">
|
||||
|
||||
除了多种触发方式以外,流水线还需要支持人工审批。这也就是说,每个阶段的流转可以是自动的,上一阶段完成后,就自动执行下一阶段;也可以是手动执行的,必须经过人为确认才能继续执行,这里的人为确认需要配合权限的管控。
|
||||
|
||||
其实,人工审批的场景在软件交付过程中非常常见。如果是自建流程引擎,人工审批就不难实现,但是,如果你是基于Jenkins来实现这个过程,虽然Jenkins提供了input方法来实现人为审批的功能,但我还是比较推荐你自己通过**扩展代码**来实现。比如,将每个原子的执行过程抽象为before()、execute() 和 after() 三个阶段,可以将人工审批的逻辑写在before()或者after()方法中。
|
||||
|
||||
这样一来,对于所有原子都可以默认执行基类方法,从而获得人工审批的能力。是否开启人工审批,可以通过原子配置中的参数实现。你就不需要在每个原子中人工注入input方法了,流水线的执行过程会更加清晰。
|
||||
|
||||
我给你分享一个抽象原子类的设计实现,如下面的代码所示:
|
||||
|
||||
```
|
||||
abstract class AbstractAtom extends AtomExecution {
|
||||
def atomExecution() {
|
||||
this.beforeAtomExecution()
|
||||
// 原子预处理步骤,你可以将通用执行逻辑,比如人工审批等写在这里
|
||||
echo('AtomBefore')
|
||||
before()
|
||||
// 原子主体核心逻辑
|
||||
echo('AtomExecution')
|
||||
execute()
|
||||
// 原子后处理步骤,你可以将通用执行逻辑,比如人工审批等写在这里
|
||||
echo('AtomAfter')
|
||||
after()
|
||||
this.afterAtomExecution()
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## 特性七:动静分离配置化
|
||||
|
||||
流水线的灵活性不仅体现在流程可编排、流程可控方面,每一个原子都需要持续迭代功能。那么,如何在不改变代码的情况下,实现原子的动态化配置呢?
|
||||
|
||||
这就需要用到**动静分离**的设计方法了。那么,什么是动静分离呢?
|
||||
|
||||
其实,**动静分离就是一种配置化的实现方式**。这就是指,将需要频繁调整或者用户自定义的内容,保存在一个静态的配置文件中。然后,系统加载时通过读取接口获取配置数据,并动态生成用户可见的交互界面。
|
||||
|
||||
你可能觉得有点抽象,我来给你举个例子。你可以看一下下面这张截图。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/50/49/5096345bd515d2223146e9bbf88e5f49.png" alt="">
|
||||
|
||||
如果我想对某一个原子扩展一个新的功能,提供一个新的用户配置参数,传统的做法就是在前端页面中增加一段html代码。这样的话,原子功能的每一次变更都需要前端配合调整,原子的独立性就不复存在了,而是跟页面强耦合在一起。
|
||||
|
||||
另外,前端页面加入了这么多业务逻辑,如果哪天需要同时兼容不同的原子版本,那么前端页面也需要保存两套。一两个应用这么玩也就罢了,如果有上百个应用,那简直没法想象。
|
||||
|
||||
那么,具体要怎么做呢?**最重要的就是定义一套标准的原子数据结构**。
|
||||
|
||||
比如,在上面这张图的左侧部分,我给你提供了一个参考结构。对于所有的原子来说,它对外暴露的功能都是通过这套标准化的方式来定义的。前端在加载原子的时候,后端提供的接口获取原子的数据结构,并按照约定的参数类型,渲染成不同的控件类型。
|
||||
|
||||
不仅如此,控件的属性也可以灵活调整,比如控件的默认值是什么,控件是否属于必填项,是否存在可输入字符限制等等。那么,当你想增加一个新的参数的时候,只需要修改原子配置,而不需要修改前端代码。**结构定义和具体实现的分离,可以大幅简化原子升级的灵活性**。
|
||||
|
||||
无论在原子结构设计,还是前后端交互等领域,**定义一个通用的数据结构是设计标准化的系统的最佳实践**。
|
||||
|
||||
对于流水线平台来说,除了原子,很多地方都会用到配置化的方式。比如,系统报告中体现的字段和图表类型等,就是为了满足用户差异化的需求。而且,将配置纳入版本控制,你也可以快速查询原子配置的变更记录,达到一切变更皆可追溯的目标。
|
||||
|
||||
## 特性八:快速接入
|
||||
|
||||
前面我提到过,流水线的很多能力都不是自己提供的,而是来源于垂直业务平台。那么,**在建设流水线平台的时候,能否快速地实现外部平台能力的接入,就成了一个必须要解决的问题**。
|
||||
|
||||
**经典的解决方式就是提供一种插件机制,来实现平台能力的接入**。比如,Jenkins平台就是通过这种方式,建立了非常强大的插件生态。但是,如果每个平台的接入都需要企业内部自己来实现插件的话,那么,企业对于平台接入的意愿就会大大降低。
|
||||
|
||||
实际上,**接入成本的高低,直接影响了平台能力的拓展,而流水线平台支持的能力多少,就是平台的核心竞争力**。
|
||||
|
||||
那么,有没有一种更加轻量化的平台接入方法呢?我给你提供一个解决思路:**自动化生成平台关联的原子代码**。
|
||||
|
||||
在第七个特性中,我们已经将原子的数据结构通过一种标准化的描述式语言定义完成了,那原子的实现代码是否可以也自动化生成呢?实际上,在大多数情况下,外部平台打通有两种类型。
|
||||
|
||||
- 平台方提供一个本地执行的工具,也就是类似SonarQube的Scanner的方式,通过在本地调用这个工具,实现相应的功能。
|
||||
- 通过接口调用的方式,实现平台与平台间的交互,调用的实现过程无外乎同步和异步两种模式。
|
||||
|
||||
既然平台接入存在一定的共性,那么,我们就可以规划解题方法了。
|
||||
|
||||
首先,**流水线平台需要定义一套标准的接入方式**。以接口调用类型为例,接入平台需要提供一个任务调用接口、一个状态查询接口以及一个结果上报接口。
|
||||
|
||||
- **任务调用接口**:用于流水线触发任务,一般由接入平台定义和实现。对于比较成熟的平台来说,这类接口一般都是现成的。接口调用参数可以直接转换成原子的参数,一些平台的配置化信息(比如接口地址、接口协议等),都可以定义在原子的数据结构中。
|
||||
- **状态查询接口**:用于流水线查询任务的执行状态,获取任务的执行进度。这个接口也是由接入平台定义和实现的,返回的内容一般包括**任务状态**和**执行日志**等。
|
||||
- **数据上报接口**:用于任务将执行结果上报给流水线平台进行保存。这个接口由流水线平台定义,并提供一套标准的数据接口给到接入方。接入方必须按照这个标准接口上报数据,以简化数据上报的过程。
|
||||
|
||||
通过将平台接入简化为几个标准步骤,可以大幅简化平台接入的实现成本。按照我们的经验,一套平台的接入基本都可以在几天内完成。
|
||||
|
||||
## 特性九:内建质量门禁
|
||||
|
||||
在[第14讲](https://time.geekbang.org/column/article/163072)中,我给你介绍了内建质量的理念,以及相关的实施步骤。你还记得内建质量的两大原则吗?
|
||||
|
||||
- 问题发现得越早,修复成本就越低;
|
||||
- 质量是每个人的责任,而不是质量团队的责任。
|
||||
|
||||
**毫无疑问,持续交付流水线是内建质量的最好阵地,而具体的展现形式就是质量门禁**。通过在持续交付流水线的各个阶段注入质量检查能力,可以让内建质量真正落地。
|
||||
|
||||
一般来说,流水线平台都应该具备质量门禁的能力,我们甚至要把它作为流水线平台的一级能力进行建设。在流水线平台上,要完成**质量规则制定**、**门禁数据收集和检查**,以及**门禁结果报告的完整闭环**。质量门禁大多数来源于垂直业务平台,比如,UI自动化测试平台就可以提供自动化测试通过率等指标。只有将用于门禁的数据上报到流水线平台,才能够激活检查功能。
|
||||
|
||||
那么,质量门禁的功能应该如何设计呢?
|
||||
|
||||
从后向前倒推,首先是设置**门禁检查功能**。这个功能也是一种流水线的通用能力,所以和人工审核的功能类似,也可以放在原子执行的after()步骤中,或者独立出来一个步骤就叫作qualityGates()。
|
||||
|
||||
每次原子执行时都会走到这个步骤,在步骤中校验当前流水线是否已经开启了门禁检查功能,并且当前原子是否提供了门禁检查能力。如果发现已配置门禁规则,而且当前原子在检查范围内,就等待运行结果返回,提取数据,并触发检查工作。你可以参考下面的示例代码。
|
||||
|
||||
```
|
||||
def qualityGates() {
|
||||
// 获取质量门禁配置以及生效状态
|
||||
boolean isRun = qualityGateAction.fetchQualityGateConfig(host, token, pipelineId, oneScope)
|
||||
// 激活检查的情况等待结果返回,最多等待30分钟
|
||||
if (isRun) {
|
||||
syncHandler.doSyncOperation(
|
||||
30,
|
||||
'MINUTES',
|
||||
{
|
||||
// 等待执行结果返回,质量门禁功能必须同步执行
|
||||
return httpUtil.doGetToExternalResult(host, externalMap.get(oneScope), token)
|
||||
})
|
||||
// 提取返回数据
|
||||
qualityGateAction.fetchExecutionResult(host, token, externalMap.get(oneScope), buildId)
|
||||
// 验证质量门禁
|
||||
qualityGateAction.verify(oneScope)
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
解决了如何检查的问题,我们再往前一步,看看质量门禁的规则应该如何定义。
|
||||
|
||||
在企业内,定义和管理质量规则的一般都是QA团队,所以需要给他们提供一个统一入口,方便他们进行规则配置和具体数值的调整。
|
||||
|
||||
对质量门禁来说,检查的类型可以说是多种多样的。
|
||||
|
||||
- 从比较类型来说,可以比较结果大于、等于、小于、包含、不包含等;
|
||||
- 从比较结果来说,可以是失败值、警告值。失败值是指,只要满足这个条件,就直接终止流水线执行。而警告值是说,如果满足这个条件,就给一个警告标记,但是不会终止流水线执行。
|
||||
|
||||
这些条件,往往需要根据QA团队定义的规则来适配。
|
||||
|
||||
**质量规则可以由一组子规则共同组成**,比如,单元测试通过率100%、行覆盖率大于50%、严重阻塞代码问题等于0……
|
||||
|
||||
所以,你看,想要定义一个灵活的质量门禁,就需要在系统设计方面花点功夫了。在之前的实践中,我们就采用了适配器加策略模式的方式,这样可以满足规则的灵活扩展。
|
||||
|
||||
策略模式是23种设计模式中比较常用的一种。如果你之前没有了解过,我给你推荐一篇[参考文章](https://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/strategy.html)。如果想要深入学习设计模式,极客时间也有相应的专栏,或者你也可以购买经典的《[设计模式](https://item.jd.com/10100236.html)》一书。其实,**核心就在于面向接口而非面向过程开发,通过实现不同的接口类,来实现不同的检查策略**。
|
||||
|
||||
## 特性十:数据聚合采集
|
||||
|
||||
作为软件交付过程的载体,流水线的可视化就体现在可以在流水线上看到每一个环节的执行情况。这是什么意思呢?
|
||||
|
||||
在系统没有打通的时候,如果你想看测试的执行结果,就要跑到测试系统上看;如果想看数据库变更的执行状态,就得去数据库管理平台上看。这里的问题就是,没有一个统一的地方可以查看本次发布的所有状态信息,而这也是流水线的可视化要解决的问题。
|
||||
|
||||
当平台的能力以原子的形式接入流水线之后,流水线需要有能力获取本次执行相关的结果数据,这也是在平台对接的时候,务必要求子系统实现数据上报接口的原因。至于上报数据的颗粒度,其实并没有一定之规,原则就是**满足用户对最基本的结果数据的查看需求**。
|
||||
|
||||
以单元测试为例,需要收集的数据包括两个方面,一个是单元测试的执行结果,比如一共多少用例,执行多少,成功失败分别多少。另外,即使收集覆盖率信息,至少也要包含各个维度的覆盖率指标。但是,对于具体每个文件的覆盖率情况,这种粒度的数据量比较大,可以通过生成报告的方式来呈现,不用事无巨细地都上报到流水线后台进行保存。
|
||||
|
||||
在企业内部没有建立独立的数据度量平台之前,流水线平台承载了全流程数据的展示功能。但是,毕竟流水线的目标是为了展示客观的数据结果,而不是在于对数据进行分析挖掘。所以,当企业开始建设数据度量平台时,流水线也可以作为数据源之一,满足度量平台对于各项工程能力的度量需求。
|
||||
|
||||
## 总结
|
||||
|
||||
到此为止,我给你完整地介绍了现代流水线必备的十大特性。其实,流水线的功能特性远不止这10个。随着云计算和云原生应用的发展,云原生流水线也成为了越来越多人讨论的话题。关于这方面的内容,我会在后续的课程中给你分享我的一些想法。
|
||||
|
||||
可以说,一个好的持续交付流水线平台,就是企业DevOps能力的巅峰展现。这也难怪,越来越多的公司开始在这个领域发力,甚至把它作为核心能力对外输出,成为企业商业化运作的一份子。深入掌握这10个特性,并把它们落实在流水线平台的建设中,是企业DevOps平台建设的必经之路。
|
||||
|
||||
就像美国著名女演员莉莉·汤姆林(Lily Tomlin)的那句经典名言所说的那样:
|
||||
|
||||
>
|
||||
The road to success is always under construction.(通往成功的道路,永远在建设之中)
|
||||
|
||||
|
||||
企业迈向持续交付的成功之路也不是一帆风顺的,永无止境的追求是指引我们前进的方向,也希望你能在流水线建设之路上不断思考,不断实践,持续精进。
|
||||
|
||||
## 思考题
|
||||
|
||||
你目前在使用的流水线平台有哪些不好用、待改进,或者是“反人类”的设计吗?看完这两讲的内容,你有什么新的想法和改进建议吗?
|
||||
|
||||
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,也欢迎你把文章分享给你的朋友。
|
||||
|
||||
|
||||
186
极客时间专栏/geek/DevOps实战笔记/平台工具篇/25 | 让数据说话:如何建设企业级数据度量平台?.md
Normal file
186
极客时间专栏/geek/DevOps实战笔记/平台工具篇/25 | 让数据说话:如何建设企业级数据度量平台?.md
Normal file
@@ -0,0 +1,186 @@
|
||||
<audio id="audio" title="25 | 让数据说话:如何建设企业级数据度量平台?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/92/46/92ae154d247afa71db16602933d80f46.mp3"></audio>
|
||||
|
||||
你好,我是石雪峰。今天我来跟你聊聊数据度量平台。
|
||||
|
||||
先说个题外话。在2019年的DevOps World | Jenkins World大会上,CloudBees公司重磅发布了他们的全新产品:[SDM - Software Delivery Management](https://www.cloudbees.com/software-delivery-management) 。在我看来,这注定是一个跨时代的产品。
|
||||
|
||||
简单来说,SDM想要解决的问题就是,**将割裂的软件开发流程收敛到一个平台上**,通过收集软件开发全流程的数据,并进行智能分析,从而让整个软件交付过程的方方面面对所有人都可视化。
|
||||
|
||||
无论这个产品最终是否能够获得成功,它背后的设计理念绝对是非常超前的,因为这是**第一次有一个解决方案把业务视角和开发视角连接了起来**。
|
||||
|
||||
对业务人员来说,他们能够实时看到特性的交付进度;对开发人员来说,他们也能实时看到交付特性的业务指标和用户反馈;对管理人员来说,他们可以纵观整个流程,发现交付过程中的阻塞和效率瓶颈。
|
||||
|
||||
这听起来是不是很神奇呢?别急,关于这个产品的更多特性,我会在后续的特别放送中给你带来更多的介绍,敬请期待。
|
||||
|
||||
言归正传,我走访过的公司无一例外地都在花大力气建设数据度量平台。这些度量平台虽然看起来长得都不一样,但是他们想要解决的核心问题都是一致的,那就是**软件研发过程可视化**。
|
||||
|
||||
为什么可视化对于软件研发来说这么重要呢?这是因为,可视化可以大幅降低软件开发的协作成本,增加研发过程的透明度,从而大大减少研发过程中的浪费和返工。
|
||||
|
||||
举个最简单的例子,每周开会的时间成本一般都比较高,但如果老板能对项目的状态有清晰的了解,何必还要费这么大力气汇报工作呢?
|
||||
|
||||
在专栏的[第19讲](https://time.geekbang.org/column/article/169385)中,我给你介绍了DevOps度量体系的相关内容。你还记得好的度量指标一般都具有的典型特征吗?这些特征就是**明确受众、直指问题、量化趋势、充满张力**。
|
||||
|
||||
其实,在评价一个度量平台的时候,这些特征同样适用。因为,在数据度量平台上呈现的内容,正是度量指标。这也就是说,将度量指标的数据和详情汇总起来,再根据度量指标的维度,展现出各式各样的视图,从而满足不同用户的需求。
|
||||
|
||||
这样一来,整个团队的交付情况,包括交付效率和质量,就可以通过客观数据展示出来,而不再依赖于个人的主观臆测。有了客观的数据做尺子,团队的改进空间也就一目了然了。
|
||||
|
||||
听起来是不是特别美好?但实际上,度量平台要想满足这种预期,可不是一件简单的事情。
|
||||
|
||||
我认为,在数据度量平台的建设和落地过程中,事前、事中和事后这三个阶段都存在着大量的挑战。接下来,我就从这三个阶段入手,给你聊聊度量平台建设的一些思路。
|
||||
|
||||
## 事前:指标共识
|
||||
|
||||
毫无疑问,度量指标是数据度量平台的基础。在建设平台之前,如果指标本身的定义、数据来源、计算方法、统计口径等没有在团队内部达成共识的话,那么,数据度量平台呈现出来的数据也同样是有问题的。
|
||||
|
||||
我给你举个例子。需求流转周期这个指标,一般是计算需求卡片在需求的各个状态的停留时长的总和,包括分析、设计、开发、测试、发布等。
|
||||
|
||||
其中的测试流转周期计算的是,从需求卡片进入待测试状态到测试完成进入待发布状态的时长,例如5天。但是,在真正支持测试任务的系统中,也有一个测试流转周期。这个流转周期计算的是每个测试任务的平均执行时间,这样算出来的测试周期可能只有1天。
|
||||
|
||||
先不说这两种计算方式谁对谁错,我想表达的是,**即便是针对同一个指标,在不同平台、根据不同计算方法得到的结果也大不相同**。
|
||||
|
||||
如果不能把指标的定义对齐,那么在实施度量的过程中,大家就会不清楚到底哪个数据是正确的,这显然不利于度量工作的推进。
|
||||
|
||||
另外,在定义度量指标的时候,一般都会召开指标评审会议。但这个时候,因为拿不出具体的数据,大家光盯着指标定义看,往往也看不出什么问题。等到平台上的数据出来了,才发现有些数据好像不太对。于是,要再针对指标重新梳理定义,而这往往就意味着平台开发的返工和数据重新计算。**在平台建设的过程中,数据校准和指标对齐工作花费的时间很有可能比开发平台本身的时间都要多**。
|
||||
|
||||
“**数据本身不会说话,是人们赋予了数据意义**”,而“这个意义“就是度量指标。
|
||||
|
||||
在定义指标的时候,大家都愿意选择对自己有利的解释,这就导致大家看待数据的视角无法对齐。
|
||||
|
||||
所以,在实施度量平台建设之前,最重要的就是**细化度量指标的数据源和计算方法,而且一定要细化到可以落地并拿出数据结果的程度**。
|
||||
|
||||
比如,开发交付周期这个指标一般是指从研发真正动工的时间点开始,一直到最终上线发布为止的时长。但是这个描述还是不够细化,所以,我们团队对这个指标的描述是:**从研发在需求管理平台上将一个任务拖拽到开始的开发阶段起,一直到这个任务变成已发布状态为止的时间周期。**
|
||||
|
||||
这里的任务类型包括**特性、缺陷和改进任务**三种,不包含史诗任务和技术预研任务类型。我们会对已达到交付状态的任务进行统计,未完成的不在统计范围中。你看,只有描述到这种颗粒度,研发才知道应该如何操作,数据统计才知道要如何获取有效的数据范围。
|
||||
|
||||
我建议你**在着手启动数据度量平台建设之前,至少要保证这些指标数据可以通过线下、甚至是手工的方式统计出来,并在内部达成共识**。
|
||||
|
||||
切忌一上来就开始盲目建设!很多时候,我们虽然花了大力气建设平台,最终也建设出来了,但结果却没人关注,核心问题还是出在了指标上。
|
||||
|
||||
数据平台作为企业内部的公信平台,数据的准确性至关重要。如果数据出现了偏差,不仅会导致错误的判断,带来错误的结果,还会对平台自身的运营推广造成很大的伤害。
|
||||
|
||||
## 事中:平台建设
|
||||
|
||||
随着软件交付活动复杂性的上升,在整个交付过程中用到的工具平台也越来越多。虽然通过持续交付流水线平台实现了交付链路的打通,通过交付流水线来驱动各个环节的工具平台来完成工作,但是,客观来说,企业内部的工具平台依然是割裂的状态,而非完整的一体化平台。
|
||||
|
||||
这就带来一个问题:每个平台或多或少都有自己的数据度量能力,甚至也有精细化维度的数据展示,但是这些数据都是存储在各个工具平台自身的数据库中的。
|
||||
|
||||
我给你举个例子。Jira是一个业界使用比较普遍的需求管理平台,也是一个成熟的商业工具,所以,对于这类商业化系统都提供了比较完善的API。再加上Jira自带的JQL查询语言,可以相对比较简单地查询并获取元数据信息。但是,对于一个自研平台来说,对外开发的API可能相对简单,甚至有的系统都没有对外暴露API。在这种情况下,如果想要获取平台数据,要么依赖于开发新的API,要么就只能通过JDBC直接访问后台数据库的形式来提取数据。
|
||||
|
||||
不仅如此,还有些平台的数据是通过消息推送的方式来获取的,无法主动地获取数据,只能通过订阅消息队列广播的方式来获取。
|
||||
|
||||
所以,你看,**对于不同的元数据平台,数据获取的方式也是千差万别的**。
|
||||
|
||||
### 挑战一:大量数据源平台对接
|
||||
|
||||
那么,作为一个统一的数据度量平台,面对的第一个挑战就是,**如何从这些种类繁多的平台中提取有用的数据,并且保证数据源接入的隔离性,做到灵活接入呢?**
|
||||
|
||||
我给你的建议还是采用流水线设计的思路,那就是**插件化**,只不过,这次要实现的插件是**数据采集器**。你可以看一下这张简单的架构示意图:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/e9/2a/e9806c2956d151804423f7f237fe152a.png" alt="">
|
||||
|
||||
采集器是针对每一个对接的数据源平台实现的,它的作用就是对每个数据源进行数据建模,从而对平台屏蔽各种数据获取方式,将采集到的数据进行统一格式化上报和存储。在采集器上面可以设计一个Operation层,用来调整采集器的执行频率,控制采集数据的范围。
|
||||
|
||||
如果数据量比较大,你也可以让采集器对接类似Kafka这样的消息队列,这些都可以按需实现。这样一来,新平台如果想要接入,只需要针对这个平台的数据特性实现一个采集器即可,平台的整体架构并不需要变化。
|
||||
|
||||
你可以看看下面的这段采集器的示例代码:
|
||||
|
||||
```
|
||||
@Override
|
||||
public void collect(FeatureCollector collector) {
|
||||
logBanner(featureSettings.getJiraBaseUrl());
|
||||
int count = 0;
|
||||
|
||||
try {
|
||||
long projectDataStart = System.currentTimeMillis();
|
||||
ProjectDataClientImpl projectData = new ProjectDataClientImpl(this.featureSettings,
|
||||
this.projectRepository, this.featureCollectorRepository, jiraClient);
|
||||
count = projectData.updateProjectInformation();
|
||||
log("Project Data", projectDataStart, count);
|
||||
} catch (Exception e) {
|
||||
// catch exception here so we don't blow up the collector completely
|
||||
LOGGER.error("Failed to collect jira information", e);
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### 挑战二:海量数据存储分析
|
||||
|
||||
一般来说,常见的数据存储方式无外乎RDMS关系型数据库和NoSQL非关系型数据库两种类型。那么,究竟应该如何选择,还是要看数据度量平台的数据特征。
|
||||
|
||||
- 第一个典型特征就是**数据量大**。对于一个大型公司而言,每天的代码提交就有近万笔,单单这部分数据就有几十万、上百万条。
|
||||
- 第二个特征就是**数据结构不统一**。这个其实很好理解,毕竟需求相关的数据字段和代码相关的数据字段基本上没有什么共性,而且字段的数量也会根据指标的调整而调整。
|
||||
- 第三个特征就是**数据访问频繁**。度量平台需要在大规模的数据集中进行随机访问、数据的读取运算等操作,这就要求很好的横向扩展能力。
|
||||
|
||||
另外,数据度量平台一般都会保存元数据和加工数据。所谓元数据,就是采集过来的、未加工过的数据,而加工数据则是经过数据清洗和数据处理的数据。
|
||||
|
||||
我还是举个代码库的例子来说明一下。元数据就是一条条用户的代码提交记录,而加工数据则是按照分钟维度聚合过的提交信息,包括数量、行数变化等。这些加工过的数据可以很简单地提供给前端进行图表展示。存储加工数据的原因就在于,避免每次实时的大量数据运算,以提升度量平台的性能。
|
||||
|
||||
基于这些典型特征和场景,不难看出,非关系型数据库更加适合于大量元数据的保存。
|
||||
|
||||
我推荐你使用HBase,这是一个适合于非结构化数据存储的数据库,天生支持分布式存储系统。而对于加工数据的保存,你可以采用关系型数据库MySQL。
|
||||
|
||||
当然,数据库的选型不止这一种,业界还有很多开源、商业工具。比如,开源的数据度量平台Hygieia就采用的是MongoDB,而商业工具中的Insight也在业内的很多大型公司在大规模使用。
|
||||
|
||||
我再给你分享一幅数据度量的架构图。从这张图中,你可以看到,底层数据都是基于HBase和HDFS来存储的。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/0f/ec/0fd99a661eede0fbc0ae7e282464ceec.png" alt="">
|
||||
|
||||
### 挑战三:度量视图的定制化显示
|
||||
|
||||
度量平台需要满足不同维度视角的需求,所以一般都会提供多个Dashboard,比如管理层Dashboard、技术经理Dashboard、个人Dashboard等。但是,这种预置的Dashboard很难满足每个人的差异化需求,就像“一千个人眼里有一千个哈姆雷特”一样,度量平台的视图也应该是千人千面的。
|
||||
|
||||
那么如果想要实现度量视图的自定义,比如支持图标位置的拖拽和编辑,自己增加新的组件、并按照自定义视图发送报告等,那就需要在前端页面开发时下点功夫了。好在对于现代前端框架,都有现成的解决方案,你只需要引用对应的组件即可。
|
||||
|
||||
我给你推荐两个前端组件,你可以参考一下:
|
||||
|
||||
- [插件一](https://github.com/jbaysolutions/vue-grid-layout)
|
||||
- [插件二](https://github.com/STRML/react-grid-layout)
|
||||
|
||||
这两个组件都可以支持widget的拖拽、缩放、自动对齐、添加、删除等常见操作。这样一来,每个人都可以自由地按需定制自己的工作台视图,不同角色的人员也可以定制和发送报告,而不需要从度量平台提取数据,再手动整理到PPT里面了。
|
||||
|
||||
以vue-grid-layout为例,在使用时,你可以将echarts图表放在自定义组件里面,同时你也可以自己实现一些方法,具体的方法可以参考一下[这篇文章](https://www.cnblogs.com/yasoPeng/p/9961732.html)。
|
||||
|
||||
在了解了刚开始建设度量平台的三个常见挑战之后,你应该已经对度量平台的架构有了一个大体的认识,接下来,我们来看看第三个阶段。
|
||||
|
||||
## 事后:规则落地
|
||||
|
||||
以现在的开发效率来说,建设一个数据度量平台并不是件困难的事情。实际上,建设度量平台只能说是迈出了数据度量的第1步,而剩余的99步都依赖于平台的运营推广。
|
||||
|
||||
这么说一点也不夸张,甚至可以说,如果根本没人关心度量平台上的数据,那么可能连第1步的意义都要画上个问号。
|
||||
|
||||
在开始运营的时候,度量平台面临的最大挑战就是**数据的准确性**,这也是最容易被人challenge的地方。
|
||||
|
||||
造成数据不准确的原因有很多,比如,度量指标自身的计算方式问题、一些异常数据引入的问题、部门维度归类聚合的问题。但是实际上,往往带来最多问题的还是研发操作不规范。
|
||||
|
||||
举个例子,像需求交付周期这种数据强依赖于需求卡片流转的操作是否规范,如果研发上线后一次性把卡片拖拽到上线状态,那么这样算出来的需求交付周期可能只有几秒钟,显然是有问题的。
|
||||
|
||||
正确的做法是,根据真实的状态进行流转,比如研发提测关联需求,后台自动将需求卡片流转到待测试状态;测试验收通过后,卡片再次自动流转到测试完成状态等。**尽量实现自动化操作,而不是依赖于人的自觉性**。
|
||||
|
||||
再举个例子,像需求关联的代码行数,如果研发提交的时候并没有对代码和需求建立关联,那么统计出来的数据也会有很大的失真。这些不规范的数据并不会因为后续操作的改变而改变,也很难进行数据的修复和清理,会一直留存在度量系统的数据池中,是抹不掉的印记。
|
||||
|
||||
所以,度量平台只有通过项目自上而下的驱动才能起到真正的作用。要**对不规范的操作建立规则,对恶意操作的数据进行审计,把度量发现的问题纳入持续改进,对每项指标的走势进行跟踪和定位**。
|
||||
|
||||
另外,为了让数据可以直指问题,在度量平台中,也需要体现出来当前的数据是好还是坏。
|
||||
|
||||
方式和方法有很多,比如,建立参考值(比如对于单测覆盖率制定最低50%的参考值),这样在度量图表中就能体现出当前数据和参考值的差距。或者,你也可以在每一项可以横向比较的指标旁边,体现当前处在大部门的哪个位置,是前10%,还是后10%?这样的数据都有助于推动改进行为。
|
||||
|
||||
说到底,**度量的目的是持续改进**。如果统计了100个指标的数据,并都体现在度量平台上,却说不出来到底哪个指标给团队带来了改进,以及改进是如何实现的,那么,这种度量平台的价值又在哪里呢?
|
||||
|
||||
## 总结
|
||||
|
||||
好啦,在这一讲中,我给你介绍了建设数据度量平台的核心价值,也就是**让软件交付过程变得可视化**。在这一点上,业界各大公司的思路都是一致的。也正因为如此,数据度量平台是当前企业DevOps平台建设不可或缺的一环。
|
||||
|
||||
在平台建设的时候,你需要关注事前、事中和事后三个阶段的事情。
|
||||
|
||||
- 事前就是要对指标的定义达成共识。这里的指标要细化到数据源和详细的计算公式层面,即便没有度量平台,也可以计算出相应的结果;
|
||||
- 事中就是平台建设方面,面对多数据源平台可以采用采集器插件的方式灵活适配,建议使用HBase等非关系型数据库进行数据存储,可以利用现有的前端组件来实现可视化界面展示。
|
||||
- 事后就是数据的运营和规则落地。只有度量数据能够反映出问题,并驱动团队改进,度量才有意义。
|
||||
|
||||
## 思考题
|
||||
|
||||
你在企业中建设和应用度量平台的时候,还遇到过哪些问题呢?你又是如何解决的呢?
|
||||
|
||||
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,也欢迎你把文章分享给你的朋友。
|
||||
|
||||
|
||||
219
极客时间专栏/geek/DevOps实战笔记/平台工具篇/26 | 平台产品研发:三个月完成千人规模的产品要怎么做?.md
Normal file
219
极客时间专栏/geek/DevOps实战笔记/平台工具篇/26 | 平台产品研发:三个月完成千人规模的产品要怎么做?.md
Normal file
@@ -0,0 +1,219 @@
|
||||
<audio id="audio" title="26 | 平台产品研发:三个月完成千人规模的产品要怎么做?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/63/98/63cb07b82c2518f59fc51e3d3a2ac398.mp3"></audio>
|
||||
|
||||
你好,我是石雪峰。
|
||||
|
||||
虽然我们之前聊了这么多的平台建设思路,但是,可能很多人都没有机会经历一个平台从构思到开发、再到推广落地的完整过程。
|
||||
|
||||
如果要开发一个千人使用的DevOps产品,需要多长时间呢?你可能会说需要半年甚至是更长的时间,我之前也是这么觉得的。
|
||||
|
||||
但是,2018年,在启动流水线平台建设的时候,老板“大手一挥”,要求在三个月内见到成效,我都快惊呆了。
|
||||
|
||||
因为,我们要真正地从零开始:原型图都没有一张,代码都没有一行,临时组建的一个草台班子还分散在北京、上海两地,团队成员之前都没怎么打过招呼,这能行吗?
|
||||
|
||||
今天,我想给你分享的就是这个真实的故事。我来跟你一起复盘下这次“急行军”的历程,看看我们做对了什么,又做错了什么,有哪些干货是可以拿来就用的,又有哪些“坑”是你一定要努力回避的。
|
||||
|
||||
其实,作为一个非专业的DevOps产品经理,你终将面对这样的挑战,但你要相信,**只要开始去做了,就没有什么是不可能的**。
|
||||
|
||||
## 项目启动
|
||||
|
||||
时间回到一年前,当时我所在的这个“草台班子”是个啥情况呢?团队组成是这样的:两个后台开发在北京,一个半前端开发在上海,还有一个基础设施工程师和一个流水线开发工程师,再加上半个全能打杂的产品经理,也就是我,满打满算一共6个人。
|
||||
|
||||
项目从11月中旬开始构思,12月初开启动会,当时,除了我之外,没有任何人清楚我们要做的到底是个什么玩意儿。这该怎么办呢?
|
||||
|
||||
玩过游戏的同学应该都知道打好开局有多重要,所以,为了这个Kickoff会议,我事先做了大量的准备工作,其中就包括0.2版本的产品原型图。与其说是一个原型图,不如说就是一个草稿,简陋得不能再简陋了。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/ac/fe/ac58f3b2040056ee030008370dc6c3fe.png" alt="">
|
||||
|
||||
项目的Kickoff会议是项目组成员和未来产品的第一次见面,留下一个积极的印象非常重要。所以,从第一刻开始,我就铆足了精神。
|
||||
|
||||
首先,我发出了一封热情洋溢的会议邀请。在会议邀请中,我仔细地陈述了我们为什么要做这件事,为什么是现在,为什么不做不行。
|
||||
|
||||
在正式开会的时候,我再一次明确了项目的重要性和紧急性,并给大家演示了第一版的系统原型图(没错,就是简陋到极致的刚刚的这张原型图)。
|
||||
|
||||
即便这样,三个月的工期也让大家非常焦虑。为了缓解紧张情绪,证明这个项目的可行性,我还做了两件事:
|
||||
|
||||
1. 搭建了一个系统demo,几个简单的页面;
|
||||
1. 由于用到了另外一个开源产品的核心技术,于是,我就对这个技术进行了简单演示。
|
||||
|
||||
虽然我自己心里对这个计划也相当“打鼓”,但我还是希望告诉大家,这并不是不可能的任务,努力帮助大家树立信心。
|
||||
|
||||
在项目启动会上,团队达成了两个非常关键的结论:**一个是系统方案选型;另一个是建立协作机制**。
|
||||
|
||||
首先,由于时间紧任务重,我们决定使用更易于协作的前后端分离的开发模式。后来,事实证明,这是一个非常明智的选择。这不仅大幅提升了开发效率,也大大降低了之后向移动端迁移的成本。在开发移动端产品的时候,后端接口大部分都可以直接拿来使用。
|
||||
|
||||
在技术框架方面,由于大家对前后端分离的模式达成了共识,我们就采用**Python+Django+VUE**的方式来做。你可能会问,为啥不用基于Java的Spring系列呢?因为我觉得,对于内部系统来说,这些典型的框架应付起来基本都绰绰有余,关键还是要选你熟悉的、易上手的那个。从这个角度来看,Python显然有着得天独厚的优势。即便之前只是写写脚本,想要上手Python也不是一件困难的事情。
|
||||
|
||||
在项目协作方面,我等会儿会专门提到,由于团队成员分散在北京、上海两地,彼此之间不够熟悉和信任,所以,**建立固定的沟通机制就非常重要**。
|
||||
|
||||
至少,在项目初期,我们每周都要开两次电话会议:
|
||||
|
||||
- 一次是面向全员的。一方面同步项目的最新进展,另一方面,也给大家一些紧迫感,让大家觉得“其他人都在按照计划执行,自己也不能落后”。
|
||||
- 另外一次是面向跨地域骨干的。这主要还是为了增进联系,并且对一些核心问题进行二次的进展确认。不拉上全员,也是为了避免过多地浪费项目成员的时间。
|
||||
|
||||
最后,项目毕竟还是有一些技术风险的,所以还需要启动预研。我们这个项目的主要风险是在**前端交互**上。
|
||||
|
||||
这是一个从来没人实现过的场景,有大量的用户界面编排操作在里面。所以,我们专门指定了一位同学,让他啥也别想,一门心思地进行技术攻关。
|
||||
|
||||
事实证明,但凡能打硬仗的同事,在后来都是非常靠谱且独当一面的,这与年龄无关,哪怕是应届生,也同样如此。
|
||||
|
||||
讲到这里,我要先给你总结一下在项目启动阶段要重点关注的几件事情:
|
||||
|
||||
- 明确项目目标,树立团队的信心;
|
||||
- 沟通开发模式和技术架构选型,以快速开发和简单上手为导向;
|
||||
- 建立沟通渠道,保持高频联系;
|
||||
- 识别项目的技术风险,提前开启专项预研。
|
||||
|
||||
## 开发策略
|
||||
|
||||
人类社会活动的每一个环节,都需要越来越多的人为了同一个目标推进工作,软件开发也不例外。那么,我们是怎么做的呢?
|
||||
|
||||
首先,就是**研发环境容器化**。
|
||||
|
||||
**对于接触一个全新技术栈的开发来说,本地搭建一套完整可运行的环境总是绕不过去的坎**。即便是对照着文档一步步操作,也总会有遗漏的地方。除此之外,项目依赖的各种中间件,哪怕稍微有一个版本不一致,最后一旦出现问题,就要查很久。
|
||||
|
||||
既然如此,为什么不一上来就采用标准化的环境呢?这就可以发挥容器技术的优势了。主力后台开发同学自己认领了这个任务,先在本地完成环境搭建并调试通过,接着把环境配置容器化。这样一来,新人加入项目后,几分钟就能完成一套可以工作的本地开发环境。即便后续要升级环境组件,比如Django框架版本,也非常简单,只要推送一个镜像上去,再重启本地环境就可以了。
|
||||
|
||||
其次,就是选择分支策略。虽然DevOps倡导的是主干开发,但是我们还是选择了“三分支”的策略,因为**我们搭建了三套环境**。
|
||||
|
||||
测试环境对应dev分支作为开发主线,所有新功能在特性分支开发,自测通过后,再通过MR到dev分支并部署到测试环境进行验收测试,一般验收测试由需求提出方负责。
|
||||
|
||||
接下来,定期每周两次从dev上master分支,master分支对应了预发布环境,保证跟生产环境的一致性,数据也会定期进行同步。只有在预发布环境最终验收通过后,才具备上线生产环境的条件。通过将master分支合并到release分支,最后完成生产环境部署。这种分支策略的示意图如下:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/43/25/435d72ddc0b694e4efa84dc8cef3be25.png" alt="">
|
||||
|
||||
为什么要采用三套环境的“三分支”策略呢?
|
||||
|
||||
这里的主要原因就是,团队处于组建初期,磨合不到位,经常会出现前后端配置不一致的情况。更何况,我们这个项目不只有前后端开发,还有核心原子业务开发,以及基础设施维护。任何一方的步调不一致,都会导致出现问题。
|
||||
|
||||
另外,内部平台开发往往有个通病,就是**没有专职测试**。这也能理解,总共才几个人的“草台班子”,哪来的测试资源啊?所以,基本上只能靠研发和产品把关。
|
||||
|
||||
但是,毕竟测试也是个专业的工种,这么一来,总会有各种各样的问题。再加上,产品需求本身就没有那么清晰、灵活多变,所以,**多一套环境,多一套安全**。
|
||||
|
||||
但不可否认的是,这种策略并非是最优解,只不过是适应当时场景下的可行方案。当团队磨合到位,而且也比较成熟之后,就可以简化一条分支和一套环境了。不过,前提是,**只有快速迭代,快速上线,才能发挥两套环境的优势**。
|
||||
|
||||
>
|
||||
Use what you build to build what you use.(使用你开发的工具来开发你的工具)
|
||||
|
||||
|
||||
这是我们一以贯之的理念。既然是DevOps平台,那么团队也要有DevOps的样子,所以,作为一个全功能团队,研发自上线和研发自运维就发挥到了极致。
|
||||
|
||||
同时,我们并没有使用公司统一的上线流程,而是自己建立了一个标准化的上线流程并固化在工具里面,团队的每一个人都能完成上线动作。
|
||||
|
||||
这样一来,就不会再依赖于某个具体的人员了,这就保持了最大的灵活性。即便赶上大促封网,也不会阻塞正常的开发活动。
|
||||
|
||||
## 开发协作流程
|
||||
|
||||
仅仅是做到上面这几点,还不足以让整个团队高效运转起来,因为**缺少了最重要的研发协作流程**。
|
||||
|
||||
作为项目负责人,我花了很大的精力优化研发协作流程,制定研发协作规范。当这一切正常运转起来后,我发现,这些前期的投入都是非常值得的。
|
||||
|
||||
在工具层面,我们使用了Jira。对于小团队来说,Jira的功能就足够优秀了,可以满足大多数场景的需求。但是Jira的缺点在于,使用和配置门槛稍微有点高。因此,团队里面需要有一个熟悉Jira的成员,才能把这套方法“玩”下去。
|
||||
|
||||
在Jira里面,我们采用了**精益看板加上迭代**的方式,基本上两周一个迭代,保持开发交付的节奏。这种开发工作流刚好适配我们的分支策略和多环境部署。
|
||||
|
||||
需求统一纳入Backlog管理,当迭代开始时,就拖入待开发状态,研发挑选任务启动开发,并进入开发中。当开发完成后,也就意味着功能已经在测试环境部署。这个时候,就可以等待功能验收。只有在验收通过之后,才会发布到预发布环境。并经过二次验收后,最终上线发布给用户。
|
||||
|
||||
开发流程并不复杂,你可以看一下下面这两版流程图。
|
||||
|
||||
图片版:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/be/98/be2b81f9744fe06876fac21c61a4b798.png" alt="">
|
||||
|
||||
文字版:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/ec/8e/ec61ade9f0b2c3b014e27a7ac367298e.png" alt="">
|
||||
|
||||
定义好开发工作流之后,接下来,就需要明确原则和规范了。对于一个新组建的团队来说,**规则是消除分歧和误解的最好手段,所以一定要让这些规则足够得清晰易懂**。比如,在我们内部就有一个“3-2-1”原则:
|
||||
|
||||
3:**创建**任务三要素
|
||||
|
||||
- 有详细的问题说明和描述
|
||||
- 有清晰的验收标准
|
||||
- 有具体的经办人和迭代排期
|
||||
|
||||
2:**处理**任务两要素
|
||||
|
||||
- 在开发中,代码变更要关联Jira任务号
|
||||
- 在开发完成后,要添加Jira注释,说明改动内容和影响范围
|
||||
|
||||
1:**解决**任务一要素
|
||||
|
||||
- 问题报告人负责任务验收关闭
|
||||
|
||||
当然,团队规则远不止这几条。你要打造自己团队内部的规则,并且反复地强调规则,帮助大家养成习惯。这样一来,你会发现,**研发效率提升和自组织团队都会慢慢成为现实**。
|
||||
|
||||
除此之外,**你也不要高估人的主动性,期望每个人都能自觉地按照规则执行**。所以,定期和及时的提醒就非常必要。比如,每天增加定时邮件通知,告诉大家有哪些需求需要验收,有哪些可以上线发布,尽量让每个人都明白应该去哪里获取最新的信息。
|
||||
|
||||
另外,每次开周会时,都要强调规则的执行情况,甚至每天的站会也要按需沟通。只有保持短促、高频的沟通,才能产生理想的效果。
|
||||
|
||||
## 产品运营策略
|
||||
|
||||
关于产品运营策略,“酒香不怕巷子深”的理念已经有些过时了。想要一个产品获得成功,**团队不仅要做得好,还要善于运营和宣传,而这又是技术团队的一大软肋**。
|
||||
|
||||
开发团队大多只知道如何实现功能,却不知道应该怎么做产品运营。往往也正因为如此,团队很难获取用户的真实反馈,甚至开发了很多天才的功能,用户都不知道。产品开发变成了“自嗨”,这肯定不符合产品设计的初衷。
|
||||
|
||||
考虑到这些,我们在平台运营的时候,也采取了一些手段。我想提醒你的是,**很多事情其实没有没有多难,关键就看有没有想,有没有坚持做**。
|
||||
|
||||
比如,你可以建立内部用户沟通群,在产品初期尽量选择一些活跃的种子用户来试用。那些特别感兴趣、愿意尝试新事物、不断给你提建议的都是超级用户。这些用户未来都是各个团队中的“星星之火”,**在项目初期,你一定要识别出这些用户**。
|
||||
|
||||
另外,每一次上线都发布一个release notes,并通过邮件和内部沟通群的方式通知全员,一方面可以宣传新功能,另一方面,也是很重要的一方面,**就是保持存在感的刷新**。你要让用户知道这个产品是在高速迭代的过程中的,而且每次都有不一样的新东西,总有一样会吸引到他们,或者让他们主动提出自己的问题。
|
||||
|
||||
在用户群里面,注意要及时响应用户的问题。你可以在团队内部建立OnCall机制,每周团队成员轮值解决一线用户的问题,既可以保证问题的及时收敛,也能让远离用户的开发真真切切地听到用户的声音。这样的话,在需求规划会和迭代回顾会的时候,开发就会更多地主动参与讨论。
|
||||
|
||||
以上这些都是比较常规的手段,在我们的产品运营中,还有两个方法特别有效,我也推荐给你。
|
||||
|
||||
平台运营就跟打广告是一样的,越是在人流最大、关注度最高的地方打广告,效果也就越好。每个公司一般都有类似的首页,比如公司内部的技术首页、技术论坛、日常办公的OA系统等等,这些地方其实都会有宣传的渠道和入口。**你要做的就是找到这个入口,并联系上负责这个渠道的人员**。我们的产品就一度实现了热门站点的霸屏,宣传效果非常明显,用户量直线上升。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/ac/c6/aca17122846f83e9d8700af0ad3952c6.png" alt="">
|
||||
|
||||
另一个方法有些取巧,但对于技术团队来说,也非常适用,那就是**通过技术分享的渠道来宣传产品**。
|
||||
|
||||
相信每个团队都会有定期的技术分享渠道,或者是技术公众号等,**你可以把平台的核心技术点和设计思想提炼出来,拟定一个分享话题,并在内部最大范围的技术分享渠道中进行分享**。
|
||||
|
||||
很多时候,单纯地宣传一个产品,很多人是“不感冒”的。但是,如果你在讲一些新技术,并结合产品化落地的事情,对技术人员的吸引力就会大很多。所以,**换个思路做运营,也是提升产品知名度的好方法**。我把我之前总结的产品运营渠道和手段汇总成了一幅脑图,也分享给你。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/67/27/676b53d64ba520cc1c56d429b5d01a27.png" alt="">
|
||||
|
||||
## 团队文化建设
|
||||
|
||||
最后,我想再跟你简单聊聊团队文化建设的事情。毕竟,无论什么样的工具、流程、目标,最终都是依靠人来完成的。**如果忽略对人的关注,就等同于本末倒置,不是一个成熟的团队管理者应该做的事情**。我给你分享我的两点感受。
|
||||
|
||||
**1.让专业的人做专业的事情**
|
||||
|
||||
很多时候,千万不要小看专业度这个事情。任何一个组织内部的职能都需要专业能力的支撑,这些专业能力都是量变引发的质变。
|
||||
|
||||
我举个最简单的例子,你还记得我在前面提到的0.2版本的原型草稿吗?实际上,到了0.3版本,引用前端工程师话来说,“原型做得比系统还漂亮”。这是为什么呢?难道是我这个“半吊子”产品经理突然开窍了吗?
|
||||
|
||||
显然不是。其实答案很简单,就是我去找了专业产品经理做外援,让他帮我改了两天的原型图。对于专业的人来说,这些事情再简单不过了。
|
||||
|
||||
找专业的人来做这些事情,不仅可以帮助你快速地跨越鸿沟,也能留下很多现成的经验,供你以后使用,这绝对不是一个人埋头苦干可以做得到的。
|
||||
|
||||
不仅是产品方面,技术领域也是一样的。**我们要勇于承认自己的无知,善于向别人求助,否则到头来,损失的时间和机会都是自己买单,得不偿失**。
|
||||
|
||||
**2.抓大放小,适当地忽略细节**
|
||||
|
||||
在协作的过程中,团队总会在一些细节上产生冲突。如果任由团队成员在细节上争论不休,久而久之,就会影响团队之间的信任感。这个时候,就需要引导团队将注意力集中在大的方向上,适当地暂缓细节讨论,以保证团队的协作效率。
|
||||
|
||||
比如,一个业务逻辑是放在前端处理,还是放在后端处理,结果并没有太大区别,说白了,就是放在哪儿都行。但是,前端同学会坚持认为,逻辑处理都应该由后端来解决,以降低前端和业务的耦合性,这样说也没有错。可是,后端同学也会有自己的想法,比如针对前端拦截器的处理机制,后端到底要不要配合着返回前端要求的返回码,而不是直接抛出http原始的返回码呢?
|
||||
|
||||
类似的这些问题,没有谁对谁错之分,但是真要是纠结起来,也不是一两句话就能说清楚的。
|
||||
|
||||
这个时候,就需要有人拍板,选择一条更加符合常规的方式推进,并预留出后续的讨论空间。甚至,为了促进多地合作,自己人这边要适当地牺牲一些,以此来换取合作的顺利推进。这样一来,你会发现,有些不可调和的事情,在项目不断成功、人员不断磨合的过程中,也就不是个事情了。
|
||||
|
||||
## 总结
|
||||
|
||||
在这一讲中,关于如何开发产品,可以说,我是把自己在过去几个项目经历中的总结倾囊相授了。
|
||||
|
||||
其实,就像我在讲“[DevOps工程师需要的技能](https://time.geekbang.org/column/article/151398)”中提到的那样,软实力(比如沟通协作、同理心、持续改进等)对促进产品快速迭代开发演进有着重大的作用。作为非专业产品经理,我也在慢慢地积累自己的产品心经,有机会再给你好好聊聊。
|
||||
|
||||
你可能还在想,最终千人的目标是否实现了呢?我想说的是,有些时候,真实生活比故事还要精彩。
|
||||
|
||||
就在预订目标的倒数第二天,平台用户只有997个。当时,我跟同事吐槽这个数字,他们说要不要拉几个用户进来,我说:“算了吧,随它去吧。“结果你猜怎样?在当天周五下班的时候,我又去平台上看了一眼,不多不少刚好1000个注册用户。当时我的第一感觉就是,**要相信,当我们把自己的全身心和热情都灌注在一个产品的开发过程中时,美好的事情会自然而然地发生**。
|
||||
|
||||
## 思考题
|
||||
|
||||
你对这一讲的哪部分内容印象最深刻呢?你有什么其他有助于产品快速研发落地的观点吗?
|
||||
|
||||
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,也欢迎你把文章分享给你的朋友。
|
||||
|
||||
|
||||
272
极客时间专栏/geek/DevOps实战笔记/平台工具篇/27 | 巨人的肩膀:那些你不能忽视的开源工具.md
Normal file
272
极客时间专栏/geek/DevOps实战笔记/平台工具篇/27 | 巨人的肩膀:那些你不能忽视的开源工具.md
Normal file
@@ -0,0 +1,272 @@
|
||||
<audio id="audio" title="27 | 巨人的肩膀:那些你不能忽视的开源工具" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/a0/d4/a052611ce7637a0da2daee351537a4d4.mp3"></audio>
|
||||
|
||||
你好,我是石雪峰。
|
||||
|
||||
自研工具平台对公司来说是一件高成本和高投入的事情,对于技术人员的要求也非常高。很少有公司能够像BAT一样投入近百人的团队来开发内部系统工具,毕竟,如果没有这么大规模的团队,平台产生的收益也比较有限。
|
||||
|
||||
另外,也很少有公司像一些行业头部公司一样,会直接投入大量资金购买成熟的商业化工具或者通过乙方合作的方式联合共建。
|
||||
|
||||
这些方法的长期投入都比较大,不太适用于中小型企业。那么,有其他可以低成本、快速见效的解决方案吗?
|
||||
|
||||
实际上,现在的开源工具已经非常成熟了,只要稍加熟悉,就能快速地基于开源工具搭建一整套研发交付工具链平台。
|
||||
|
||||
几年前,我跟几个朋友利用业余时间就搭建了这样一套开源的端到端流水线解决方案。我依稀记得,这个解决方案架构图是在北京开往上海的高铁上完成的。目前,这个方案在行业内广为流传,成为了很多公司搭建自己内部工具链平台的参考资料。这个系统的架构图如下:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/54/65/540e6527c7e2d54d0e33abc591349a65.png" alt="">
|
||||
|
||||
今天,我会基于这个解决方案,给你介绍一下研发代码提交阶段、集成测试阶段和部署发布阶段的工具使用技巧,工具选型以主流开源解决方案为主,商业工具为辅,涵盖了Jira、GitLab、Jenkins、SonarQube和Kubernetes等,希望可以手把手地帮助你快速搭建一套完整的持续交付平台。
|
||||
|
||||
**对于持续交付工具链体系来说,工具的连通性是核心要素**,所以我不会花太多时间介绍工具应该如何搭建,毕竟这类资料有很多,或者,你参考一下官网的搭建文档就可以了。尤其是现在很多工具都提供了容器化的部署方式,进一步简化了自身工具的建设成本。
|
||||
|
||||
## 需求管理 - Jira
|
||||
|
||||
在Jira官网上的醒目位置,写着一句话:**敏捷开发工具的第一选择**。在我看来,Atlassian公司的确有这个底气,因为**Jira确实足够优秀,跟Confluence的组合几乎已经成为了很多企业的标配**。这也是为什么我没有选择开源工具Redmine或者其他诸如Teambition等的SaaS化服务。
|
||||
|
||||
当然,近些年来,各大厂商也在积极地对外输出研发工具能力,以腾讯的TAPD为代表的敏捷协同开发工具,就使用得非常广泛。但是,其实产品的思路都大同小异,搞定了Jira,其他工具基本也就不在话下了。
|
||||
|
||||
作为敏捷协同工具,Jira新建工程可以选择团队的研发模式是基于Scrum,还是看板方法,你可以按需选择。在专栏的[第8讲](https://time.geekbang.org/column/article/156884)和[第9讲](https://time.geekbang.org/column/article/158789)中,我给你介绍了精益看板,你完全可以在Jira中定制自己团队的可视化看板。
|
||||
|
||||
看板的配置过程并不复杂,我把它整理成了文档,你可以点击网盘[链接](https://pan.baidu.com/s/1SAmWYv7WeYgM6yZSRs5nag)获取,提取码是mrtd。需要提醒你的一点是:**别忘了添加WIP在制品约束,别让你的精益看板变成了可视化看板**。
|
||||
|
||||
需求作为一切开发工作的起点,是贯穿整个研发工作的重要抓手。**对于Jira来说,重点是要实现跟版本控制系统和开发者工具的打通**。接下来,我们分别来看下应该如何实现。
|
||||
|
||||
如果你也在使用特性分支开发模式,你应该知道,一个特性就对应到一个Jira中的任务。通过任务来创建特性分支,并且将所有分支上的提交绑定到具体任务上,从而建立清晰的特性代码关联。我给你推荐两种实现方式。
|
||||
|
||||
第一种方式是基于Jira提供的原生插件,比如 [Git Integration for Jira](https://marketplace.atlassian.com/apps/4984/git-integration-for-jira)。这个插件配置起来非常简单,你只需要添加版本控制系统的地址和认证方式即可。然后,你就可以在Jira上进行查看提交信息、对比差异、创建分支和MR等操作。但是这个插件属于收费版本,你可以免费使用30天,到期更新即可。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/16/d9/1641afb86fdb0872d0b83e893a4803d9.png" alt="">
|
||||
|
||||
第二种方式,就是**使用Jira和GitLab的Webhook进行打通**。
|
||||
|
||||
首先,你要在GitLab项目的“设置 - 集成”中找到Jira选项,按下图添加相应配置即可。配置完成之后,你只需要在提交注释中添加一个Jira的任务ID,就可以实现Jira任务和代码提交的关联,这些关联体现在Jira任务的Issue links部分。
|
||||
|
||||
另外,你也可以实现Jira任务的状态自动流转操作,无需手动移动任务卡片。我给你提供一份 [配置说明](http://confluence.gjingao.com/pages/viewpage.action?pageId=6520911) ,你可以参考一下。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/55/48/55e7b81af5f2f96e124493e3d36d9648.png" alt="">
|
||||
|
||||
不过,如果只是这样的话,还不能实现根据Jira任务来自动创建分支,所以接下来,还要进行Jira的Webhook配置。在Jira的系统管理界面中,你可以找到“高级设置 - Webhook”选项,添加Webhook后,可以绑定各种系统提供的事件,比如创建任务、更新任务等,这基本可以满足绝大多数场景的需求。
|
||||
|
||||
假设我们的系统在创建Jira任务的时候,要自动在GitLab中基于主线创建一条分支,那么你可以将GitLab提供的创建分支API写在Jira触发的Webhook地址中。参考样例如下:
|
||||
|
||||
>
|
||||
https : //这里替换成你的GitLab服务地址/repository/branches?branch=${issue.key}&ref=master&private_token=[这里替换成你的账号Token]
|
||||
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/50/f2/504a61becf60fe6a2ddcfca5f624b9f2.png" alt="">
|
||||
|
||||
到这里,Jira和GitLab的打通就完成了。我们来总结下已经实现的功能:
|
||||
|
||||
1. GitLab每次代码变更状态都会同步到Jira任务中,并且实现了Jira任务和代码的自动关联(Issue links);
|
||||
1. 可以在MR中增加关键字 Fixes/Resolves/Closes Jira任务号,实现Jira的自动状态流转;
|
||||
1. 每次在Jira中创建任务时,都会自动创建特性分支。
|
||||
|
||||
关于Jira和开发者工具的打通,我把操作步骤也分享给你。你可以点击[网盘链接](https://pan.baidu.com/s/1ByoVZRTzG48yt8Nmgf2cJg)获取,提取码是kf3t。现在很多工具平台的建设都是以服务开发者为导向的,所以距离开发者最近的IDE工具就成了新的效率提升阵地,包括云IDE、IDE插件等,都是为了方便开发者可以在IDE里面完成所有的日常任务,对于管理分支和Jira任务,自然也不在话下。
|
||||
|
||||
## 代码管理 - GitLab
|
||||
|
||||
这个示例项目中的开发流程是怎样的呢?我们一起来看下。
|
||||
|
||||
第1步:在需求管理平台创建任务,这个任务一般都是可以交付的特性。你还记得吗?通过前面的步骤,我们已经实现了自动创建特性分支。
|
||||
|
||||
第2步:开发者在特性分支上进行开发和本地自测,在开发完成后,再将代码推送到特性分支,并触发提交阶段的流水线。这条流水线主要用于**快速验证提交代码的基本质量**。
|
||||
|
||||
第3步:当提交阶段流水线通过之后,开发者创建合并请求(Merge Request),申请将特性分支合并到主干代码中。
|
||||
|
||||
第4步:代码评审者对合并请求进行Review,发现问题的话,就在合并请求中指出来,最终接受合并请求,并将特性代码合入主干。
|
||||
|
||||
第5步:代码合入主干后,立即触发集成阶段流水线。这个阶段的检查任务更加丰富,测试人员可以手动完成测试环境部署,并验证新功能。
|
||||
|
||||
第6步:特性经历了测试环境、预发布环境,并通过部署流水线最终部署到生产环境中。
|
||||
|
||||
在专栏的[第12讲](https://time.geekbang.org/column/article/161549)中,我提到过,持续集成的理念是通过尽早和及时的代码集成,从而建立代码质量的快速反馈环。所以,**版本控制系统和持续集成系统也需要双向打通**。
|
||||
|
||||
这里的双向打通是指版本控制系统可以触发持续集成系统,持续集成的结果也需要返回给版本控制系统。
|
||||
|
||||
接下来,我们看看具体怎么实现。
|
||||
|
||||
### 代码提交触发持续集成
|
||||
|
||||
首先,你需要在Jenkins中安装[GitLab插件](https://plugins.jenkins.io/gitlab-plugin)。这个插件提供了很多[GitLab环境变量](https://github.com/jenkinsci/gitlab-plugin#defined-variables),用于获取GitLab的信息,比如,gitlabSourceBranch这个参数就非常有用,它可以提取本次触发的Webhook的分支信息。毕竟,这个信息只有GitLab知道。只有同步给Jenkins,才能拉取正确的分支代码执行持续集成过程。
|
||||
|
||||
当GitLab监听到代码变更的事件后,会自动调用这个插件提供的Webhook地址,并实现解析Webhook数据和触发Jenkins任务的功能。
|
||||
|
||||
其实,我们在自研流水线平台的时候,也可以参考这个思路:**通过后台调用GitLab的API完成Webhook的自动注册,从而实现对代码变更事件的监听和任务的自动化执行**。
|
||||
|
||||
当GitLab插件安装完成后,你可以在Jenkins任务的Build Triggers中发现一个新的选项,勾选这个选项,就可以激活GitLab自动触发配置。其中比较重要的两个信息,我在下面的图片中用红色方块圈出来了。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/18/64/18400444f248087f0b3f33c34303ed64.png" alt="">
|
||||
|
||||
- 上面的链接就是Webhook地址,每个Jenkins任务都不相同;
|
||||
- 下面的是这个Webhook对应的认证Token。
|
||||
|
||||
你需要把这两个信息一起添加到GitLab的集成配置中。打开GitLab仓库的“设置-集成”选项,可以看到GitLab的Webhook配置页面,将Jenkins插件生成的地址和Token信息复制到配置选项中,并勾选对应的触发选项。
|
||||
|
||||
GitLab默认提供了多种触发选项,在下面的截图中,只勾选了Push事件,也就是只有监听到Git Push动作的时候,才会触发Webhook。当然,你可以配置监听的分支信息,只针对特性分支执行关联的Jenkins任务。在GitLab中配置完成后,可以看到新添加的Webhook信息,点击“测试”验证是否可以正常执行,如果一切正常,则会提示“200-OK”。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/9b/8d/9b30070e1c038d301943c2d8adcc948d.png" alt="">
|
||||
|
||||
### 持续集成更新代码状态
|
||||
|
||||
打开Jenkins的系统管理页面,找到GitLab配置,添加GitLab服务器的地址和认证方式。注意,这里的Credentials要选择GitLab API Token类型,对应的Token可以在GitLab的“用户 - 设置 - Access Tokens”中生成。由于Token的特殊性,只有在生成的时候可见,以后就再也看不到了。所以,在生成Token以后,你需要妥善地保存这个信息。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/e5/32/e533cac2cc18bb852f2e8ff200427232.png" alt=""><br>
|
||||
<img src="https://static001.geekbang.org/resource/image/db/bf/db49222bd6fac25909294de44d0204bf.png" alt="">
|
||||
|
||||
那么,配置完成后,要如何更新GitLab的提交状态呢?这就需要用到插件提供的[更新构建结果](https://github.com/jenkinsci/gitlab-plugin#build-status-configuration)命令了。
|
||||
|
||||
对于自由风格类型的Jenkins任务,你可以添加构建后处理步骤 - Publish build status to GitLab,它会自动将排队的任务更新为“Pending”,运行的任务更新为“Running”,完成的任务根据结果更新为“Success”或者是“Failed”。
|
||||
|
||||
对于使用流水线的任务来说,官方也提供了相应的[示例代码](https://github.com/jenkinsci/gitlab-plugin#declarative-pipeline-jobs),你只需要对照着写在Jenkinsfile里面就可以了。
|
||||
|
||||
```
|
||||
updateGitlabCommitStatus name: 'build', state: 'success'
|
||||
|
||||
```
|
||||
|
||||
这样一来,每次提交代码触发的流水线结果也会显示在GitLab的提交状态中,可以在查看合并请求时作为参考。有的公司更加直接:如果流水线的状态不是成功状态,那么就会自动关闭提交的合并请求。其实无论采用哪种方式,初衷都是**希望开发者在第一时间修复持续集成的问题**。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/ac/12/ac621c245c87edb3de95f7aac626c012.png" alt="">
|
||||
|
||||
我们再阶段性地总结一下已经实现的功能:
|
||||
|
||||
1. 每次GitLab上的代码提交都可以通过Webhook触发对应的Jenkins任务。具体触发哪个任务,取决于你将哪个Jenkins任务的地址添加到了GitLab的Webhook配置中;
|
||||
1. 每次Jenkins任务执行完毕后,会将执行结果写到GitLab的提交记录中。你可以查看执行状态,决定是否接受合并请求。
|
||||
|
||||
## 代码质量 - SonarQube
|
||||
|
||||
SonarQube作为一个常见的开源代码质量平台,可以用来实现静态代码扫描,发现代码中的缺陷和漏洞,还提供了比较基础的安全检查能力。除此之外,它还能收集单元测试的覆盖率、代码重复率等。
|
||||
|
||||
对于刚开始关注代码质量和技术债务的公司来说,是一个比较容易上手的选择。关于技术债务,在专栏的[第15讲](https://time.geekbang.org/column/article/165480)中有深入讲解,如果你不记得了,别忘记回去复习一下。
|
||||
|
||||
那么,代码质量检查这类频繁执行的例行工作,也比较适合自动化完成,**最佳途径就是集成到流水线中,也就是需要跟Jenkins进行打通**。我稍微介绍一下执行的逻辑,希望可以帮你更好地理解这个配置的过程。
|
||||
|
||||
SonarQube平台实际包含两个部分:
|
||||
|
||||
- 一个是平台端,用于收集和展示代码质量数据,这也是我们比较常用的功能。
|
||||
- 另外一个是客户端,也就是SonarQube的Scanner工具。这个工具是在客户端本地执行的,也就是跟代码在一个环境中,用于真正地执行分析、收集和上报数据。这个工具之所以不是特别引人注意,是因为在Jenkins中,后台配置了这个工具,如果发现节点上没有找到工具,它就会自动下载。你可以在Jenkins的全局工具配置中找到它。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/e9/2d/e919f073a1269135dcf45d04dadf8b2d.png" alt="">
|
||||
|
||||
了解了代码质量扫描的执行逻辑之后,我们就可以知道,对于SonarQube和Jenkins的集成,只需要单向进行即可。这也就是说,只要保证Jenkins的Scanner工具采集到的数据可以正确地上报到SonarQube平台端即可。
|
||||
|
||||
这个配置也非常简单,你只需要在Jenkins的全局设置中添加SonarQube的平台地址就行了。注意勾选第一个选项,保证SonarQube服务器的配置信息可以自动注入流水线的环境变量中。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/f2/38/f2907fecbee87af49cd1fffc9b6fb438.png" alt="">
|
||||
|
||||
在执行Jenkins任务的时候,同样可以针对自由风格的任务和流水线类型的任务,添加不同的上报方式。关于具体的内容,你可以参考SonarQube的[官方网站](https://docs.sonarqube.org/latest/analysis/scan/sonarscanner-for-jenkins/),这里就不赘述了。
|
||||
|
||||
到此为止,我们已经实现了GitLab、Jenkins和SonarQube的打通。我给你分享一幅系统关系示意图,希望可以帮助你更好地了解系统打通的含义和实现过程。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/0e/53/0ecc003fb103eb633c5c02c291342d53.png" alt="">
|
||||
|
||||
## 环境管理 - Kubernetes
|
||||
|
||||
最后,我们再来看看环境管理部分。作为云原生时代的操作系统,Kubernetes已经成为了云时代容器编排的事实标准。对于DevOps工程师来说,Kubernetes属于必学必会的技能,这个趋势已经非常明显了。
|
||||
|
||||
在示例项目中,我们同样用到了Kubernetes作为基础环境,所有Jenkins任务的环境都通过Kubernetes来动态初始化生成。
|
||||
|
||||
这样做的好处非常多。一方面,可以实现环境的标准化。所有环境配置都是以代码的形式写在Dockerfile中的,实现了环境的统一可控。另一方面,环境的资源利用率大大提升,不再依托于宿主机自身的环境配置和资源大小,你只需要告诉Kubernetes需要多少资源,它就会帮助你找到合适的物理节点运行容器。资源的调度和分配统一通过Kubernetes完成,这就进一步提升了资源的有效利用率。想要初始化一套完整的环境,对于中小系统来说,是分分钟就可以完成的事情。关于这一点,我会在讲“云原生时代应用的平台建设”时跟你探讨。
|
||||
|
||||
那么,**想要实现动态初始化环境,需要打通Jenkins和Kubernetes**。好在Jenkins已经提供了官方的[Kubernetes插件](https://plugins.jenkins.io/kubernetes)来完成这个功能。你可以在Jenkins系统配置中添加云 - Kubernetes,然后再参考下图进行配置。
|
||||
|
||||
需要注意的是,**必须正确配置Jenkins的地址(系统配置 - Jenkins Location),否则会导致新建容器无法连接Jenkins。**
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/b2/b0/b20afc90dc6736828c0f1bdab8fa9bb0.png" alt="">
|
||||
|
||||
生成动态节点时,需要使用到JNLP协议,我推荐你使用**Jenkins官方提供的镜像**。
|
||||
|
||||
JNLP协议的全称是Java Network Launch Protocol,是一种通用的远程连接Java应用的协议方式。典型的使用场景就是在构建节点(也就是习惯上的Slave节点)上发起向Master节点的连接请求,将构建节点主动挂载到Jenkins Master上,供Master调度使用。**区别于使用SSH长连接的方式,这种动态连接的协议特别适合于Kubernetes这类的动态节点**。镜像配置如下图所示:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/30/f5/307b1ab57a92f0359a0de3de09dff9f5.png" alt="">
|
||||
|
||||
在配置动态节点的时候,有几个要点你需要特别关注下。
|
||||
|
||||
1. ** 静态目录挂载**。由于每次生成一个全新的容器环境,所以就需要将代码缓存(比如.git目录)、依赖缓存(.m2, .gradle, .npm)以及外部工具等静态数据通过volume的方式挂载到容器中,以免每次重新下载时影响执行时间。
|
||||
1. 如果你的Jenkins也是在Kubernetes中运行的,注意**配置Jenkins的JNLP端口号**(使用环境变量:JENKINS_SLAVE_AGENT_PORT)。否则,在系统中配置的端口号是不会生效的。
|
||||
1. 由于每次初始化容器有一定的时间损耗,所以你可以**配置一个等待时长**。这样一来,在任务运行结束后,环境还会保存一段时间。如果这个时候有新任务运行,就可以直接复用已有的容器环境,而无需重新生成。
|
||||
1. **如果网络条件不好,可以适当地加大创建容器的超时时间**,默认是100秒。如果在这个时间内无法完成容器创建,那么Jenkins就会自动杀掉创建过程并重新尝试。
|
||||
|
||||
如果一切顺利,动态Kubernetes环境就也可以使用了。这时,我们就可以完整地运行一条流水线了。在设计流水线的时候,你需要注意的是**流水线的分层**。具体的流水线步骤,我已经写在了系统架构图中。比如,提交阶段流水线需要完成拉取代码、编译打包、单元测试和代码质量分析四个步骤,对应的代码如下:
|
||||
|
||||
```
|
||||
// pipeline 2.0 - Commit stage - front-end
|
||||
pipeline {
|
||||
agent {
|
||||
// Kubernetes节点的标签
|
||||
label 'pipeline-slave'
|
||||
|
||||
|
||||
}
|
||||
environment {
|
||||
// 镜像仓库地址
|
||||
HARBOR_HOST= '123.207.154.16'
|
||||
IMAGE_NAME = "front-end"
|
||||
REPO = 'front-end'
|
||||
HOST_CODE_DIR = "/home/jenkins-slave/workspace/${JOB_NAME}"
|
||||
GROUP = 'weaveworksdemos'
|
||||
COMMIT = "${currentBuild.id}"
|
||||
TAG = "${currentBuild.id}"
|
||||
TEST_ENV_NAME = 'test'
|
||||
STAGE_ENV_NAME = 'staging'
|
||||
PROD_ENV_NAME = 'prod'
|
||||
BUILD_USER = "${BUILD_USER_ID}"
|
||||
// 需要挂载到容器中的静态数据
|
||||
COMMON_VOLUME = ' -v /nfs/.m2:/root/.m2 -v /nfs/.sonar:/root/.sonar -v /nfs/.npm:/root/.npm '
|
||||
}
|
||||
stages {
|
||||
stage('Checkout') {
|
||||
steps {
|
||||
git branch: 'xxx', credentialsId: '707ff66e-1bac-4918-9cb7-fb9c0c3a0946', url: 'http://1.1.1.1/shixuefeng/front-end.git'
|
||||
}
|
||||
}
|
||||
stage('Prepare Test') {
|
||||
steps {
|
||||
sh '''
|
||||
docker build -t ${IMAGE_NAME} -f test/Dockerfile .
|
||||
docker run --rm -v ${HOST_CODE_DIR}:/usr/src/app ${IMAGE_NAME} /usr/local/bin/cnpm install
|
||||
'''
|
||||
}
|
||||
}
|
||||
stage('Code Quality') {
|
||||
parallel {
|
||||
stage('Unit Test') {
|
||||
steps {
|
||||
sh '''
|
||||
docker run --rm -v ${HOST_CODE_DIR}:/usr/src/app ${IMAGE_NAME} /usr/local/bin/cnpm test
|
||||
'''
|
||||
}
|
||||
}
|
||||
stage('Static Scan') {
|
||||
steps {
|
||||
sh 'echo "sonar.exclusions=node_modules/**" >> sonar-project.properties'
|
||||
script {
|
||||
def scannerHome = tool 'SonarQubeScanner';
|
||||
withSonarQubeEnv('DevOpsSonar') {
|
||||
sh "${scannerHome}/bin/sonar-scanner"
|
||||
updateGitlabCommitStatus name: 'build', state: 'success'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
如果你按照刚刚我所介绍的步骤操作的话,你就会得到这样一张完整的流水线演示效果图:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/0f/b3/0f36a2ac9cfc8d5878ac7cf68dcc05b3.png" alt="" title="系统截图">
|
||||
|
||||
结合Jenkins自身的人工审批环节,可以实现多环境的自动和手动部署,构建一个真正的端到端持续交付流水线。
|
||||
|
||||
## 总结
|
||||
|
||||
在今天的课程中,我通过一个开源流水线的解决方案,给你介绍了如何建立一个开源工具为主的持续交付流水线平台。你应该也有感觉,对于DevOps来说,真正的难点不在于工具本身,而在于如何基于整个研发流程将工具串联打通,把它们结合在一起,发挥出最大的优势。这些理念对于自建平台来说也同样适用,你需要在实践中多加尝试,才能在应用过程中游刃有余。
|
||||
|
||||
## 思考题
|
||||
|
||||
关于这套开源流水线解决方案,你对整体的工具链、配置、设计思路还有什么疑问吗?在实施过程中,你遇到了哪些绕不过去的问题呢?
|
||||
|
||||
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,也欢迎你把文章分享给你的朋友。
|
||||
187
极客时间专栏/geek/DevOps实战笔记/平台工具篇/28 | 迈向云端:云原生应用时代的平台思考.md
Normal file
187
极客时间专栏/geek/DevOps实战笔记/平台工具篇/28 | 迈向云端:云原生应用时代的平台思考.md
Normal file
@@ -0,0 +1,187 @@
|
||||
<audio id="audio" title="28 | 迈向云端:云原生应用时代的平台思考" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/3b/df/3b0b613ee12ad5b836858e067a4cabdf.mp3"></audio>
|
||||
|
||||
你好,我是石雪峰。
|
||||
|
||||
最近几年,相信你一定从各种场合听到过“云原生”这个词。比如云原生应用的[12要素](https://12factor.net/zh_cn/)、最近大火的现象级技术Docker,以及容器编排技术Kubernetes。其中,Kubernetes背后的CNCF,也就是云原生应用基金会,也成了各大企业争相加入的组织。
|
||||
|
||||
DevOps似乎也一直跟云技术有着说不清的关系,比如容器、微服务、不可变基础设施以及服务网格、声明式API等都是DevOps技术领域中的常客。云原生应用似乎天生就和DevOps是绝配,自带高可用、易维护、高扩展、持续交付的光环。
|
||||
|
||||
那么,所谓的云原生,到底是什么意思呢?我引用一下来自于CNCF的官方定义:
|
||||
|
||||
>
|
||||
<p>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.<br>
|
||||
云原生使用一种开源软件技术栈来部署微服务应用,将每个组件打包到它自己的容器中,并且通过动态编排来优化资源的利用率。</p>
|
||||
|
||||
|
||||
我总结一下这里面的关键字:**开源软件、微服务应用、容器化部署和动态编排**。那么,简单来说,云原生应用就是将微服务风格的架构应用,以容器化的方式部署在云平台上,典型的是以Kubernetes为核心的云平台,从而受益于云服务所带来的各种好处。
|
||||
|
||||
我在专栏中也反复强调过,容器技术和Kubernetes是划时代的技术,是每一个学习DevOps的工程师的必备技能。就像很多年前要人手一本《鸟哥的Linux私房菜》在学习Linux一样,Kubernetes作为云时代的Linux,同样值得你投入精力。
|
||||
|
||||
今天,我并不是要跟你讲Kubernetes,我想通过一个项目,以及最近两年我的亲身经历,给你分享一下,云原生究竟会带给DevOps怎样的改变。这个项目就是Jenkins X。
|
||||
|
||||
在2018年初,我分享过有关Jenkins X的文章,在短短几天的时间内,阅读量就过万了。这一方面体现了Jenkins在国内的巨大影响力,另外一方面,也凸显了Jenkins与这个时代的冲突和格格不入。为什么这么说呢?因为Jenkins作为一个15年的老系统,浑身上下充满了云原生的反模式 ,比如:
|
||||
|
||||
1. Jenkins是一个Java单体应用,运行在JVM之上,和其他典型的Java应用并没有什么区别;
|
||||
1. Jenkins使用文件存储,以及各种加载模式、资源调度机制等,确保了它天生不支持高可用;
|
||||
1. Jenkins虽然提供了流水线,但是流水线依然是执行在主节点上,这就意味着随着任务越来越多,主节点消耗的资源也就越来越多,不仅难以扩展,还非常容易被随便一个不靠谱的任务搞挂掉。
|
||||
|
||||
举个最简单的例子,如果一个任务输出了500MB的日志,当你在Jenkins上点击查看全部日志的时候,那就保佑自己的服务器能挺过去吧。因为很多时候,服务器可能直接就死掉了。当然,**我非常不建议你在生产环境做这个实验。**
|
||||
|
||||
那么,如果想让Jenkins实现云原生化,要怎么做呢?有的同学可能会说:“把Jenkins放到容器中,然后丢给Kubernetes管理不就行了吗?”如果你也是这么想的,那就说明,无论是对Kubernetes还是云原生应用,你的理解还不够到位。我来给你列举下,如果要把Jenkins改造为一个真正的云原生应用,要解决哪些问题:
|
||||
|
||||
1. 可插拔式的存储(典型的像是S3、OSS)
|
||||
1. 外部制品管理
|
||||
1. Credentials管理
|
||||
1. Configuration管理
|
||||
1. 测试报告和覆盖率报告管理
|
||||
1. 日志管理
|
||||
1. Jenkins Job
|
||||
1. ……
|
||||
|
||||
你看,我还只是列举了其中一部分,以云原生应用12要素的标准来说,要做的改造还有很多。
|
||||
|
||||
以日志为例,当前Jenkins的所有日志都是写在Master节点上的,如果想改造成云原生应用的方法,首先就是要把日志看作一种输出流。输出流不应该由应用管理,写在应用运行节点的本地,而是应该由专门的日志服务来负责收集、分析、整理和展示。比如ElasticSearch、Fluent,或者是AWS的CloudWatch Logs,都可以实现这个功能。
|
||||
|
||||
那么,Jenkins X是怎么解决这个问题的呢?
|
||||
|
||||
我们来试想一个场景:当开发工程师想要开发一个云原生应用的时候,他需要做什么?
|
||||
|
||||
首先,他需要有一套可以运行的Kubernetes环境。考虑到各种不可抗力因素,这绝对不是一件简单的事情。尤其是在几年前,如果有人能够通过二进制的方式完成Kubernetes集群的搭建和部署,这一定是一件值得吹牛的事情。好在现在公司里面都有专人负责Kubernetes集群维护,各大公有云厂商也都提供了这方面的支持。
|
||||
|
||||
现在,我们继续回到工程师的视角。
|
||||
|
||||
当他接到一个需求后,他首先需要修改代码,然后把代码编译打包,在本地测试通过。接下来,他要将代码提交到版本控制系统,手动触发流水线任务,并等待执行完毕。如果碰巧这次调整了编译命令,他还要修改流水线配置文件。最后,经过千辛万苦,生成了一个镜像文件,并把镜像文件推送到镜像服务器上。这还没完,他还需要修改测试环境的Kubernetes资源配置,调用kubectl命令完成应用的更新并等待部署完成。如果对于这次修改,系统验证出了新的问题,那么不好意思,刚刚的这些步骤都需要重头来过。
|
||||
|
||||
你看,虽然云原生应用有这么多好处,但是大大提升了开发的复杂度。一个工程师必须要熟悉Kubernetes、流水线、镜像、打包、部署等一系列的环节和新技术新工具,才有可能完成一次部署。如果这些操作都依赖于外部门或者其他人,那你就且等着吧。这么看来,这条路是走不下去的。
|
||||
|
||||
**在云时代,一切皆服务**。那么,在云原生应用时代,DevOps或持续交付理应也是以一种服务的形式存在。就好比你在用电的时候,一定不会去考虑电厂是怎么运转的,电是怎么送到家里来的,你只要负责用就可以了。
|
||||
|
||||
那么,我们来看看Jenkins X是怎么一步步地把Jenkins“干掉”的。其实,我希望你能记得,**是不是Jenkins X本身并不重要,在这个过程中使用到的工具和技术,以及它们背后的设计理念,才是更重要的**。
|
||||
|
||||
## 1.自动化生成依赖的配置文件
|
||||
|
||||
对于一个云原生应用来说,除了源代码本身之外,还依赖于哪些配置文件呢?其中就包括:
|
||||
|
||||
- Dockerfile:用于生成Docker镜像
|
||||
- Jenkinsfile:应用关联的流水线配置
|
||||
- Helm Chart:把应用打包并部署运行在Kubernetes上的资源文件
|
||||
- Skaffold:用于在Kubernetes中生成Docker image的工具
|
||||
|
||||
考虑到你可能不太熟悉这个Skaffold工具,我简单介绍一下。
|
||||
|
||||
实际上,如果想在 Kubernetes 环境中生成Docker镜像,你会发现,一般来说,这都依赖于Docker服务,也就是Docker daemon。那么常见的做法无外乎Docker-in-Docker和Docker-outside-Docker。
|
||||
|
||||
其中,Docker-in-Docker就是在基础镜像中提供内建的Docker daemon和镜像生成环境,这依赖于官方镜像的支持。而Docker-outside-Docker比较好理解,就是将宿主机的Docker daemon挂载到Docker镜像里面。
|
||||
|
||||
有三种典型的实现方式:第一种是挂载节点的Docker daemon,第二种就是使用云平台提供的外部服务,比如Google Cloud Builder,第三种就是使用无需Docker daemon也能打包的方案,比如常见的Kaniko。
|
||||
|
||||
而Skaffold想要解决的就是,你不需要再关心如何生成镜像、推送镜像和运行镜像,它会通通帮你搞定,依赖的就是skaffold.yaml文件。
|
||||
|
||||
这些文件如果让研发手动生成,那会让研发的门槛变得非常高。好在你可以通过Draft工具来自动化这些操作。Draft是微软开源的一个工具,它包含两个部分。
|
||||
|
||||
- 源代码分析器。它可以自动扫描你的源代码,根据代码特征,识别出你所用到的代码类型,比如JavaScript、Python等。
|
||||
- build pack。简单来说,build pack就是一种语言对应的模板。通过在模板中定义好预设的环境依赖配置文件,包括上面提到的Dockerfile、Jenkinsfile等,从而实现依赖项的自动生成和创建。当然,你也可以定义自己的build pack,并作为模板在内部项目中使用。
|
||||
|
||||
很多时候,模板都是一种特别好的思路,它可以大大简化初始配置成本,提升环境和服务的标准化程度。对于流水线来说,也是如此,毕竟,不是很多人都是这方面的专家,只要能针对90%的场景提供一组或几组最佳实践的模板就足够了。
|
||||
|
||||
这样一来,无论是已经存在的代码,还是权限初始化的项目,研发都不需要操心如何实现代码打包、生成镜像,以及部署的过程。这也会大大节省研发的精力。毕竟,就像我刚刚提到的,不是每个人都是容器和构建方面的专家。
|
||||
|
||||
## 2.自动化流水线过程
|
||||
|
||||
当应用初始化完成之后,流水线应该是开箱即用的状态。也就是说,比如项目采用的是特性分支加主干开发分支发布的策略,那么,build pack中就预置了针对每条分支的流水线配置文件。这些文件定义了每条分支需要经过的检查过程。
|
||||
|
||||
那么,当研发提交代码的时候,对应的流水线就会被自动触发。对于研发来说,这一切都是无感知的。只有在必要的时候(比如出现了问题),系统才会通知研发查看错误信息。这就要求**流水线的Jenkinsfile要自动生成,版本控制系统和CI/CD系统也需要自动打通**。比如,Webhook的注册和配置、MR的评审条件、自动过滤的分支信息等等,都是需要自动化完成的。
|
||||
|
||||
这里所用到的技术主要有三点。
|
||||
|
||||
1. **流水线即代码**。毕竟,只有代码化的流水线配置才有可能自动化。
|
||||
1. **流水线的抽象和复用**。以典型的Jenkinsfile为例,大多数操作应该提取到公共库,也就是shared library中,而不应该hard code在流水线配置文件里面,以提升抽象水平和能力复用。
|
||||
1. **流水线的条件判断**。对于同一条流水线来说,根据不同的条件,可以实现不同的执行路径。
|
||||
|
||||
## 3.自动化多环境部署
|
||||
|
||||
对于传统应用来说,尤其是对上下游依赖比较复杂的应用来说,环境管理是个老大难的问题。Kubernetes的出现大大简化了这个过程。当然,**前提是云原生应用部署在Kubernetes上时,所有依赖都是环境中的资源**。
|
||||
|
||||
依靠Kubernetes强大的资源管理能力,能够动态初始化出来一套环境,是一种巨大的进步。
|
||||
|
||||
Jenkins X默认就提供了预发环境和生产环境。不仅如此,对于每一次的代码提交所产生的PR,Jenkins X都会自动初始化一个预览环境出来,并自动完成应用在预览环境的部署。这样一来,每次代码评审的时候,都能够打开预览环境查看应用的功能是否就绪。通过借助用户视角来验收这些功能,也提升了最终交付的质量。
|
||||
|
||||
这里面所用到的技术,除了之前我在第16讲中给你介绍过的GitOps,主要就是**Prow工具**。
|
||||
|
||||
你可以把Prow看作ChatOps的一种具体实现。实际上,它提供的是一种**高度扩展的Webhook时间处理能力**。比如,你可以通过对话的方式,输入 /approve 命令,Prow接收到这个命令后,就会触发对应的Webhook,并实现流水线的自动执行以及一系列的后台操作。
|
||||
|
||||
## 4. 使用云原生流水线
|
||||
|
||||
在今年年初,Jenkins X进行了一次全面的升级,开始支持Tekton流水线。Tekton的前身是2018年初创建的KNative项目,这是一个面向Kubernetes的Serverless解决方案。但随着这个项目边界的扩大,它渐渐地把整个交付流程的编排都纳入了进来,于是就成立了Tekton项目,用来提供Kubernetes原生的流水线能力。
|
||||
|
||||
Tekton提供了最底层的能力,Jenkins X提供了上层抽象,也就是通过一个yaml文件的形式来描述整个交付过程。我给你分享了一个流水线配置文件的例子:
|
||||
|
||||
```
|
||||
agent:
|
||||
label: jenkins-maven
|
||||
container: maven
|
||||
pipelines:
|
||||
pullRequest:
|
||||
build:
|
||||
steps:
|
||||
- sh: mvn versions:set -DnewVersion=$PREVIEW_VERSION
|
||||
- sh: mvn install
|
||||
release:
|
||||
setVersion:
|
||||
steps:
|
||||
- sh: echo \$(jx-release-version) > VERSION
|
||||
comment: so we can retrieve the version in later steps
|
||||
- sh: mvn versions:set -DnewVersion=\$(cat VERSION)
|
||||
- sh: jx step tag --version \$(cat VERSION)
|
||||
build:
|
||||
steps:
|
||||
- sh: mvn clean deploy
|
||||
|
||||
```
|
||||
|
||||
在这个例子中,你可以看到,流水线过程是通过yaml格式来描述的,而不是通过我们之前所熟悉的groovy格式。另外,在这个文件中,你基本上也看不到Tekton中的资源类型,比如Task、TaskRun等。
|
||||
|
||||
实际上,Jenkins X基于Jenkins原有的流水线语法结构,重新定义了一套基于yaml格式的语法。你依然可以使用以前的命令在yaml中完成整个流水线的定义,但是,在后台,Jenkins X会将这个文件转换成Tekton需要使用的CRD资源并触发Kubernetes执行。
|
||||
|
||||
说白了,用户看起来还是在使用Jenkins,但实际上,流水线的执行引擎已经从原来的JVM变成了现在Kubernetes。流水线的执行和调度由Kubernetes来完成,整个过程中每一步的环境都是动态初始化生成的容器,所有的数据都是通过外部存储来保存的。
|
||||
|
||||
经过这次升级,终于实现了真正意义上的平台云原生化改造。关于这个全新的Jenkins流水线语法定义,你可以参考下[官方文档](https://jenkins-x.io/docs/reference/pipeline-syntax-reference/)。
|
||||
|
||||
我再给你分享一幅Serverless Jenkins和Tekton的关系示意图,希望可以帮助你更好地理解背后的实现机制。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/4c/8f/4cb1d827f29ca6d2a55f13ab9b60a58f.jpeg" alt="">
|
||||
|
||||
>
|
||||
[https://dzone.com/articles/move-toward-next-generation-pipelines](https://dzone.com/articles/move-toward-next-generation-pipelines)
|
||||
|
||||
|
||||
最终,我们希望达到的目的,就是不再有一个一直存在的Jenkins Master实例等待用户调用,而是一种被称为是“Ephemeral Jenkins”的机制,也就是一次性的Jenkins,只有在需要的时候才会启动一个Master实例,用完了就关闭掉,从一种静态服务变成了一种转瞬即逝的动态服务,也就是看似不在、又无处不在的形式,以此来驱动云原生应用的CI/CD之旅。
|
||||
|
||||
讲到这里,我们回头再看看最开始的那个场景。对于享受了云原生流水线服务的工程师而言,他所需要关注的就只有把代码写好这一件事情,其他原本需要他操心的事情,都已经通过后台的自动化、模板化实现了。
|
||||
|
||||
即便是在本地开发调试,你也完全可以利用Kubernetes提供的环境管理能力,甚至在IDE里面,只要保存代码,就能完成从打包、镜像生成、推送、环境初始化和部署的完整过程。我相信,这也是云原生工具赋能研发的终极追求。
|
||||
|
||||
## 总结
|
||||
|
||||
最近这两年,经常有人问我,Jenkins是不是过时了?类似Argo、Drone等更轻量化的解决方案是否更加适合云原生应用的发展?
|
||||
|
||||
其实,社区的开发者也在问自己这样的问题,而答案就是Jenkins X项目。这个项目整合了大量的开源工具和云原生解决方案,其中包括:
|
||||
|
||||
- 基于Kubernetes的云原生开发体验
|
||||
- 自动化的CI/CD流程
|
||||
- 多套预置的环境,并能够灵活初始化环境
|
||||
- 使用GitOps在多环境之间进行部署晋级
|
||||
- 云原生的流水线架构和面向用户的易用配置
|
||||
- 可插接自定义的流水线执行引擎
|
||||
|
||||
我必须要承认,云原生带给平台的改变是巨大且深刻的。这两年,我一方面惊叹于社区的巨大活力和创新力,另一方面,我也深刻地意识到“未来已来”,这种变更的脚步越来越近。
|
||||
|
||||
在云原生时代,我们需要打造的也应该是一个自动化、服务化、高度扩展的平台。这也就是说,**用于打造云原生应用的平台自身也应该具备云原生应用的特征**,并通过平台最大化地赋能研发工程师,提升他们的生产力水平。
|
||||
|
||||
## 思考题
|
||||
|
||||
对于DevOps的落地推行来说,建设工具仅仅是完成了第一步,那么,如何让工具发挥真正的威力,并在团队中真正地进行推广落地呢?你有哪些建议呢?
|
||||
|
||||
欢迎在留言区写下你的思考和答案,我们一起讨论,共同学习进步。如果你觉得这篇文章对你有所帮助,也欢迎你把文章分享给你的朋友。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user