Jenkins学习之Pipeline流水线

发布于 2019-04-20  7 次阅读


前言

在前面的文章中我通过在jenkins UI界面手动配置job并结合多种parameter参数实现了单个Job多种模式(部署和回滚)的构建,不过前面也提到了这只是入门,在生产环境下,往往会有多种类型的项目,比如安卓项目、node.js、JAVA项目等等或者说一个构建包会在多个环境下运行比如: 测试、预发布、生产。我们会发现多个job之间大部分操作都是相同的,如果仅仅因为几个不同之处就配置多个job。不但麻烦而且不易于管理,于是jenkins在2.x版本提供了pipeline流水线的功能用于解决这些问题,并且随着jenkins不断升级,后期也出现了像BlueOcean这样的可视化pipeline管理工具,他能够更加直观的看到pipepine每一个阶段的情况以及处理所需要的时间,让pipeline更加简单方便。

背景

在日常开发中,我们经常会有发布需求,而且还会遇到各种环境,比如:线上环境(Online),模拟环境(Staging),开发环境(Dev)等。最简单的就是手动构建、上传服务器,但这种方式太过于繁琐,使用jenkins持续集成可以完美地解决这个问题, Jenkins构建也有很多种方式,现在使用比较多的是自由风格的软件项目(Jenkins构建的一种方式,会结合SCM(全称soft )和构建系统来构建你的项目,甚至可以构建软件以外的系统)的方式。针对单个项目的简单构建,这种方式已经足够了,但是针对多个类似且又存在差异的项目,就难以满足要求,否则就需要大量的job来支持,这就存在,一个小的变动,就需要修改很多个job的情况,难以维护。我们团队之前就存在这样的问题。

目前,我们团队主要负责开发和维护多个Android项目,而且每个项目都需要构建,每个构建流程非常类似但又存在一定的差异。比如构建的流程大概如下:

  • 克隆代码;
  • 静态代码检查(可选);
  • 单元测试(可选);
  • 编译打包APK或者热补丁;
  • APK分析,获取版本号(VersionCode),包的Hash值(apkhash)等;
  • 加固;
  • 上传测试分发平台;
  • 存档(可选);
  • 触发自动化测试(可选);
  • 通知负责人构建结果等。

整个流程大体上是相同的,但是又存在一些差异。比如有的构建可以没有单元测试,有的构建不用触发自动化测试,而且构建结果通知的负责人也不同。如果使用自由风格软件项目的普通构建,每个项目都要建立一个job来处理流程(可能会调用其他job)。

这种处理方式原本也是可以的,但是必须考虑到,可能会有新的流程接入(比如二次签名),构建流程也可能存在Bug等多种问题。无论哪种情况,一旦修改主构建流程,每个项目的job都需要修改和测试,就必然会浪费大量的时间。针对这种情况,我们使用了Pipeline的构建方式来解决。

当然,如果有项目集成了React Native,还需要构建JsBundle。在Native修改以后,JsBundle不一定会有更新,如果是构建Native的时候一起构建JsBundle,就会造成很多资源浪费。并且直接把JsBundle这类大文件放在Native的Git仓库里,也不是特别合适。

pipeline基本语法介绍

学习一种编程语言(groovy)最开始的步骤总是学习它的语法,知晓它的规则。但是对于pipeline来说,暂时还不需要深入去学习groovy,下面简单的为大家介绍下pipeline的一些主要的基本知识:

agent:该部分指定整个Pipeline或特定阶段将在Jenkins环境中执行的位置,具体取决于该agent 部分的放置位置。该部分必须在pipeline块内的顶层定义 ,也可以使用在stage级。

stage:表示这个Pipeline的某一个执行阶段(使用stage使得逻辑变得更加简单明了)

steps: 包含一个或者多个在stage块中执行的step序列(在这里执行操作:运行maven或者部署等等)

environment:指定键值对,可用于step中,主要是为常量或者变量赋值,根据所在的位置来决定其作用范围(类似于java中全局和局部的概念)

options:允许执行pipeline内置的专用选项,也可以使用由插件提供的

parameters:提供触发pipeline时的参数列表

trigger:定义了触发pipeline的方式(jenkins1.x中的pollscm定时构建)

tools:自动安装工具,注意这里使用的一定是在jenkins全局配置中已经定义好了的

when:可以用来执行一些代码逻辑

post:可以根据pipeline的状态来执行一些操作

以上是属于个人理解,具体以官方文档为准。下面再来详细说说里面比较重要的agent,其他的部分请大家自行google或者百度,相对来说比较简单。我的理解是:agent是一个机器总代理,它其中的参数都是为了指定一些可以使用的机器

agent的一些参数如下:

any : 在任何可用的机器上执行pipeline

none : 当在pipeline顶层使用none时,每个stage需要指定相应的agent,比方说:


pipeline{
    agent none   //没有指定agent
    stages{
        stage('checkout code'){
            steps{
                sh 'echo "checkout code"'
            }
        }
    }
}

以上代码会报下面这串错误,原因就是没有指定agent应用的节点:

 

label:在指定的机器上运行pipeline或者stage,比方说


agent{ label 'slave1'}  //指定slave1的节点机器运行该stage或者pipeline

这个设置的作用:在大规模集群中,CI机器往往是相同的配置,而此时你的项目又需要一些额外的配置,这个时候这个设置可以很好的完成这个功能

docker:定义这个参数后,指定pipeline或stage时会动态的接收一个指定节点的docker的镜像,并且还可以接受一个args的参数用于执行docker run 的参数。比方说你的项目要在A环境中做测试,在B环境中做预发验证,在C环境做灰度发布(这里只是简单的打个比方,实际中不是这样的,只是为了说明此时需要在不同的环境中做不同的事情),这个时候涉及到多个环境,常规做法可以是直接指定几个不同的slave的从节点,但是如果我此时想做测试并且只有一台机器,那我可以在这台机器上做几个docker镜像,分别用于不同的构建过程.比方说:


agent{
    docker{
        image 'mydocker'  //指定docker的镜像名称
        label 'slave1'    //指定在哪个机器上执行docker镜像
        args  '-v /tmp:/tmp' //运行时传入docker run的参数
    }
}

以上命令是在slave1的从节点机器上用mydocker的镜像生成一个容器,并传入-v /tmp:/tmp的参数


一个幽默,喜欢动漫,音乐,爱小动物,逐渐成为二次元肥宅的LINUX运维工程师,我会用心写博客,刚开始写的不太好。但是我会不断进步的!。就像我的博客下面写的。我宁愿做错,也不愿什么都不做 ps:好像是伊泽瑞尔说的,看来你游戏没少玩啊 23333333333333