前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >GoCD的正确打开方式|洞见

GoCD的正确打开方式|洞见

作者头像
ThoughtWorks
发布2018-04-17 17:15:23
2.8K0
发布2018-04-17 17:15:23
举报
文章被收录于专栏:ThoughtWorksThoughtWorks

事件:ThoughtWorks在2016年11月发布的技术雷达中将“Jenkins as a deployment pipeline”列为了“暂缓”。

Jenkins以“持续集成”闻名,进入持续交付时代后,常被人们用来尝试搭建deployment pipeline,我以前也乐此不疲。遗憾的是Jenkins的设计是以单个job为核心,deployment pipeline的实现需要靠官方或社区插件来支持,看上去都能实现,但在实际使用中总让我觉得差了点什么。最近的一则广告可以完美表达这种体验:

(图片来自:http://t.cn/RX7EvfT)

不拼凑,纯pipeline?

ThoughtWorks坦言将“Jenkins as a deployment pipeline”列为了“暂缓”是相当冒险的,因为ThoughtWorks在此领域有一款竞争产品:GoCD。GoCD曾是一款商业产品,现已追随大潮进行了开源,身边一些朋友尝试之后褒贬不一,有人反馈它忠实还原了《持续交付》中提到的pipeline,也有人反馈较难上手。我想结合技术雷达分享一些GoCD的使用经验,希望对正在尝试GoCD的同学有所帮助。

建议一 :如果你不需要deployment pipeline,不要使用GoCD

用惯jenkins job做持续集成的同学,往往一上来就被GoCD的配置界面搞得晕头转向:

"我只是想运行一下mvn clean package怎么有这么多东西要设置,stage、job、task都是什么鬼?"

(信息量好大)

GoCD在设计之初就将deployment pipeline作为“一等公民”,实现复杂交付流程是其强项,但如果你需要的只是持续集成,就有点杀鸡用牛刀了。因此,重要的话说三遍:

  • 如果你不需要deployment pipeline,不要使用GoCD。
  • 如果你不需要deployment pipeline,不要使用GoCD。
  • 如果你不需要deployment pipeline,不要使用GoCD。

如果看到这里,你还没有关闭页面,那让我们来看一下GoCD的pipeline元素吧。

P代表pipeline,S代表stage,J代表job,T代表task

Pipeline可由若干个stage组成,stage之间可以设置依赖关系,默认上游stage失败的时候不会触发下游stage。stage可由多个job组成,但多个job一般用在并行任务的用例中(例如并行构建多个模块),它们之间是没有依赖关系的,所以如果你希望某个stage执行一系列有依赖关系的动作,应该使用单个job并为其设置多个task,而不是多个job。这里比较容易产生误会的是job,因为它和jenkins job同名。一个典型的pipeline可能会按如下设计:

每个stage代表一个阶段,build&test负责构建和单元测试,IntDeploy负责自动化端到端测试,UATDeploy负责手工测试,Prd_Deploy则负责部署生产环境,每个stage最简可由一个job组成,job中的task依次完成自动化任务。

Pipeline、stage、job、task使得GoCD可以组合串行、并行执行,实现复杂、精巧的工作流。但就像硬币的另一面,这些概念也提高了入门门槛,再加上原有的UI交互设计得比较繁琐,往往需要来回地切换编辑页面才能完成整个pipeline的设置,也难怪用户抱怨了。

改善

不过好消息是,“Have a better getting-started experience”已列入GoCD roadmap,一个全新的"quick edit"功能也已经发布(需要16.9.0以上)。

全新的"quick edit"功能,让你可以在单个页面即完成pipeline的配置,操作更简便。 而对于熟手来说,本文后面提到的“实现pipeline as code"更合胃口。

建议二:必备插件——script-executor-task

曾经有朋友向我吐槽GoCD的task太难用了,每个task只能执行一条命令,导致每个job都有十几个task。

(琐碎的tasks,使用前)

其实,你需要的是一款叫做“script-executor-task”的GoCD插件。是的,你没有看错,GoCD也是有插件的!有了这款插件后,你就可以像shell脚本一样编排指令,从而愉快地合并臃肿的task了。

(使用后)

不可矫枉过正

值得一提的是,这个插件的初衷是简化task中命令的书写和排序,而不提倡滥用它编排大量琐碎的指令。不管是用jenkins还是GoCD,最佳实践是将指令放到脚本文件中,并纳入代码版本仓库(SCM)。可以签出的脚本方便团队所有人查看,更改也有迹可循,便于协作;另一方面脚本与工具的耦合也最小(往往就是一行命令),我们将在“实现Pipeline as Code”一节中继续讨论这个话题。

建议三:你使用Artifact Repository了吗?

Pipeline的各个环节本质上是在验证构建出的artifact(以下翻译为二进制包)是否符合质量标准,这就要求pipeline能够正确识别和传递artifact。“只生成一次二进制包”是pipeline设计中的一条重要原则,下游步骤应该重用上游步骤生成的二进制包。 相比每次从源代码构建二进制包,这节约了宝贵的反馈时间,更重要的是它实现了“你所测试的二进制包就是将要发布的二进制包”的配置管理需求。

Gocd对此提供内建支持:publish artifacts和fetch artifact task(相比jenkins需要copy artifact plugin并且需要细心选择上游job,详见基于Jenkins实现的部署流水线中共享二进制包。)

(上游构建stage将artifact到gocd自带的artefact repository)

(下游部署stage从构建stage抓取artifact)

一个容易出现误解的地方是,在没有使用publish/fetch artifact功能的情况下,试图在同一个pipeline的stage间共享artifacts,这很可能造成artifact传递错误,严重的时候可能造成向生产环境发布未经测试的二进制包。

如上例中,分别在commit-stage和acceptance-stage中取消publish/fetch build/version,只要这两个stage都分配在同一个go-agent上执行,也不会报错。假设现在pipeline build number为892,运行pipeline build number为890的acceptance-stage也会取得一份build/version文件,但这份文件的来源是该go-agent上最近一次commit-stage运行后生成的(很可能是由pipeline build number892),未必是pipeline build number为890的commit-stage生成的,这样就出现了artifact版本错位。

(隐蔽的artifact版本错误)

重视artifact repository并且正确实现artifact共享是一条合格deployment pipeline的重要标志,只有这样artifact的来源才能够回溯,才能检查它是否符合了发布的标准,才有信心真正实现一键发布到生产环境。

应用publish/fetch artifact是生成正确Value Stream Map的前提,通过Value Stream Map可以直观地观测artifact经历的质量检查步骤和结果,作为是否发布此artifact的前置条件。

专用artifact repository

最后多嘴一句,虽然Gocd提供了内置的artifact repository,但我强烈推荐使用专用的artifact repository产品(例如java常见的sonatype nexus或者私有Docker Registry)。这些产品往往有更好的GUI和周边工具支持,可以帮助你更好地管理artifacts。在这种方案中,我建议使用Gocd的artifact repository来作为publish/fetch artifact的唯一标识符(通常以文件形式),在各pipeline及其stage之间共享这个唯一标识符,而artifact本身的publish/fetch则交给专用的artifact repository,并通过唯一标识符来识别。

(专用artifact repository方案)

建议四:实现Pipeline as Code

严格来说,不管是GoCD还是jenkins,早就可以通过编辑config文件或使用API来实现pipeline as code了,但它们都不易使用。前者因为config文件掌管着全局配置,粒度太粗,实际上只可能由专人维护,成为瓶颈。后者则往往需要开发客户端程序。随着infrastructure as code概念的流行,开发团队希望更灵活且更可靠地管理自己的pipeline(如果你用过Travis CI,会对这种方式很熟悉)。从16.7开始,GoCD提供了更友好的pipeline as code支持,可以通过yaml或json定义pipeline,并将配置文件放到SCM(git或其他)中,GoCD会自动获取定义文件并生成pipeline。

(GoCD可以兼容手工配置和文件配置,所以你可以在部分pipeline上尝试这种技术)

configuration deployment

那么pipeline定义文件是放在应用源代码仓库还是单独放在独立代码仓库呢?我的建议是:都可以。但是如果deployment-pipeline含有部署环节,且部署不同环境需要不同的环境变量时,我建议把流水线本身拆开:

  1. 构建环节作为一条单独的pipeline,这条pipeline由自动触发的stage组成,目标是构建artifact,如果有条件的话还进行一些端到端的自动化验证。这条pipeline的定义文件可以和项目源码仓库放在一起,因为pipeline的改变常常也影响了artifact本身的构建,它们的变化节奏应该是一致的。
  2. 部署环节作为一条(或多条,视环境数量决定)单独的pipeline,这条pipeline由fetch artifact开头,其定义文件可以和部署脚本及环境变量放在一起,它们的变化节奏应该是一致的。与负责构建的pipeline分开的原因是,当你想为QA环境部署一次配置变更时(如果你使用了特性开关,这种情况很常见),往往并不希望等待pipeline重新再构建一次artifact。

(部署pipeline与构建pipeline分离,可以实现 configuration deployment,单独部署环境变量变更)

期待:缺乏统计报表类功能/插件

deployment-pipeline不是设计出来的,而是演化来的。

deployment-pipeline的初衷是希望能够通过自动化和可视化来消除交付活动中的瓶颈,但如果不精心维护,pipeline自身可能也会出现瓶颈。例如随着自动化测试用例逐渐增多,反馈周期也会随之变长,这时需要重构pipeline以便消除瓶颈,但如何重构,重构的效果是需要用数据来度量的。jenkins有一些插件可以统计job的平均执行时间,job失败后的平均恢复时间等指标,可以用来指导团队重构pipeline。遗憾的是,GoCD对此没有内建的功能支持,而plugin还不够丰富,暂时存在空白。让我们期待官方和社区在这方面有所作为吧。

写在最后

感谢你耐心看完本文,最后把重要的话再说三遍:

如果你不需要deployment pipeline,不要使用Gocd。

如果你不需要deployment pipeline,不要使用Gocd。

如果你不需要deployment pipeline,不要使用Gocd。

但是这年头,应用软件交付怎么会不需要deployment pipeline呢?


本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-04-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 思特沃克 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档