• 对于注定会优秀的人来说,他所需要的,只是时间----博主
  • 手懒得,必受贫穷,手勤的,必得富足----《圣经》
  • 帮助别人,成就自己。愿君在本站能真正有所收获!
  • 如果你在本站中发现任何问题,欢迎留言指正!
  • 宝剑锋从磨砺出,梅花香自苦寒来!
  • 本站开启了防爆破关小黑屋机制,如果您是正常登录但被关进小黑屋,请联系站长解除!

<三十一>Jenkins-pipeline学习笔记–从一个简单的项目构建开始(一)

Jenkins eryajf 3个月前 (09-15) 583°C 已收录 0个评论
本文预计阅读时间 23 分钟

系列汇总

这是一个系列文章,大大小小到今天惊然发现竟然已经累计二十篇了,也就不得不做一个小汇总。回想当初写第一篇文章的时候,就已经决心事无巨细,一应认真的走下来,回头遮望,看着皇皇这么多文章,一股强烈的成就感就此油然而生,于是便有了这些汇总整理。在这个过程当中,好像也帮助过不少的人,这是让我尤其开心的事情,同时也结识了一些志同道合的朋友,再没有比这更让人觉得愉悦的事情啦!也希望以后写出更多类似的系列文章。

文章汇总地址如右:Jenkins入门教程。

如果相中哪个,点击进去便是。希望正在读这段话的你能够在这个小系列中获得自信以及喜悦!

1,前言少叙。

Jenkins pipeline是很早就出来了的功能,也是很早就了解了的功能,我也曾不止一次打算学一学这个被不少人推荐过的新方式,也听说过一些公司,将几千个项目,全部基于Jenkinsfile进行高效便捷的管理,心有向往,之所以始终没有彻底入门,一方面是因为公司现有所有项目都是基于传统的自由风格或者maven风格的构建方式,自己比较熟悉也比较得心应手了,一下子换方式有点难以出发,另一方面就是,实在没有遇到过多么好的教程,基本上每次出发都是从入门到放弃的过程,甚为难受,网上的教程,要么是太简单,只介绍了一星半点的,这类文章最没价值,空误时间,要么是太详细,一下子把Jenkinsfile语法的所有功能点都讲到了,却从来不曾简单系统地介绍过一个项目,使人迷失在繁多的功能点里,却没有丁点收获。

这次,当我干脆跳出原有的一切窠臼,以一种全新的视角来看Jenkins pipeline时,反而有了不少的收获,加之又购买了《Jenkins 2.0 实践指南》一书,给原有积累的大脑,带来不少新的启迪与发散,于是,打算从自己的角度,来记录一下Jenkins pipeline。

想到自己学习这个知识点一路来走过的弯路,就对网上繁杂的文章感到愤慨,为了能给后来人导引一个比较明确且清晰的路线,我今天特别由浅入深,循序渐进,用个几篇文章,把这里边的门道儿说明清楚。

2,从一个简单的项目开始。

有不少的文章仅仅是将官方文档里边的一些介绍搬运了一下,不知道作者本人是否理解,是否学精通了,反正我个人在官方文档里边,也是积累了许多经验值之后,才能够看懂每个知识点的意义。

所以这里不用那种方式介绍,而是先配置一个简单的项目,用到了什么,再对对应的知识点进行讲解。

日常工作中的持续集成,最简单的,莫过于一些前端项目,只需要将开发的代码同步到远程主机定义好的目录即可,因此这里就创建一个简单的文件,模拟这种发布情景,暂不纠结复杂的编译之类的事情,先从简单的构建开始,以学习语法规范为要。

3,准备工作。

1,主机分布

主机 软件 IP 版本
CentOS 7.3.1611 (Core) Gitlab 192.168.3.65 12.2.5
CentOS 7.3.1611 (Core) Jenkins 192.168.3.66 2.194

2,安装软件

安装软件的工作,这里就不再赘述了,可参考如下文章进行配置。

另外两台主机都需要安装如下基础软件:

yum -y install git rsync ntpdate && ntpdate -u cn.pool.ntp.org

3,创建项目

为后边实验顺利,这里先在gitlab创建一个测试项目,项目地址如下:

http://192.168.3.65/jenkins-learn/hello-world

里边只有一个readme文件,用于验证简单发布的一些结果。

4,秘钥安排

同样是为了后边实验顺利,这里提前将各处需要安排的秘钥,给安排妥当。

  • Jenkins与gitlab。

    可能每个人以及每个公司在使用Jenkins的时候,与gitlab交互的时候,采用的方式都是不一样的,事实上再多也无非以下三种而已。

    • 1,通过Jenkins主机秘钥方式,也就是将Jenkins主机公钥放到gitlab应用中,这种最方便,推荐。

    • 2,通过用户名密码,在Jenkins处添加用户名密码,如果用户对项目有权限,则可以使用。

    • 3,通过gitlab里边的deploy key进行授权。

    我这里就采用了第一种方案,在Jenkins创建密钥对,然后将公钥放到管理员账号的配置里边。认证完成之后,在Jenkins主机,拉取一下刚刚项目的代码,做一下简单的连通性工作,否则后边在添加了代码URL之后会一直认证不过去,就是因为没有初始认证的缘故:

    [root@jenkins  ~]$git clone git@192.168.3.65:jenkins-learn/hello-world.git
    
    # 此处要求有一个认证,输入yes即可。
    
  • Jenkins与应用主机。

    这个就比较简单了,这里Jenkins分别给两台机器都传了公钥,后续的实验,也就在这种状况下进行。

4,配置项目。

1,简单配置。

现在直接去Jenkins里边,创建一个pipeline风格的项目:

进入项目的配置,直接在最下边的流水线处,按如下内容配置:

将项目仓库地址填入,然后脚本路径一般写成默认的Jenkinsfile,就这么简单的配置,就可以了,直接点击保存即可。

注意:因为前边已经做过Jenkins的公钥放置到gitlab里边的操作,因此这里不需要配置任何认证,就不会再报错。

现在需要准备编写Jenkinsfile了,事实上在日常流程中,这个文件应该是准备好了之后,再来创建项目的,只不过这里为了便于理解整个流程,特别把顺序做了调整。

现在来到项目的根目录中:

$ ls
Jenkinsfile readme.md

$ cat readme.md
Jenkins pipeline test。

接着是 Jenkinsfile的内容:

pipeline {
    agent any
    environment {
        git_url     = "git@192.168.3.65:jenkins-learn/hello-world.git"
        remote_ip   = "192.168.3.66"
        remote_dir  = "/opt/hello"
    }
    options {
        buildDiscarder(logRotator(numToKeepStr: '10'))
        disableConcurrentBuilds()
        timeout(time: 10, unit: 'MINUTES')
        timestamps()
    }
    stages {
        stage('rsync') {
            steps {
                echo 'rsync'
                sh '''
                    rsync -avz --progress -e 'ssh -p 22' --exclude='Jenkinsfile' --exclude='.git' --delete ${WORKSPACE}/  root@$remote_ip:$remote_dir
                '''
            }
        }
        stage('delete') {
            steps {
                echo '清理工作目录'
                cleanWs()
            }
        }
    }
    post {
        success {
            sh "echo 成功了"
        }
        failure {
            sh "echo 失败了"
        }
    }
}

如上的参数内容暂时先不讲解,暂时去做一下构建,看看效果。

2,手动构建。

暂时先手动点击一下构建按钮,看看效果。

构建日志内容如下:

Started by GitLab push by 李启龙
Obtained Jenkinsfile from git git@192.168.3.65:jenkins-learn/hello-world.git
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /root/.jenkins/workspace/hello-world
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Declarative: Checkout SCM)
[Pipeline] checkout
No credentials specified
Cloning the remote Git repository
Cloning repository git@192.168.3.65:jenkins-learn/hello-world.git
 > git init /root/.jenkins/workspace/hello-world # timeout=10
Fetching upstream changes from git@192.168.3.65:jenkins-learn/hello-world.git
 > git --version # timeout=10
 > git fetch --tags --progress git@192.168.3.65:jenkins-learn/hello-world.git +refs/heads/*:refs/remotes/origin/*
 > git config remote.origin.url git@192.168.3.65:jenkins-learn/hello-world.git # timeout=10
 > git config --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/* # timeout=10
 > git config remote.origin.url git@192.168.3.65:jenkins-learn/hello-world.git # timeout=10
Fetching upstream changes from git@192.168.3.65:jenkins-learn/hello-world.git
 > git fetch --tags --progress git@192.168.3.65:jenkins-learn/hello-world.git +refs/heads/*:refs/remotes/origin/*
 > git rev-parse remotes/origin/master^{commit} # timeout=10
 > git branch -a -v --no-abbrev --contains 1b884f34ab93fe97de3fb5d8311c2249257a9b89 # timeout=10
Checking out Revision 1b884f34ab93fe97de3fb5d8311c2249257a9b89 (origin/master)
 > git config core.sparsecheckout # timeout=10
 > git checkout -f 1b884f34ab93fe97de3fb5d8311c2249257a9b89
Commit message: "jenkins"
 > git rev-list --no-walk a50c119cd98c57bd022c64a0da70a7b55e81714a # timeout=10
[Pipeline] }
[Pipeline] // stage
[Pipeline] withEnv
[Pipeline] {
[Pipeline] withEnv
[Pipeline] {
[Pipeline] timeout
Timeout set to expire in 10 分
[Pipeline] {
[Pipeline] timestamps
[Pipeline] {
[Pipeline] stage
[Pipeline] { (rsync)
[Pipeline] echo
18:03:06  rsync
[Pipeline] sh
18:03:07  + rsync -avz --progress -e 'ssh -p 22' --exclude=Jenkinsfile --exclude=.git --delete /root/.jenkins/workspace/hello-world/ root@192.168.3.66:/opt/hello
18:03:07  sending incremental file list
18:03:07  ./
18:03:07  README.md
18:03:07  
             24 100%    0.00kB/s    0:00:00  
             24 100%    0.00kB/s    0:00:00 (xfr#1, to-chk=0/2)
18:03:07  
18:03:07  sent 164 bytes  received 44 bytes  416.00 bytes/sec
18:03:07  total size is 24  speedup is 0.12
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (delete)
[Pipeline] echo
18:03:07  清理工作目录
[Pipeline] cleanWs
18:03:07  [WS-CLEANUP] Deleting project workspace...
18:03:07  [WS-CLEANUP] Deferred wipeout is used...
18:03:07  [WS-CLEANUP] done
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Declarative: Post Actions)
[Pipeline] sh
18:03:08  + echo 成功了
18:03:08  成功了
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // timestamps
[Pipeline] }
[Pipeline] // timeout
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

刚刚的结果,其实是将代码同步到Jenkins本机了,那么去看一眼效果是否如我们所想:

[root@jenkins  ~]$cd /opt/hello/
[root@jenkins  hello]$ls
README.md
[root@jenkins  hello]$cat README.md
Jenkins pipeline test。

如此以来,一个简单的项目就配置好了,这种将配置code化的方式,不仅优雅,节约了大量的配置时间,而且提高了不少的效率。

5,配置讲解。

现在进入正式的配置语法讲解环节,基于当前所用的,进行讲解。

再次将文件内容拉过来:

pipeline {
    agent any
    environment {
        git_url     = "git@192.168.3.65:jenkins-learn/hello-world.git"
        remote_ip   = "192.168.3.66"
        remote_dir  = "/opt/hello"
    }
    options {
         // 表示保留10次构建历史
        buildDiscarder(logRotator(numToKeepStr: '10'))
        // 不允许同时执行流水线,被用来防止同时访问共享资源等
        disableConcurrentBuilds()
        // 设置流水线运行的超时时间, 在此之后,Jenkins将中止流水线
        timeout(time: 10, unit: 'MINUTES')
        // 输出构建的时间信息
        timestamps()
    }
    stages {
        stage('rsync') {
            steps {
                echo 'rsync'
                sh '''
                    rsync -avz --progress -e 'ssh -p 22' --exclude='Jenkinsfile' --exclude='.git' --delete ${WORKSPACE}/  root@$remote_ip:$remote_dir
                '''
            }
        }
        stage('delete') {
            steps {
                echo '清理工作目录'
                cleanWs()
            }
        }
    }
    post {
        success {
            sh "echo 成功了"
        }
        failure {
            sh "echo 失败了"
        }
    }
}
  • pipeline
    用于声明表示流水线的标识,表示这里将采用声明式的语法风格,与之对应的还要另外一种,叫做脚本式,这里不必纠结两个名词的意义,简单说明两种方式的意思就是:

    • 声明式:在Jenkinsfile固定的关键字之内,所采用的语法风格大多与shell类似,这种风格更加符合日常的阅读习惯,也更简单,以后我都将采用这种方式进行介绍以及深入。
    • 脚本式:并不是我们脑海中理解的shell script,而是一种基于Groovy语言的语法风格,对于并不熟悉开发的运维同学来说,这种方式学习成本以及普及性都有较大的局限,因此并不推荐这种方式。

    我想,在我一路学习的过程中,也遇到不少文章是基于脚本式的,这类使用者原有的身份大多是Java开发者,因此书写起这种代码仿佛更加得心应手一些,但是我以前的多次放弃,与碰上这种风格的Jenkinsfile不无关系。

  • anget
    此关键字用于表示当前流水线将要执行的位置,当我们的Jenkins是主从那种集群的时候,可以通过agent进行指定,同时也可以基于docker容器的构建,后边会详细介绍,这里的any表示任一客户端,因为当前Jenkins是单机的,因此就在当前主机执行。
  • environment
    用于设置环境变量,以便于代码复用的时候,更加清晰明了的简化工作内容,只要项目是类似的,那么直接在 environment区域进行配置即可,而无需穿梭到复杂的内容里更改配置。需要注意的一点是,变量的声明可以在pipeline以及stage区域当中,与大多数语言一样,不同的区域作用域也是不一样的。
  • options
    用来配置Jenkins应用自身的一些配置项,这个地方简单列举了几个,后边在详解参数配置的文章里边,会详细介绍。
  • stages
    此关键字用于表示流水线各个步骤的声明,其下一层级是stage,stages部分至少包含一个stage。
  • stage
    表示实际构建的阶段,每个阶段做不同的事情,可按如上方式定义阶段的名称。
  • steps
    标识阶段之中具体的构建步骤,至少包含一个步骤,在stage中有且只能有一个steps。
  • post
    用于定义在整个流水线执行结果的情况,通常可配合通知进行对项目构建状态的告知。

目前,这个项目所用到的语法,就是这些,一开始学习的时候,实在不必过于纠结每一个语法的原理或者深意,只需大致了解,然后专注于自己所想要的,只要完成自己所想的,就是最好的。

比如基于上边只有rsync单步骤情景,往Java项目上套,也是很简单的,只需要将日常构建的几个步骤,用一个一个stage来表示,这样,一个简单好用的流水线就完成了,在完成基础功能构建之后,再去深入各个参数,进行比较花哨的配置应用。

下一篇文章,就将详细介绍各个语法的规范以及用法,从而丰富我们的日常构建生活。


weinxin
扫码订阅本站,第一时间获得更新
微信扫描二维码,订阅我们网站的动态,另外不定时发送WordPress小技巧,你可以随时退订,欢迎订阅哦~

二丫讲梵 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明<三十一>Jenkins-pipeline学习笔记–从一个简单的项目构建开始(一)
喜欢 (2)
[如果想支持本站,可支付宝赞助]
分享 (0)
eryajf
关于作者:
学无止境,我愿意无止境学。书山有路,我愿意举身投火,淬炼成金!

您必须 登录 才能发表评论!