1

Jenkins-pipeline学习笔记–从一个简单的项目构建开始(一) |坐而言不如起而行! 二丫讲...

 2 years ago
source link: http://www.eryajf.net/3292.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
本文预计阅读时间 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,安装软件

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

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

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

3,创建项目

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

  1. 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之后会一直认证不过去,就是因为没有初始认证的缘故:

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

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

4,配置项目。

1,简单配置。

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

71cfeb93ly1gmavv5moc5j217e0rsjwu.jpg

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

71cfeb93ly1gmavv9k2e9j21gg13waf5.jpg

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

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

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

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

  1. $ ls
  2. Jenkinsfile readme.md
  3. $ cat readme.md
  4. Jenkins pipeline test。

接着是 Jenkinsfile的内容:

  1. pipeline {
  2. agent any
  3. environment {
  4. git_url = "[email protected]:jenkins-learn/hello-world.git"
  5. remote_ip = "192.168.3.66"
  6. remote_dir = "/opt/hello"
  7. }
  8. options {
  9. buildDiscarder(logRotator(numToKeepStr: '10'))
  10. disableConcurrentBuilds()
  11. timeout(time: 10, unit: 'MINUTES')
  12. timestamps()
  13. }
  14. stages {
  15. stage('rsync') {
  16. steps {
  17. echo 'rsync'
  18. sh '''
  19. rsync -avz --progress -e 'ssh -p 22' --exclude='Jenkinsfile' --exclude='.git' --delete ${WORKSPACE}/ root@$remote_ip:$remote_dir
  20. '''
  21. }
  22. }
  23. stage('delete') {
  24. steps {
  25. echo '清理工作目录'
  26. cleanWs()
  27. }
  28. }
  29. }
  30. post {
  31. success {
  32. sh "echo 成功了"
  33. }
  34. failure {
  35. sh "echo 失败了"
  36. }
  37. }
  38. }

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

2,手动构建。

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

构建日志内容如下:

  1. Started by GitLab push by 李启龙
  2. Obtained Jenkinsfile from git [email protected]:jenkins-learn/hello-world.git
  3. Running in Durability level: MAX_SURVIVABILITY
  4. [Pipeline] Start of Pipeline
  5. [Pipeline] node
  6. Running on Jenkins in /root/.jenkins/workspace/hello-world
  7. [Pipeline] {
  8. [Pipeline] stage
  9. [Pipeline] { (Declarative: Checkout SCM)
  10. [Pipeline] checkout
  11. No credentials specified
  12. Cloning the remote Git repository
  13. Cloning repository [email protected]:jenkins-learn/hello-world.git
  14. > git init /root/.jenkins/workspace/hello-world # timeout=10
  15. Fetching upstream changes from [email protected]:jenkins-learn/hello-world.git
  16. > git --version # timeout=10
  17. > git fetch --tags --progress [email protected]:jenkins-learn/hello-world.git +refs/heads/*:refs/remotes/origin/*
  18. > git config remote.origin.url [email protected]:jenkins-learn/hello-world.git # timeout=10
  19. > git config --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/* # timeout=10
  20. > git config remote.origin.url [email protected]:jenkins-learn/hello-world.git # timeout=10
  21. Fetching upstream changes from [email protected]:jenkins-learn/hello-world.git
  22. > git fetch --tags --progress [email protected]:jenkins-learn/hello-world.git +refs/heads/*:refs/remotes/origin/*
  23. > git rev-parse remotes/origin/master^{commit} # timeout=10
  24. > git branch -a -v --no-abbrev --contains 1b884f34ab93fe97de3fb5d8311c2249257a9b89 # timeout=10
  25. Checking out Revision 1b884f34ab93fe97de3fb5d8311c2249257a9b89 (origin/master)
  26. > git config core.sparsecheckout # timeout=10
  27. > git checkout -f 1b884f34ab93fe97de3fb5d8311c2249257a9b89
  28. Commit message: "jenkins"
  29. > git rev-list --no-walk a50c119cd98c57bd022c64a0da70a7b55e81714a # timeout=10
  30. [Pipeline] }
  31. [Pipeline] // stage
  32. [Pipeline] withEnv
  33. [Pipeline] {
  34. [Pipeline] withEnv
  35. [Pipeline] {
  36. [Pipeline] timeout
  37. Timeout set to expire in 10 分
  38. [Pipeline] {
  39. [Pipeline] timestamps
  40. [Pipeline] {
  41. [Pipeline] stage
  42. [Pipeline] { (rsync)
  43. [Pipeline] echo
  44. 18:03:06 rsync
  45. [Pipeline] sh
  46. 18:03:07 + rsync -avz --progress -e 'ssh -p 22' --exclude=Jenkinsfile --exclude=.git --delete /root/.jenkins/workspace/hello-world/ [email protected]:/opt/hello
  47. 18:03:07 sending incremental file list
  48. 18:03:07 ./
  49. 18:03:07 README.md
  50. 18:03:07
  51. 24 100% 0.00kB/s 0:00:00
  52. 24 100% 0.00kB/s 0:00:00 (xfr#1, to-chk=0/2)
  53. 18:03:07
  54. 18:03:07 sent 164 bytes received 44 bytes 416.00 bytes/sec
  55. 18:03:07 total size is 24 speedup is 0.12
  56. [Pipeline] }
  57. [Pipeline] // stage
  58. [Pipeline] stage
  59. [Pipeline] { (delete)
  60. [Pipeline] echo
  61. 18:03:07 清理工作目录
  62. [Pipeline] cleanWs
  63. 18:03:07 [WS-CLEANUP] Deleting project workspace...
  64. 18:03:07 [WS-CLEANUP] Deferred wipeout is used...
  65. 18:03:07 [WS-CLEANUP] done
  66. [Pipeline] }
  67. [Pipeline] // stage
  68. [Pipeline] stage
  69. [Pipeline] { (Declarative: Post Actions)
  70. [Pipeline] sh
  71. 18:03:08 + echo 成功了
  72. 18:03:08 成功了
  73. [Pipeline] }
  74. [Pipeline] // stage
  75. [Pipeline] }
  76. [Pipeline] // timestamps
  77. [Pipeline] }
  78. [Pipeline] // timeout
  79. [Pipeline] }
  80. [Pipeline] // withEnv
  81. [Pipeline] }
  82. [Pipeline] // withEnv
  83. [Pipeline] }
  84. [Pipeline] // node
  85. [Pipeline] End of Pipeline
  86. Finished: SUCCESS

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

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

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

5,配置讲解。

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

再次将文件内容拉过来:

  1. pipeline {
  2. agent any
  3. environment {
  4. git_url = "[email protected]:jenkins-learn/hello-world.git"
  5. remote_ip = "192.168.3.66"
  6. remote_dir = "/opt/hello"
  7. }
  8. options {
  9. // 表示保留10次构建历史
  10. buildDiscarder(logRotator(numToKeepStr: '10'))
  11. // 不允许同时执行流水线,被用来防止同时访问共享资源等
  12. disableConcurrentBuilds()
  13. // 设置流水线运行的超时时间, 在此之后,Jenkins将中止流水线
  14. timeout(time: 10, unit: 'MINUTES')
  15. // 输出构建的时间信息
  16. timestamps()
  17. }
  18. stages {
  19. stage('rsync') {
  20. steps {
  21. echo 'rsync'
  22. sh '''
  23. rsync -avz --progress -e 'ssh -p 22' --exclude='Jenkinsfile' --exclude='.git' --delete ${WORKSPACE}/ root@$remote_ip:$remote_dir
  24. '''
  25. }
  26. }
  27. stage('delete') {
  28. steps {
  29. echo '清理工作目录'
  30. cleanWs()
  31. }
  32. }
  33. }
  34. post {
  35. success {
  36. sh "echo 成功了"
  37. }
  38. failure {
  39. sh "echo 失败了"
  40. }
  41. }
  42. }
  • 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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK