基于Jenkins的构建部署任务扩展设计

1个月前

一种DevOps构建及部署任务设计的思路及方法

转载本文需注明出处:微信公众号EAWorld,违者必究。


前言:



不同企业,不同系统,不同应用在开发中所使用的技术栈都不尽相同,因此构建所用的编译工具以及应用部署所使用的应用服务器也有所不同。如何扩展支持各种工具与应用服务器部署也成为了DevOps支撑企业持续集成与持续部署落地的关键组成部分。

本文从普元DevOps平台基于Jenkins pipeline构建及部署任务的扩展设计提供一种DevOps构建及部署任务设计的思路及方法。


目录:



1.为什么在设计时要考虑如何扩展?

2.我们做了哪些扩展方面的设计。

3.扩展设计后续。


1.为什么在设计时要考虑如何扩展?

在了解普元DevOps任务扩展设计之前,再重复说明一下普元DevOps平台持续集成及持续部署基于Jenkins pipeline的任务编排模式。



持续部署任务与持续集成任务基本一样,将类似应用服务器的部署(如websphere应用部署)封装成一个独立的任务,只是部署在pipeline stage的groovy脚本中添加了ansible-playbook的调用。在构建任务以及发布流水线中,用户可以根据自己的需求进行任务的编排。平台会将编排的好的任务提交给Jenkins引擎执行。



普元DevOps平台将提供的原子任务分为五类:代码,工具,构建,部署,测试。

代码:拉取代码,代码库打标签,代码库分支维护,代码库标签,代码库分支合并等。

工具:脚本执行,数据库检查,数据库脚本执行,介质仓库同步,文件生成等。

构建:Maven构建,Npm构建,Gradle构建,Ant构建,Docker镜像构建等。

部署:数据组件发布,Tomcat云主机部署,Springboot云主机部署,Weblogic应用部署,Websphere应用部署,EOS应用部署等。

测试:Checkmarx,SonarQube,JMeter,Robotframework,Findbugs等。

平台提供的五类原子任务合计已经超过70个,后续仍然会不断增加。

由此可知,若在设计之初不考虑原子任务的扩展创建,后续添加原子任务将是一件繁复的工作。

2.我们做了哪些扩展方面的设计

设计思路:

原子任务扩展的关键点无非三点:原子任务,任务的属性参数,任务的脚本实现。



我们使用sql添加原子任务以及原子任务的属性参数,后端提供原子任务以及任务属性查询接口,然后前端使用动态表单展示原子任务信息以及任务属性。用户编排任务后执行。平台会根据用户编排的任务流程组装配置整个jenkins任务的xml配置文件,然后提交给jenkins引擎生成对应的任务。

相关表设计:

任务模板表

表结构关键字段:



关键字段说明:

STAGE_HANDLER: 定义任务拦截器,可以对任务属性进行处理。

COMMON_STAGE_TPS: 任务公共属性模板,平台将一些任务属性定义为公共的模板供任务直接引用。

如在部署相关任务中都涉及介质信息相关属性,因此将介质信息定义为一个公共属性模板,在部署任务中通过该字段引用,这样就不需要在任务属性表中重复定义介质相关属性,后续对介质信息的相关字段扩展也会直接映射到所有关联了该模板的部署任务。



任务模板属性表

表结构关键字段:



关键字段说明:

CONTROL_TYPE: 属性的表单类型,有以下几种类型textbox,dict,combobox,checkbox editor,类型不同对应的前端展示的表单控件不同。

VALUE_PROVIDER: 当表单类型为特定类型时,此字段定义数据来源。比如当表单类型为combobox时,此参数可以配置为api接口相关访问信息,将接口返回值作为下拉选项和值。

Maven构建任务属性示例:



MAVEN版本:CONTROL_TYPE设置为dict,VALUE_PROVIDER值设置为{"type":"dictcombobox","dictTypeId":"DPS_CD_MAVEN_VERSION"},如果需要扩展额外的MAVEN版本支持,只需要在平台管理新增业务字典DPS_CD_MAVEN_VERSION的值即可。



JDK版本:同MAVEN版本一样,也是采用了业务字典项,方便扩展多版本支持。

settings文件:CONTROL_TYPE设置为editor,VALUE_PROVIDER值设置为{"type":"xml"},这样在编辑器中会根据xml类型做高亮显示。

执行Junit测试:CONTROL_TYPE设置为checkbox。

其他需要用户输入的字符串参数大多使用textbox类型。

此任务中没有使用到的CONTROL_TYPE为combobox的类型在之前提到的公共属性模板介质信息中的介质仓库属性有使用,使用该类型时将VALUE_PROVIDER定义为api访问的相关信息如下:



组件实例运维表

表结构关键字段:



关键字段说明:

COMPONENT_TYPE:组件类型,使用业务字典项DPS_PDM_COMPONENT_TYPE定义,通常将工程中最小可部署的单位定义成一个组件,如普元DevOps应用采用前后端分离的方式部署,这里定义3个组件,前端nginx-web组件,后端tomcat组件以及数据库mysql组件,在编排发布流水线时可以根据具体的部署任务关联对应的组件(如tomcat云主机部署任务关联DevOps后端的tomcat组件)。

OPERATE_NAME:运维操作,定义组件实例的运维操作。部分部署任务(如Tomcat云主机部署等)执行成功后会根据组件及主机资源等配置信息生成组件实例,组件实例的运维操作通过该字段定义。



相对于任务及任务属性的动态表单设计,脚本的设计就相对简单了。只需要将实现具体功能的脚本文件根据既定的规则命名及存放到指定的目录即可。

3.扩展设计后续

在线任务扩展

当前这种任务扩展方式仅仅只是给开发人员提供了便利,但是用户仍然很难扩展自己的任务,因此后续会考虑将任务扩展的能力做成平台功能的一部分提供给用户使用。



任务定义:创建一个任务,如maven构建任务,对应的任务类型为构建(build)。

属性定义:设计任务参数,如maven构建任务,构建依赖的jdk版本,构建所使用的pom文件路径等。同时配置参数对应的前端控件(如checkbox,select,password等),若使用select框则需要定义展示数据的来源,可以是api和业务字典等。

脚本编写:提供在线IDE的能力,用户可以实时维护并编辑自己的脚本,保存后即可完成加载。以供后续测试使用。

任务测试:可以配置任务的属性参数,选择对应的测试脚本。在执行测试前可以根据预知的正确结果定义校验步骤,如构建任务是不是生成了对应的文件,部署任务是不是启动了对应的端口,HTTP是否可以正常访问等。

任务发布:可以对测试通过的任务进行发布,也可以对已经发布的任务进行下线维护。

环境隔离

在普元DevOps平台中jenkins作为构建部署引擎提供服务,对用户来说是无感知的,用户不需要知道应用在何处编译,也不需要知道编译工具的路径,用户只需要配置任务执行即可。jenkins引擎会根据用户的配置生成对应的任务。

我们在使用DevOps平台过程中也碰到了一些问题。

1.应用构建依赖特定的环境编译。如IOS应用等。因此我们添加了构建及部署任务可以选择指定的jenkins引擎以及绑定到指定节点执行的能力。

2.扩展工具支持,扩展多版本支持不方便。因为任务是随机调度的,所有的jenkins节点都得包含编译所需的工具,因此所有的jennkins节点都得安装对应的工具及版本。

3.安全问题。因为jenkins引擎是各个项目公用,且包含脚本执行的能力,存在误操作或被恶意破坏的可能(Use Groovy Sandbox配置开启后功能基本无法正常使用)。



针对问题2和3,我们思考了两种解决方案,都是基于容器进行环境隔离。

方案1:每一个任务对应一个slave节点,slave节点进程运行在容器内部,根据任务自动创建,任务完成自动销毁。

优点:slave节点动态创建,动态销毁,节省资源。

缺点:slave节点使用的容器镜像,仍然需要包含任务所需的所有工具。会存在镜像过大的问题。

方案2:jenkins的管理节点和slave节点仍然运行在主机环境,只将任务具体stage中最终形成的执行命令使用容器运行,任务中执行命令的容器挂载同一个workspace空间。如stage git最终形成了一条命令git pull http://test.project.git。使用包含git工具的容器镜像运行这条命令将代码拉取到挂载的workspace中,stage maven生成的命令maven clean install则使用包含maven构建环境的容器镜像执行即可。

优点:扩展工具只需要扩展新的镜像即可,非常方便。

缺点:需要维护镜像与原子任务的关系。

写在最后

企业DevOps平台建设与落地不是一蹴而就的,DevOps平台本身亦是如此。只有在不断使用的过程中不断的优化演进,这样才能让DevOps平台愈发强大,以更好的支撑企业的IT建设。



关于作者:谷缜,现任普元高级研发工程师。曾参与神华灾备云平台项目,九江银行持续集成项目等,主要负责项目实施工作。开源技术爱好者,擅长云计算,容器,DevOps等相关领域技术。


关于EAWorld:微服务,DevOps,数据治理,移动架构原创技术分享。长按二维码关注!

COMMENTS

需要 后方可回复
如果没有账号可以 一个帐号。