从零开始部署企业智能硬件CI环境Jenkins篇(二)

Jenkins

开始之前

一般来说,成熟的大型公司通常具备一套完备的持续集成环境,从代码托管到部署上线都有相关的工程团队维护,用来配合各个业务团队的基础开发环境。但是通用的模型往往难以适配具有独特需求的业务。这个时候是提pr等待基础环境迭代,还是自己动手造轮子,往往根据业务方手头项目的进度安排来决定,并非取决于个人或者团队的能力。

笔者在加入目前这个团队时,恰好面临这个选择。公司已经提供了比较完善的项目管理环境,但细节方面仍需要打磨。而新的项目已经开始正式迭代开发,无法等待工程效率团队的迭代成果。

所以,笔者只能在尽可能利用公司环境的基础上,使用Jenkins替换其中的CI环境,使用Nginx服务替换其中的产物分派托管环境。
持续集成方案

基础环境配置

确定方案之后,则开始针对团队具体业务业务和团队开发环境进行有效配置,在此笔者仅列举若干关键功能配置,一些比较常见的业务在此不再赘述。

在本文的书写过程中,网络资料以及Jenkins的相关文档给了笔者大量的帮助,但由于所参考的原始资料部分已经散失来源,部分源码以及策略可能与原著者相同,如果在说明过程中有侵权的地方,还请指出,我好及时修改或做出说明

安全配置与人员管理

Jenkins默认的人员权限管理非常粗糙,仅能针对全局用户配置哪些域可以访问。
真实的业务场景中往往使用的是矩阵式项目管理,针对不同的人员与项目,往往有不同的配置和授权方案。

这个横向系统与原来的垂直领导系统就组成了一个矩阵,因此称矩阵管理。也就是说,矩阵管理中的员工是双线汇报的模式。其上司有两个,一个是流程上司,一个是专业上司。流程上司负责你的日常考核,专业上司负责你的晋升和任免。
在这里插入图片描述

因此,为了解决上述问题,需要引入Matrix Authorization Strategy 插件进行管理。关键技术点如下:

全局安全配置

全局安全配置注意,全局安全配置的授权策略要选中Role-Based Strategy,注意这个选项在选中后,一定不要更改,否则后续的配置会完全失效,只能靠备份工程恢复。

配置矩阵化权限

安装插件后,从系统管理进入相关设置
在这里插入图片描述

Manage Roles 配置

Manage Roles用于设置矩阵化项目的类型,首先将Job权限进行切分整体组策略。
Job权限切分切分完成之后,不同的整体组策略对应不同的Job可使用权限。
增加项目配置策略组策略之外,还可以针对不同的Job进行同样的权限配置。注意:

  1. 整体组策略的优先级要高于项目组策略。如果某人已经设置了高优的项目组策略,那么即使后续即使在项目组策略中做了限制,后者的限制会失效。
  2. 项目组策略提供了一种Pattern参数,用来通过正则描述相关的项目。这个正则关系中,用来表示*全字符匹配的方式,改为了.*,请务必注意,可以参考图中,我用来描述BigBee项目的正则关系。
Assign Roles 配置

组策略设置完成之后,可以开始配置人员设置。
在这里插入图片描述相关人员可以赋予全局的整体权限,与Manage Roles中配置的内容一致。
同时,还可以针对不同的项目归属,将不同的人员进行配置。
在这里插入图片描述这样完美解决了不同人员在不同项目中的人员项目矩阵管理。

简单备份工程

Jenkins 默认不包含任何存档保存工具,虽然后续我们可以通过保存docker镜像的方式来变相保存每个阶段的Jenkins 配置,但是在业务开展的早期,通过ThinBackUp的方式保存Jenkins 配置,仍然不失为一种及时备份的好方案。
在这里插入图片描述ThinBackUp的使用方法非常简单,其原理是将$JENKINS_HOME 内的整个文件进行打包存档,同时生成的本地xml文件可供restore时调用。
在这里插入图片描述以上是我的配置文件。

进阶邮箱配置

Jenkins的邮件功能非常简陋,既没办法自定义邮件内容,也没办法指定不同编译场景下的动作。只能以模板方式发送给指定用户。因此,大多数的Jenkins用户都会使用Email Extension Plugin这个插件来完善邮件的配置。
关于这个插件的使用,网上已经有了比较全面的介绍,这里不再赘述。仅将笔者常用模板贴出来:
在这里插入图片描述

简易均衡配置

所谓均衡,只是一种比较夸张说法,但 Throttle Concurrent Builds Plugin 这个插件提供了一个非常简单有效的功能——那就是限制同一个执行节点(Node)内同一个Job最大执行数,以及同一个Job的整体最大执行数。
前者可以有效的解决Job并发可能带来的类竞态问题,后者可以解决在缺少k8s编排环境下,对多个Job在多个Slaver机上的执行效率。
比如我的一个Job配置:
ThrottleConcurrentBuildsPlugin这个配置指的是,该Job可以最多同时并发5个流水,同时在一个Node里最多可以执行1个。比如说,我有4个Node,每个Node上包括两个executor。如果未安装该插件,那么我们同时并行执行3个A-Job的流水,以及2个B-Job的流水,结果应该是这样的。
在这里插入图片描述
而安装完插件,并做了相应的配置之后,执行结果应该是这样的:
在这里插入图片描述
在通常的业务配置中,一个Node通常对应为一个容器环境(注意,此Node与K8S中的Node并不一致),同时未来保证最大化的Slaver节点可用性,我们会将同一套业务编译环境部署在多个Node上。而这些编译资源,比如说源码环境,通常映射到了本地磁盘上。这样一来,如果一个Node里同时执行多个同样Job的流水,那么这些本地业务环境就会出现冲突。而将这些业务资源剥离成每个节点一个,可以完美避免上述问题。

变量影响范围

使用Jenkins的同学,多半绕不开参数化构建的坑。大多数情况下,我们会使用Jenkins环境变量,比如:
默认环境变量这种,如果要是自己设置参数,通过“参数化构建”选项也可以自定以自己的配置项,比如:
在这里插入图片描述需要注意的是,这些参数都是全局变量,也就是在这个Job任何地方都可以调用并生效。
如果你还想使用一些环境变量,但不希望这些变量以参数化的形式显示在Job中,你可以使用 EnvInject Plugin 带来的效果。
在这里插入图片描述在我的脚本中,除了参数化声明的若干变量,以及Jenkins默认的环境变量外,还包括一个ARCHIVE_PACKAGE_NAME变量,该变量同样可以在Job内全局引用。
在这里插入图片描述

注意,通过export方式去声明的参数是不可能在Job内全局引用的,因为Job内不同的环节有的已经跨了终端进程,同一个export只对该终端进程内的所有任务生效。

通过该方法,可以解决一些需要注入到Job内部的,但不希望被显示在参数化环境的全局变量问题。

如果更进一步,一些参数只出现在构建环节,根本无需声明为全局变量,但仍然希望它能够在一个Job内跨终端传递,有办法吗?
答案是有的,通过将参数保存至本地文件的方式,也可以实现类似的效果。
比如我将需要保存的部分参数,以键值对的方式写入本地文件中,注意save.txt文件并不会因为声明而自动创建,需要使用者自己手动创建
保存save.txt同时,Jenkins本地也要声明将从这个文件中读取键值对信息:
声明save.txt在其他的终端里,就可以调用以上声明的参数了。
在这里插入图片描述以上的环境变量,并不需要在全局变量中进行声明。

参数化构建联动参数

在参数化配置中,除了默认的参数类型外,还有一例比较常见的配置是联动参数。即当parmA=“a"时,parmB=”b”,当parmA="A"时,parmB=“B”,两者之间存在switch-case关系。
要实现类似的效果,需要使用插件是 Active Choices Plugin,该插件可以解决多个参数输入时的联动关系。
Active Choices Plugin在使用时,类似Choices插件的使用,都需要输入多个参数供业务侧选择。不同的是,在做选择时,可以添加reference作为判断参考,比如:
在这里插入图片描述在这里插入图片描述通过groove模块的配置,可以简单的实现这个switch-case关系。

多行参数输入与处理

必须要说明的是,不同于其他功能是通过Jenkins丰富的插件库来补充。Jenkins 默认的输入参数multi line input本身是一个糟糕的功能,它既没有办法为多行输入添加分隔符,也没办法把多行输入按正确排列传递给下一级流水。至少在我使用的Jenkins版本Jenkins ver. 2.121.3上,这个问题依然还存在。
所以听我的,如果能够避免使用这个功能,我建议你就不要用了,如果你一定要坚持使用,这里可以参考网络上所搜集到的一种间接解决方案。

增加分隔符

默认的multi-line-input方案会将多行输入整合为一行作为输入。比如说,我们输入的多行参数是这样:
在这里插入图片描述
首先要对多行内容增加分隔符:

import os
import io

with io.open("multi.txt", "w+", encoding="utf-8") as text_file:
    text_file.write("%s" % unicode(os.getenv("OPERATOR_PRAMS")))

在这里,我们将“OPERATOR_PRAMS”输入的多行参数增加“%s”后缀分隔符,并且保存到本地的multi.txt文件中,之所以这么处理,是因为保存到本地文件中才可以真正引用多行参数。
而读取的方式也很简单:

    if [[ -f $WORKSPACE/multi.txt ]];then
        ls -l $WORKSPACE/multi.txt
        echo "存在有效multi.txt,内容是:"
        cat $WORKSPACE/multi.txt
        while read line || [[ -n ${line} ]]
        do
            echo $line
            A=$(echo $line | awk 'BEGIN{FS=","} {print $1}')
            B=$(echo $line | awk 'BEGIN{FS=","} {print $2}')
            C=$(echo $line | awk 'BEGIN{FS=","} {print $3}')
            if [[ -z $(echo ${A} | grep -E "^[A-Z]{2}[0-9]{2}$") ]] ||  [[ -z $(echo ${A} | grep "${JENKINS_OPERATOR:0:2}") ]];then
                echo "注入版本错误,退出"
                break
            fi    
        done < $WORKSPACE/multi.txt
        rm $WORKSPACE/multi.txt
    fi
fi

在设计这个流程中存在以下两个需要注意的风险:

自动输入设计

注意上述的用例仍然是用户手动输入时填入的参数,如果需要将该multi-line-input参数作为Jenkins默认的输入选项,相关的配置内容则需要改为

OPERATOR_PRAMS=$"CM01,default,0\nCM01,beijing,1"
跨流水传递

跨流水传递multi-line-input参数时,分割符会作为非utf8字符处理,所以不会生效,比较简单的方法是将mult.txt文件传递到下游流水,然后再填补至下游的参数中。

下游流水触发方案

Jenkins支持远程hook启动,直接通过post请求体就能唤起一个携带参数的Job流水,因此将多级Jenkins流水定向触发成为了可能。而广播触发下级流水也可以通过扩展插件实现。

定向触发

将Jenkins Job视为post请求对象,即可以触发一次远程Job。

curl -u jenkins:jenkins -X "\
"POST ${JENKINS_URL}job/ProjectName/buildWithParameters"\
"\?T=${T}"\
"\&A=${A}"\
"\&B=${B}"\
"\&C=c"

这里需要注意的是,如果你的Jenkins做了权限设置,必须要用该Job授权的用户才能触发,而笔者所使用的jenkins:jenkins用户,会造成下游流水的cause触发者改为jenkins,这点一定要注意,会影响你流水显示的触发者名称,也会影响最终的报告邮件内容。

广播触发

如果不想指定某个具体Job作为触发对象,而想将多个满足的条件的Job同时触发,还可以使用 Parameterized Trigger Plugin 插件来实现这一功能。
在这里插入图片描述该插件中,可以再project to build一栏内填写多个下游Job名称,当Job走到构建后操作时,会在满足trigger when build is时触发这些Job,同时携带Parameters内的键值对参数。这样一次执行就可以触发多个业务流水。

产物的远程保存

Jenkins本身是具备产物保存的能力的,但是过于简单。如果希望将产物保存至其他的平台,比如nginx或者FTP上,则需要一些额外操作。
通常网络上介绍的方法是使用插件 Publish Over SSH Plugin 所提供的打包功能。
在这里插入图片描述
这里需要注意的一点是,Transfers模块内的command实际上是执行在远端ssh server上的,这个ssh server的配置需要先在jenkins config中进行设置。
如果不希望使用这个脚本,也可以通过scp 自己实现一个,两者的含义是一致的。

其他

Jenkins不愧是目前最热门的CI工具,无论从易用性还是文档的完备性而言都是相当出色。
在项目的迭代过程中,以上的这些基础环境配置并非一蹴而就,大部分情形都是出现了问题,然后搜索到了解决办法。通过日复一日的迭代逐渐完善了整体的功能。
关于CI部分的基础功能介绍就到此为止,接下来我将从具体业务环境来说明流水和Job的设计,以及后续我对于整个DevOps环境的规划方案。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值