我居然用一周时间开发完了基于Tetkon的CICD发布系统

         人毕竟要与时俱进,所以我这次尝试了下用这种标题来哗众取宠一下,最终我还是活成了自己最讨厌的样子

        言归正传,写这篇文章是想记录下上周我做的一件事情:

                改造了原先公司内部自研的CICD发布系统

                采用基于Tekton的CICD发布系统

         很多基础的概念就不多做介绍了,CI/CD作为DevOps中重要部分,在公司内部承担了每个应用系统的日常迭代工作。

          许多公司会采用自研的方式来构建自己的CICD平台,已实现许多环节的自定义需求,另外一些公司会基于开源的CICD平台,例如大家都听说过的Jenkins,构建应用流水线来实现。

        而这次基于Tekton的CICD发布系统,也是一种新的尝试。

当前CICD架构介绍

        CI/CD分为两个环节,CI(持续集成)和CD(持续发布)。CI是生产应用对应的制品(war、jar、可执行二进制文件、镜像),CD是将制品以各种方式部署到对应的环境。

        我们公司的发布系统是自研的,采用自研的原因是当时还没有很成熟的开源CICD平台(Jenkins还没有像现在这么成熟,JenkinsFile还没有出现),另外自研能够更加灵活的满足需求,提前是我们拥有自研的人力和能力。

        另外对CICD系统,在设计的时候,我们引入了标准化应用的概念,针对不同语言的应用工程,将其应用的目录结构,配置文件等制定对应的规范,发布系统会根据对应的规范进行CICD操作。这样的好处是,减少应用之间的差异性,对于开发人员和运维人员开发和排除问题都提高了效率。

原先的架构如下:

  • 门面工程:用于处理页面请求,应用的管理、CICD的配置等等
  • 流水线工程:根据应用的类型,装配该应用的流水线。流水线应用属于核心应用,举个例子对于应用需要前端代码部署的,在流水线中可以增加前端构建这个节点,或是云原生化的应用,在代码构建完成后,可以新增镜像构建的节点,来完成docker build的任务。
  • 原子任务处理工程:当流水线装配完成后,整条流水线是由一个个原子任务组成,该工程就是处理这些原子任务,然后将结果返回。

        

        分析整个架构,流水线工程是核心工程,它控制着整个流水线装配、运行。但是真正处理任务的工程是原子任务处理工程,当公司业务发展,应用的日常部署的增加或减少,对应的原子任务处理工程是需要支持弹性的伸缩,来面对任务数量的变化。

        当前的架构,在原子任务处理工程,是用Python写的系统,通过MQ接收原子任务,然后可以横向部署云服务器,通过NFS或者COS等方式,进行任务间的文件传递。

        在前几年进行应用云原生化推进的工作中,我们也对CICD进行了改造,这样对业务开发人员而言,云原生化的推进相对而言是无感知的,和原先的差异并不是很大。在完成整体的推进之后,反观整个CICD平台,我觉得有个点可以值得探索和尝试下,就是接下来的内容:

Tekton和Argo Workflow

        在之前为了云原生发布对CICD系统改造的过程中,我也分析了当前主流的开源CICD平台。

        对于大家都耳熟能详的Jenkins,也推出了围绕 Kubernetes的Jenkins X技术栈,提供了一种更适合云原生时代的 DevOps 方式。

        对Jenkins,的确当前已经成为开源CICD的标准,很多公司都使用Jenkins来实现应用发布,我也调研过Jenkins,尝试过去编写标准化应用的JenkinsFile,来尝试替换流水线工程和原子任务处理工程。但是在我看来,Jenkins的功能的确太强大了,可以装各种插件来满足各种需求,而分析我们的应用CICD过程,相对比较简单,如果基于Jenkins为底座,进行CICD的上层开发,那还要投入精力去维护Jenkins,但是往往只使用了它一小部分的功能,另外对于非标准的应用其实也可以编写自己的JenkinsFile来定制自己的CICD,但是语法也并不是通用的语言。

另外在看CNCF的Landscape,我关注到了其中的两个开源项目:TektonArgo Workflow

  • Tekton

Welcome to Tekton | Tektonhttps://tekton.dev/docs/

  • Argo Workflow

Argo Workflows | Argohttps://argoproj.github.io/workflows/

        这两个项目之所以吸引我的一点就是 当底层的环境从云服务器迁移到k8s集群后,应用以工作负载的方式运行在node上,同时支持HPA水平自动伸缩,而对于CICD中的每个原子任务,也可以以POD的形式运行在Node上,任务完成后销毁,这正是Tekton和ArgoCD的一个特点。相对于原先发布系统原子任务处理工程以云服务器的方式水平伸缩,这种方式更加灵活,更加节约资源。举个最直观的例子,当凌晨的时间点,相对发布任务比较少,云服务器的方式,资源的利用率就很低,但是服务器还是运行着,如果是以POD的方式,资源的消耗会更小。

为什么选择了Tekton

        对于我最看重的一点,资源消耗的减少,Tekton和Argo Workflow都是以POD的方式运行,从初步分析来说,Argo 更胜一筹,原因有以下两点:

  • Argo是CNCF孵化项目,而Tekton是从Knative中剥离出来的项目,部署的时候使用的镜像仓库都是在谷歌gcr中,国内被墙了,部署起来就需要稍微繁琐一下,而Argo就不需要。
  • Argo有很多子项目,如果使用了Argo workflow来进行整个CI过程,可以更好的和Argo CD进行结合,在我看来,Argo CD+GitOps这一套还是可以的。

但是为什么最终我选择了Tekton,原因就是Tekton的流程粒度更细。

           当你初步了解了Tekton,就会知道他的运行结构就是每次都运行一个PipelineRun。

           对于一个Pipeline是由Task组成的,每个Task都会申请一个POD来运行对应的任务。

          但是最重要的一点是对于每个Task,里面可以配置多个Step,每个Step都是一个POD中的一个容器,可以控制每个任务的步骤,在Argo workflow里面也可以通过ContainSet来实现,但是在我使用过程中,支持得不够好(这次调研是在今年年初做的,那个时候,我看了Argo workflow的文档,没有和Step一样的概念),就因为这点,我选择了Tekton

         就以上这点,我也举个例子,对于应用CI中的构建和镜像制作,我选择放在一个Task中的两个Step,在完成构建过程后,再执行镜像制作这个Step,选择Tekton就会更加清爽。

        以上是我个人的感受和分析,也希望大家可以各抒己见,可以私信我讨论。

CICD + Tekton

        基于以上的分析,我开始尝试设计和开发基于Tekton的CICD平台

        改造流程

                以下的流程细节就不讲了,毕竟每个公司的分支策略,应用构建方式和规范不一样,只大致讲下整体流程

          Tekton Pipeline构建

分析原先的流水线流程,以最基本的Java项目的CI为例,最基本的流程如下:

  • 代码合并(有的公司合代码的操作是人为操作的,这步可以忽略)
  • 代码构建

          如果是Maven项目,那最基本的都是mvn package

  • 镜像构建

          基于构建得到的产出,来进行镜像的制作

         直观来看,可以讲以上三个步骤转换成三个Task,然后在对应的容器中,执行对应的Shell脚本便可以完成。而我的处理方式是将代码构建和镜像构建放在一个Task中分为两个Step,原因就是我不想再引入COS和CFS,如果分为两个Task,就需要考虑构建物的传递,因为Task是以单独的POD形式运行的,如果在一个Task中的两个Step运行,那么构建物的传递就会简单很多。因此流水线的构建因人而异。

        完成整个流水线的装配,之后可以在tekton的dashboard中创建一个PipelineRun运行下,观察下结果是否满足要求。

        上层平台的开发

        原先CICD平台采用的是后端Java+Python,前端React

        新的平台我采用的Go + Vue (选择go是因为go更适合云原生相关的开发,顺便前端用Vue再写一把,支持下国产)

        下面就讲下整体结合Tekton串联的流程:

        

接下来对流程图进行简要说明:

  • 当发起CICD时,首先需要根据应用的类型匹配到对应的Pipeline(引入Tekton后的一个好吃就是相对以前,我们虽然支持了标准应用的发布,但是对于非标准应用的发布,都是开发人为上机器进行操作发布,如果需要CICD平台支持,则需要开发对应的代码,并不是很灵活,而现在只需要去为这个应用制作对应的Pipeline)
  • 最后将所有的PipelineRun信息存档,删除对应的CRD,毕竟这些都是存在ETCD中,日常发布量大,数据多。
  • 对于如何获取PipelineRun的结果,我采用的方式是在Pipeline的finally中添加一个callback的Task,将需要获取的结果回调到平台中。
  • 对于实时展示,方式有很多种,前端的Interval进行调用获取,或者可以使用SSE的方式
  • 可以通过Tekton的Clientset来创建对应的PipelineRun

        由于整体的UI以及交互没有大的改动,因此前后端的开发大致花了我一周的时候就完成了。

        但是以上只是完成了CI的部分,对于CD的部分,我们原先的方式一直是以自研的方式来实现相应策略的部署,因此这里没有进行改动。

对比

        完成整体开发以后,与原先的架构对比,优势如下:

  • 资源的节约

        关于原子任务处理工程侧的资源节约是显而易见的,同时在流水线装配工程这一侧,Tekton在不安装dashboard的场景下,也只有controller和webhook,其他PipelineRun和TaskRun以CRD的方式运行,结束后销毁,所占资源较小。

  • 对非标准应用的支持

        这一点在上面提到了,就不讲了

下一步计划

        在完成初步改造之后,后续还有以下几点可以再进行优化:

  • 对项目工程进行下一步改造,Clientset的方式改成informer的方式获取CRD资源的信息
  • 对于不同构建任务的调度策略
  • 节点的构建缓存
  • 观察不同时期的任务执行速度,例如在集群资源紧张时,运行Task的Pod pending的时间,是否需要固定几个运行构建任务的节点。

总结

  • 对于底层基础技术的升级,往往会对平台提供新的改造思路,来实现系统的优化,例如像原先使用的activity的工作流平台,在云原生化改造后,也可以得到系统的优化。
  • 对于选择Tekton的这个策略,让我意识到有的时候并不是功能越强大就是越好,最合适的才是最好的。
  • 现在慢慢的第一语言从Java转变到Go,语言之间虽然是融会贯通,但是还是存在一些思想上的差异。例如在平台创建的Tekton的PipelineRun,我的这么多年Java开发经验告诉我,去找找有没有对应的Tekton Api的依赖引进来,接口方法调用下,因为之前有看到过Java的Fabric8io里封装了tekton的接口,后来看了tekton cli的源码才恍然大悟,在项目的Go mod文件里引了整个pipeline的项目,然后利用Clientset来创建Crd
  • 开发人员还是得有自己工作场景的脚手架,这样开发的效率就会提高不少。

        文章篇幅问题,关于Tekton的使用,项目细节的开发,以后有机会还会再写文章分享,也可以私信我相互探讨下

        我最后决定从这篇文章开始,以后都用一句话来结尾:

大隐隐于市!

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值