二丫讲梵 二丫讲梵
首页
  • 最佳实践
  • 迎刃而解
  • Nginx
  • Php
  • Zabbix
  • AWS
  • Prometheus
  • Grafana
  • CentOS
  • Systemd
  • Docker
  • Rancher
  • Ansible
  • Ldap
  • Gitlab
  • GitHub
  • Etcd
  • Consul
  • RabbitMQ
  • Kafka
  • MySql
  • MongoDB
  • OpenVPN
  • KVM
  • VMware
  • Other
  • ELK
  • K8S
  • LLM
  • Nexus
  • Jenkins
  • 随写编年
  • 家人物语
  • 追忆青春
  • 父亲的朋友圈
  • 电影音乐
  • 效率工具
  • 博客相关
  • Shell
  • 前端实践
  • Vue学习笔记
  • Golang学习笔记
  • Golang编程技巧
  • 学习周刊
  • Obsidian插件周刊
关于
友链
  • 本站索引

    • 分类
    • 标签
    • 归档
  • 本站页面

    • 导航
    • 打赏
  • 我的工具

    • 备忘录清单 (opens new window)
    • json2go (opens new window)
    • gopher (opens new window)
    • 微信MD编辑 (opens new window)
    • 国内镜像 (opens new window)
    • 出口IP查询 (opens new window)
    • 代码高亮工具 (opens new window)
  • 外站页面

    • 开往 (opens new window)
    • ldapdoc (opens new window)
    • HowToStartOpenSource (opens new window)
    • vdoing-template (opens new window)
GitHub (opens new window)

二丫讲梵

行者常至,为者常成
首页
  • 最佳实践
  • 迎刃而解
  • Nginx
  • Php
  • Zabbix
  • AWS
  • Prometheus
  • Grafana
  • CentOS
  • Systemd
  • Docker
  • Rancher
  • Ansible
  • Ldap
  • Gitlab
  • GitHub
  • Etcd
  • Consul
  • RabbitMQ
  • Kafka
  • MySql
  • MongoDB
  • OpenVPN
  • KVM
  • VMware
  • Other
  • ELK
  • K8S
  • LLM
  • Nexus
  • Jenkins
  • 随写编年
  • 家人物语
  • 追忆青春
  • 父亲的朋友圈
  • 电影音乐
  • 效率工具
  • 博客相关
  • Shell
  • 前端实践
  • Vue学习笔记
  • Golang学习笔记
  • Golang编程技巧
  • 学习周刊
  • Obsidian插件周刊
关于
友链
  • 本站索引

    • 分类
    • 标签
    • 归档
  • 本站页面

    • 导航
    • 打赏
  • 我的工具

    • 备忘录清单 (opens new window)
    • json2go (opens new window)
    • gopher (opens new window)
    • 微信MD编辑 (opens new window)
    • 国内镜像 (opens new window)
    • 出口IP查询 (opens new window)
    • 代码高亮工具 (opens new window)
  • 外站页面

    • 开往 (opens new window)
    • ldapdoc (opens new window)
    • HowToStartOpenSource (opens new window)
    • vdoing-template (opens new window)
GitHub (opens new window)
  • Nexus系列文章

  • Jenkins系列文章

    • Jenkins入门系列笔记汇总整理
    • 前言与介绍
    • Jenkins初始部署与简单配置
    • Jenkins各配置选项介绍
    • Jenkins中一个项目的构建
    • Jenkins配置项目构建的钉钉通知
    • Jenkins忘记管理员密码怎么办
    • Jenkins与gitlab的交互探微
    • Jenkins根目录详解
    • Jenkins插件之显示构建时间
    • Jenkins插件之批量修改配置
    • Jenkins配置简单构建邮件推送
    • Jenkins复杂邮件推送配置详解
    • Jenkins配置复杂构建邮件推送
    • Jenkins构建安卓项目之前的一些唠叨
    • Jenkins构建安卓项目配置
    • Jenkins与Gitlab分支的交互
    • Jenkins构建nodejs项目
    • 使用docker部署Jenkins及初始配置
    • 配置gitlab提交代码Jenkins自动构建
    • Jenkins回滚方案探微
    • Jenkins角色控制(小黄锁)探微
    • Jenkins构建的应用配置问题解决探微
    • Jenkins构建中tag的应用
    • Jenkins插件之Ansicolor(神器)
    • 最基础核心的Jenkins功能部署一个java应用
    • Jenkins+sonar构建代码扫描
    • Jenkins+docker+gitlab将应用部署到docker
    • Jenkins参数化构建犀利插件Active-Choices-Plugin
    • 记一次将代码中参数外显到构建历史中的操作
    • Jenkins升级与迁移的经验分享
    • pipeline笔记之从一个简单的项目构建开始
      • 1,前言少叙。
      • 2,从一个简单的项目开始。
      • 3,准备工作。
        • 1,主机分布
        • 2,安装软件
        • 3,创建项目
        • 4,秘钥安排
      • 4,配置项目。
        • 1,简单配置。
        • 2,手动构建。
      • 5,配置讲解。
    • Jenkinsfile声明式语法详解
    • 自动构建的原始配置以及pipeline中的用法
    • 多分支构建的实践与思考
    • 使用Jenkinsfile类前端项目的部署与回滚
    • 如何在Jenkinsfile中定义一个全局的时间戳变量
    • Jenkins中自由风格回滚方案的最佳实践
    • Jenkins中pipeline风格回滚方案的最佳实践
    • pipeline结合ansible剧本进行批量的部署与回滚配置
    • 最近配置安卓iOS打包本地化流程中一些值得记录的内容
    • pipeline中如何在environment环节声明一个含有通配符的变量
    • git-Parameter插件在pipeline共享库中的实践详解
    • jenkins作为ci检测代码是否合并的实践
    • 将Jenkins共享库的Jenkinsfile放到ci静态检测的实践
    • Jenkins的pipeline实践之GitSCM参数配置项详解
    • Jenkins中pipeline对接CMDB接口获取主机列表的发布实践
    • Jenkins有任务无法kill提示即将关闭
    • Jenkins基于Share Library共享库的最佳实践探索
    • Jenkins结合MySql Database插件的平台化实践思路
    • Jenkins-Groovy中三元表达式的用法
    • Jenkins-Groovy中Switch的高阶用法
    • Jenkins-pipeline之利用activity choice插件对接查询MySQL数据实现动态参数化的功能
    • CentOS通过yum快速安装Jenkins
    • Jenkins-pipeline语法之错误处理详解(文末有干货)
    • Jenkins常用插件汇总以及简单介绍
    • Jenkins所遇报错汇总及解决
    • Jenkins管理维护运维规范
  • ELK笔记

  • Kubernetes笔记

  • LLM专题

  • 系列专题
  • Jenkins系列文章
二丫讲梵
2019-09-15
目录

pipeline笔记之从一个简单的项目构建开始

文章发布较早,内容可能过时,阅读注意甄别。

# 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,安装软件

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

  • Jenkins 安装配置。 (opens new window)
  • Gitlab 安装配置。 (opens new window)

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

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

# 3,创建项目

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

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

里边只有一个 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即可。
    
    1
    2
  • Jenkins 与应用主机。

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

# 4,配置项目。

# 1,简单配置。

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

img

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

img

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

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

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

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

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

接着是 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 失败了"
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

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

# 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

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

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

如此以来,一个简单的项目就配置好了,这种将配置 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 失败了"
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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 来表示,这样,一个简单好用的流水线就完成了,在完成基础功能构建之后,再去深入各个参数,进行比较花哨的配置应用。

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

微信 支付宝
#jenkins#pipeline
上次更新: 2024/07/04, 22:40:37
Jenkins升级与迁移的经验分享
Jenkinsfile声明式语法详解

← Jenkins升级与迁移的经验分享 Jenkinsfile声明式语法详解→

最近更新
01
睡着的人不关灯
06-12
02
学习周刊-总第215期-2025年第24周
06-12
03
学习周刊-总第214期-2025年第23周
06-05
更多文章>
Theme by Vdoing | Copyright © 2017-2025 | 点击查看十年之约 | 浙ICP备18057030号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式