更多相关文章阅读
作者简介:
顾宇
ThoughtWorks 高级咨询师,9年工作经验。加入ThoughtWorks之前曾经参与中国移动,中国联通省级BOSS系统以及呼叫中心系统的研发、实施和割接。担任过售前,项目经理,维护工程师和开发工程师等职务。拥有丰富的大型系统开发及维护的实战经验。
本文我将分享之前咨询DevOps客户的案例,他们做的是在Jenkins的基础上构建一个他们自己的CI环境。我把两个客户的例子混合到一起了,其中一个大概有80个人左右,另外一个是250个人的团队。
下面是主要分享的内容:
大型团队与小型团队的区别
不同团队会碰到的问题
核心思路与解决方法
大家认为一个大型团队有多大?一般来说是以人数定义的,可能有50-100人,当你工作一段时间之后,你发现你团队里面的人名字你说不全的时候,这时候你就是面对的一个大型团队。
接下来的例子,为了您的团队扩张,你可以做一些提前的准备,我们在碰到大型团队Jenkins碰到的一些问题和我们的一些解决方案。
大团队和小团队的区别,大家可以看到这个是正步走,正步走一排排练,阅兵时是右边那样。
这里面最大的问题,当我在小团队进行组织和培训,和运行Jenkins做持续交付的时候,很多问题你是看不出来的,只有到了大团队中,这些很小的团队碰到的小问题,在大团队中才会成倍出现,变成非常大的阻碍。可能在之前小团队你觉得不是问题的问题,到了大型团队,它可能就是很严重的问题。
我们碰到的第一个问题,首先小型团队里会有很多手工而且低效的任务,因为你的软件构建比较简单,可能花十几分钟、二十几分钟就了不起了。
他这个手动任务在你整个Jenkins中占据的流水线时间不会太长,但是如果这样的任务多了之后,在一个很大的团队里在用一个Jenkins的时候,会出现成倍的问题。
但是自动化也会有其他的问题,当我们把这些任务都自动化起来之后,会出现另外一个问题,当我们在构建的时候,我们会发现一个人出现了一个问题,他把整个CI流水线弄挂,所有人都要等他把这个问题修复。
可以夸张到什么程度?之前某一个深圳非常大的电信制造商客户,他们的CI流水线因为两行代码的测试没有通过,他们200人停工两天。当然这不仅仅是找问题花的时间很长,其他人跟这个问题没有关系也被拖长了。
出现另外一个问题,出现一个大型系统的时候,一个大型团队解决大型软件的时候,CI大楼是不能倒的。
另外一个案例,有一天CI在做基础设施迁移的时候,CI做水平拓展,CI突然挂了,引发了另外半天的停工。针对大型云产品的时候,他这个CI就不能倒,这是两个非常大的痛点,一个是一个人稍微把这个CI一挂,所有人都要停工,检查各种各样的问题。另外一点,CI如果混合到一起,会有很多依赖点,会让整个CI停工。
大团队在用Jenkins的时候,大团队会把小问题放大。
这是我列出的几个明显的几个点:
不知道有没有人在一个Jenkins中配200个人,你肯定碰到到第80个人的时候,整个用户配置界面会卡,我们当时的客户就是手工去干这个事情。
由一个部门解决所有团队的问题,他们是一个大型云产品,因为很大,所以要有一个人来处理整个CI,这个部门来解决所有的问题,就变成很大的阻塞。
一个人出错,所有团队就会被阻塞,停工两天,对他们交付压力来说,这个停工是被可被原谅的。当时那个情况是我引起的,因为我要优化他的CI,水平扩展他的Jenkins,最后就发现,他这个CI大楼不能倒。
核心思路,左边这个是乐高的泰坦尼克号的模型,右边是乐高积木,第一个,碰到大型CI的时候,这首先不是一个技术问题,是一个沟通性和组织管理的问题。
第一个是康威定理,系统的结构跟我组织的沟通结构是一致的,碰到这种问题的时候,首先你要考虑的,他这个技术问题引发背后的组织上的结构问题,首先要把整个软件系统包括我的组织架构拆解变成小的块,就像乐高积木一样,先把小块构建好,再去构建大的,就不会有问题,而且我这些小块都可以并行构建。任何一块挂了之后都不会导致一整艘船沉船。
组织架构和应用架构双解耦,一般当碰到大型CI的问题的时候,不会是一个组织的问题,首先要把组织架构先拆开,会分成不同的团队,每个团队有自己的CI,这样就可以让不同的团队并行扩展,再设置一个总的CI,让不同团队之间的CI产物再进行一次集成性的构建,这就是分阶段分层次的持续集成,但不会集成到一个CI里。
不要设立持续集成管理部门,有没有朋友你们的公司有一个团队或者有一个部门是专门管CI的?我知道的目前的案例里华为是这样的,他们有这么一个持续管理部门。
按一个正常的流程来说,我们从开发、测试到这个平台,他们这个案例里有个平台,因为他们的基础设施跟我们外部云的基础设施不一样,他们有些硬件需要定制化,所以他这个平台会产生一些工作量,没有办法像我们外部应用上扩展很多平台,所以要花一个单独的时间去构建他的测试平台,然后才到他的运维,然后交付产物。
但是如果你有一个CI部门,你的沟通结构可能是这样,当我有问题的时候,所有人都会找这个CI部门,这个CI部门就成为你这个团队效率的最大瓶颈。
设立CI部门的初衷很容易理解,在一个大型软件、一个大型的团队,我们需要把所有的任务和模块拆得足够细足够小,让很多人能够快速上手,我们就会有一个专业的部门去专门管理这个CI,但是这个专门的部门,因为他要负责整个流水线,在整个流水线上所有的人都要跟他产生关系,而他们不会相互解决问题。
如果你设立了一个持续管理部门,你的团队在扩张的时候肯定会出现这样的问题。好一点的,水平价值流一直想右流动,没有问题,我只是在中间跟CI集成有问题的时候,我去找CI管理部门,这种情况最好的情况,CI部门的工作量是不饱和的。
另外一种情况,应用到Jenkins上,有两种方式,一种方式是运维的团队来管理CI,他管理Jenkins会让他做持续部署、标准化部署和自动化部署。
但是如果有单独的CI管理部门,那么他在DevOps包括持续交付上都会成为瓶颈。我能给你的第一个,大型团队用Jenkins第一个建议,千万不要设立持续集成管理部门,最多做到让运维团队来管理CI。但是这种水平的沟通要各团队之间来沟通。
第二个核心思路,手动变自动,把我们很多的Jenkins的任务变成自动触发的。
大家看完持续交付之后,所有的流水线,不管多复杂,只是分为三种状态的阶段,三种状态是构建后、测试中和发布后,在这三个状态之间有两个流程转换,第一个,从我构建后到我测试中,这是一个测试的状态,测试中到发布后这是发布的状态,中间可能会有部署。所有的流水线都可以变成这三个状态两个步骤。
在这两个步骤里面,只有这两个步骤是可以或者必须手动化的,剩下的都可以做到自动化。自动化的时候有一个问题,在Jenkins里面,当你这个Jenkins复杂之后,你会发现你要管理很多插件,这是你构建Jenkins和复制Jenkins面对最大的问题。一会儿会说到流水线及代码。
有多少团队,你的Jenkins集成LDAP,当你的团队变多的时候,这是一个非常重要的,你会有很多系统集成,你会有很多用户访问的单点登录类似于这样的东西。一个人手动去管理一百多人的Jenkins用户的时候,可能会有这样的问题,如果你企业有LDAP,你可以很容易的集成到一起。
当你把这个团队一个应用拆分成不同团队、不同模块,每个团队负责每个模块的时候,一定要做到一个代码库一条流水线。
有个客户案例是这样的,他有一个代码库,这是一个80人的团队,他有一个单一的代码库,设置了25个brunch,他写了一个插件,构建一条流水线,代码库上除了Master以外和开发分支以外,每一个分支都会有一条流水线。
它带来的问题,后面的分支越多,合并到后面就越来越困难。而且如果要做到好的持续交付,建议一个代码库一条流水线。
另外一点,自动化,这是Jenkins的最新版本,Pipeline插件,Pipeline即代码,这个过程当中会自动生成流水线。
当我扩展Jenkins的时候或者让Jenkins支持大型团队的时候,插件是很难管理的,这里建议尽量不要用Jenkins插件,我之前讲过关于Jenkins安全的,Jenkins的插件包括Jenkins本身,它是有一些漏洞的,当你去用一些插件的时候,你要不停的更新它,当你Jenkins倒了之后要去恢复它,插件是很难自动化的,当然你可以用代码自己写一个安装插件的脚本,但是它的速度仍然不够快,而且很难管理。
建议你碰到,Pipeline即代码,用工具写一些脚本,来处理这个问题。在Pipeline As Code中,大家会碰到,在过程中会用P去访问密码,这个东西尽量不要放到你的代码库里,因为可能会造成安全性问题,而且不同的团队,尤其是大型的Jenkins团队里在使用它的时候,也会造成一定的隐秘信息泄露。
每次在Pipeline取的时候,可以通过中心的数据库取到对应的。有些人会在Jenkins里设置环境变量,通过单次方式注入的方式运行。另外有的团队会用Docker作为持续交付的统一产生镜像,给大家做一个推荐,在Pipeline As Code过程当中,可以用clair,可以做Docker镜像的安全扫描,如果你用Docker作为整个Jenkins流水线的交付产物,它可以对你的镜像进行扫描,在你push到你Docker的镜像仓库之前。
如果你有大型团队,因为我有流水线即代码,个人很容易自己去做一个CI,这样就会解决刚才在大型团队里出现一个问题,核心CI公共CI挂了之后,如果你的团队大了之后,CI会变成一种关键资源,会变成一种稀缺资源,每个人都需要它。
但是我们要把它分享到每个人,如果你有刚才流水线即代码的技术,你可以让每个人自己搭建CI,只有不得不在公共环境里运行的任务才把它放上去去进行大型的集成,否则剩下的任务你自己都可以做,这样减少在大型公共环境上阻碍的时间。
在DevOps里面很重要的一个概念,部署和发布解耦,部署是一个技术动作,是把你构建出来的镜像部署到你的生产环境上,而发布是一个业务动作,是让你的用户面向你真正需要访问的程序。
在这里面有很多团队,最近我们公司出现一个不太好的案例,由于部署和发布没解耦,我这个环境上修改这些代码直接到生产环境去。很多做DevOps的团队来说,说这样部署频率很快,但是你也更快的把你的问题带给了你的最终用户。
所以建议在这个地方设置一个手动的环节,在你正式发布之前能做一些测试,你可以把你的应用程序部署到你的生产环境上去,然后做蓝绿部署,中间切换一下就可以。但是不要直接把你的代码让最终用户看到,这样会带来很多问题。
研发CI和生产CI是要分离的,这是我们最近碰到的问题,当你这个团队并不是一个DevOps团队的时候,你仍然想让DevOps团队去做的时候,如果你的运维团队控制了整个的CI,那么它会严格你这个团队整个流水线CI的使用。
这时候就要做一个解耦,让我们的研发在网络里面,这个网络里面只有我这个制品库是对应发布的唯一的出口,所有的开发环境自己有个CI,不断在自己的测试环境上去做测试,到最后由运维团队从生产环境的CI去取得我的镜像,部署到我的生产环境上,最后发布。
这样可以把我两个不同运转速度的团队,把它分离开,否则你如果变成一个CI的话,任何一个点的阻塞,很可能是组织结构上的阻塞,会造成你整个流程上的阻塞。
当你有了一个基础设施即代码的环境的时候,制品库不是必要的,这对很多使用Docker作为持续部署和发布的团队来说,这点是很重要的。你会发现你很多的工作,可能一天里60%、70%的时间都是在不断的build Docker镜像。
如果你是用Jenkins和Docker,同样不建议你用Jenkins的Docker插件,因为它也是一个阻碍你效率的环节。Docker一个比较好的实践,我这个Docker的镜像是很少去变更的,它是一个稳定的运行环境,而你的代码是可以挂载到我的Docker镜像作为一个运行环境。
举个例子,如果你用Nginx,经常切换Nginx配置,如果改成一两行配置部署一下,大概算了一下,等你构建完镜像再部署起来,到生产环境上,整个环境大概要15分钟。
但如果你是直接在生产环境上去修改Jenkins配置文件,可能只需要几秒钟就完成了,大大缩短整个构建的速度和部署的速度、修改的速度。
当然有很多容器集成的时候,在一起进行编排的时候,这个问题就会成倍的扩张。
如果你的基础设施环境是不一样的,你有很多基础设施环境,那你的制品库不是必要的,你的应用程序的代码是一个代码仓库,你的基础设施代码是另外一个代码仓库,它们只要存在一一对应的版本对应关系就可以,我只需要知道这个应用需要那个基础设施,我们之前的例子,某个电信厂商,他的基础设施变更是很麻烦的一件事情,有个镜像仓库他还要去调镜像仓库的问题,我部署之后再改我的基础设施。
如果你把你的基础设施代码配置起来,和你的应用代码形成一一对应关系的时候,它会在构建应用之前就把对应版本的基础设施构建起来,这样可以充分使用你的开发和测试的生产环境。
END
更多相关文章阅读
Jenkins创始人带您探访国内首届Jenkins用户大会(附PPT)
高效运维社区2017年最后一季课程排期来袭
预报名请填写问卷
更多课程详情、企业内训或其他业务,可以咨询我们的课程顾问哟~
如果您在华南、华东、东北、港澳台地区,可以找TA 丛琳: 18811333909 (同微信)
如果您在华北、华中、西南、西北地区,可以找TA 杨文惠:13021086339(同微信)
点击阅读原文下载 GOPS2017·上海站演讲PPT(密码: egeq)