• 我居然用一周时间开发完了基于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的使用,项目细节的开发,以后有机会还会再写文章分享,也可以私信我相互探讨下

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

    大隐隐于市!

  • 相关阅读:
    【Codecs系列】x265编码器(十一):快速运动估计搜索方法
    2022年最新宁夏建筑施工物料提升(建筑特种作业)模拟题库及答案
    Java 并发 - ThreadLocal详解
    PAT甲级:1055 The World‘s Richest |Python
    TypeScript核心篇——类(class)-可选参数-存取器-构造函数-静态属性方法-抽象类
    【Vue2.x源码系列05】异步更新及nextTick原理
    NVIDIA Jetson之ONNX的正确安装方法
    基于Tensorflow、Keras实现Stable Diffusion
    kubeflow核心功能
    阿里云服务器方升架构、自研硬件、AliFlash技术创新
  • 原文地址:https://blog.csdn.net/qq_20614905/article/details/125489337