-
1. 安装渠成
- 1.1 快速安装
- 2. 渠成介绍
-
3. 安装应用
- 3.1 安装应用
- 4. 平台使用
- 5. 命令行工具
-
6. 解决方案
-
6.1. 服务对接
- 6.1.1 生成 Gitlab 访问令牌
- 6.1.2 创建 Gitlab 操作用户
- 6.1.3 生成 Gitea 访问令牌
- 6.1.4 创建 Gitea 操作用户
- 6.1.5 对接 Sonarqube 服务
- 6.1.6 对接 Jenkins 服务
-
6.1. 服务对接
- 7. 问题排查
Jenkinsfile的用法
- 2023-04-19 12:24:56
- 祁世垚
- 2474
- 最后编辑:祁世垚 于 2023-04-19 12:24:56
- 分享链接
agent
选择 kubernetes 类型
传统 | docker | kubernetes | |
---|---|---|---|
隔离性 | 弱 | 强 | 强 |
可扩展性 | 弱 | 强 | 强 |
软件管理 | 主机安装包 | Dockerfile | Dockerfile |
复合构建 | 强 | 弱 | 强 |
编写复杂度 | 低 | 低 | 高 |
运作方式
- 传统 agent,是在主机上执行所有命令
- docker agent,是启动了一个容器,使用容器里可用的命令
- kubernetes agent,是启动了一组容器,分别在不同的容器里执行对应的命令
快速开始
pipeline {
agent {
kubernetes {
}
}
stages {
stage("Hello") {
steps {
sh 'ls -l'
sh 'pwd'
}
}
}
}
默认生成了一个只包含 jnlp(jenkins agent) 容器的 Pod
jnlp 会自动下载代码到工作区,ls 命令看到的将是代码仓库根目录下的文件
编译代码
示例中代码语言为 golang,显然 jnlp 只有 java 的 runtime 环境,没法构建 golang 代码。
所以需要加入一个 golang 容器来执行编译。
pipeline {
agent {
kubernetes {
containerTemplate {
name 'golang'
image 'hub.qucheng.com/ci/golang:1.18-alpine'
command 'sleep'
args '99d'
}
}
}
stages {
stage("Hello") {
steps {
container('golang') {
sh 'go build -o demo main.go'
}
sh 'ls -l'
sh 'pwd'
}
}
}
}
这次生成的 pod 里,多了一个名为golang 的容器,
在执行过程中,先切换到了 golang 容器中,执行了构建命令,生成一个名为 demo 的二进制文件。
随后切换到默认的 jnlp 容器,执行 ls 命令,可以看到刚生成的 demo 二进制文件,
这是因为一个 Pod 里所有容器,通过挂载的方式共享了工作区目录,在所有容器下看到的文件内容都是一样的。
复合构建
传统 agent 可以在一台主机上安装 nodejs、php、golang等工具包,在 Jenkinsfile 里调用不同的命令即可完成复合构建。
docker agent 只能生成一个容器,这个容器可能只提供一种开发语言的构建环境,很难提供复合构建。
而 kubernetes agent 可以组合多个容器,相对于传统 agent,要在 Jenkinsfile 里不断切换容器并执行命令来完成复合构建。
模版继承
如果在 Jenkinsfile 里描述所有容器的定义,整个文件会显得冗长,并且当发布了新版本的镜像,必须提交代码更改Jenkinsfile内容,才能生效。
一般都会在 Jenkins 服务端增加模版,来定义容器的参数,用户只要在 Jenkinsfile 里引用这些模版即可。
pipeline {
agent {
kubernetes {
inheritFrom "build-go"
}
}
stages {
stage("Hello") {
steps {
container('golang') {
sh 'go build -o demo main.go'
}
sh 'ls -l'
sh 'pwd'
}
}
}
}
可以引用多个模版;
Jenkins服务端添加模版时,也可以继承其它模版。
kubernetes agent 的详细介绍见 https://plugins.jenkins.io/kubernetes/
阶段与步骤
stages
在描述步骤时,必须以 stages 起头,逐一描述单个 stage,比如
pipeline {
agent {
kubernetes {
}
}
stages {
stage("A") {
steps {
echo "A"
}
}
stage("B") {
steps {
echo "B"
}
}
}
}
每个 stage 顺序执行,要执行的指令比如`echo` `sh` 等都要包在 steps 里。
stage 里可以再定义 stages,进一步拆分。
并行
默认的 stage 都是顺序执行的,当我们需要并行执行时,可以通过 parallel 来描述,该字段只能放在 stage 上下文中。
pipeline {
agent {
kubernetes {
}
}
stages {
stage("A") {
parallel {
stage("A-1") {
steps {
echo "A-1"
}
}
stage("A-2") {
steps {
echo "A-2"
}
}
stage("A-3") {
steps {
echo "A-3"
}
}
}
}
stage("B") {
steps {
echo "B"
}
}
}
}
并行节点
并行任务,可以在一个容器里同时执行多条命令,或是分开在多个容器里执行,
也可以再创建出多个 agent,在新的 agent 上执行指令。
pipeline {
agent {
kubernetes {
}
}
stages {
stage("A") {
parallel {
stage("A-1") {
agent {
kubernetes {}
}
steps {
sh 'java -version'
}
}
stage("A-2") {
agent {
kubernetes {
containerTemplate {
name 'golang'
image 'hub.qucheng.com/ci/golang:1.18-alpine'
command 'sleep'
args '99d'
}
}
}
steps {
container('golang') {
sh 'go version'
}
}
}
stage("A-3") {
steps {
echo "A-3"
}
}
}
}
stage("B") {
steps {
echo "B"
}
}
}
}
动态并行
parallel 需要定义每一个 stage,如果每个 stage 里都比较复杂,而我们需要定义很多个 stage,不仅难以阅读,并且之后的维护变更也是个问题
所以官方提供了 matrix 来应对重复性 stage 的定义,只需要定义一个 stage,jenkins 将自动生成对应数量的 stage.
pipeline {
agent {
kubernetes {
}
}
stages {
stage("Test") {
matrix {
axes {
axis {
name "SEQUENCE"
values "1", "2", "3", "4", "5"
}
}
stages {
stage("Test") {
steps {
sh 'echo sh ./autotest.sh $SEQUENCE'
}
}
}
}
}
stage("Build") {
steps {
echo "Build"
}
}
}
}
这样将并行执行 5 个命令, 关键是 axis 里的定义
更进一步的做法,可以增加一条轴,两条轴排列组合,得到10个结果,定义好 agent,将派生出 10个 agent,并行执行。
pipeline {
agent {
kubernetes {
}
}
stages {
stage("Test") {
matrix {
agent {
kubernetes {}
}
axes {
axis {
name "BUSSINESS"
values "order", "user"
}
axis {
name "SEQUENCE"
values "1", "2", "3", "4", "5"
}
}
stages {
stage("Test") {
steps {
sh 'hostname'
sh 'echo sh ./autotest.sh $BUSSINESS $SEQUENCE'
}
}
}
}
}
stage("Build") {
steps {
echo "Build"
}
}
}
}
得到的10个结果里,有时候并不是都可以使用的,可以用 excludes 排除具体的组合
pipeline {
agent {
kubernetes {
}
}
stages {
stage("Test") {
matrix {
agent {
kubernetes {}
}
axes {
axis {
name "BUSSINESS"
values "order", "user"
}
axis {
name "SEQUENCE"
values "1", "2", "3", "4", "5"
}
}
excludes {
exclude {
axis {
name 'BUSSINESS'
values 'user'
}
axis {
name 'SEQUENCE'
values '5'
}
}
// exclude {}
}
stages {
stage("Test") {
steps {
sh 'hostname'
sh 'echo sh ./autotest.sh $BUSSINESS $SEQUENCE'
}
}
}
}
}
stage("Build") {
steps {
echo "Build"
}
}
}
}
更多介绍,可以查看官方文档 https://www.jenkins.io/doc/book/pipeline/syntax/#declarative-matrix
环境变量
设置环境变量
共有三种设置方法
- 确定的字符串
- 从 jenkins 凭据里获取
- 将 shell 命令的输出作为内容
示例如下
environment {
ARTIFACTORY_SERVER = "https://abc.org"
ARTIFACTORY_TOKEN = credentials('artifactory-access-token')
ARTIFACT_VERSION = """${sh(
returnStdout: true,
script: 'echo ${BRANCH_NAME}-$(date +%Y%m%d)'
).trim()}"""
}
第二条,是读取存储在 jenkins 服务器的凭据内容。
第三条,是执行shell命令动态生成,其中 trim() 函数是把 shell 命令输出的回车换行字符去掉。
读取环境变量
sh 'echo $ARTIFACT_VERSION'
echo "${env.ARTIFACT_VERSION}"
在派生的shell命令行下读取,和在 jenkinsfile 指令中读取环境变量,注意两者的区别
环境变量的生效范围
在当前stage 以及派生的 stage 里生效,如果在 pipeline 级设置了环境变量,就等于全局生效
低一层的 stage 里,如果定义了同名的环境变量,将会覆盖。
pipeline {
agent {
kubernetes {
}
}
environment {
ARTIFACTORY_SERVER = "https://abc.org"
ARTIFACT_VERSION = """${sh( returnStdout: true, script: 'echo ${BRANCH_NAME}-$(date +%Y%m%d)' ).trim()}"""
}
stages {
stage("A") {
parallel {
stage("A-1") {
agent {
kubernetes {}
}
steps {
sh 'java -version'
echo "${env.ARTIFACTORY_SERVER}" // output: https://abc.org
sh 'echo ${ARTIFACTORY_SERVER}' // output: https://abc.org
}
}
stage("A-2") {
agent {
kubernetes {
containerTemplate {
name 'golang'
image 'hub.qucheng.com/ci/golang:1.18-alpine'
command 'sleep'
args '99d'
}
}
}
environment {
ARTIFACTORY_SERVER = "http://test.org"
}
steps {
container('golang') {
sh 'go version'
echo "${env.ARTIFACTORY_SERVER}" // output: https://test.org
}
}
}
stage("A-3") {
steps {
echo "A-3"
}
}
}
}
stage("B") {
steps {
echo "B"
echo "${env.ARTIFACT_VERSION}"
}
}
}
}
触发条件
when 关键字,可以放在某个 stage 里,决定该 stage 是否会触发
判断条件可以是:
- 匹配某个分支
- tag 触发
- pull request 触发
- 环境变量或参数的值匹配
以及其它更多条件,也可以把这些条件以 与或 的关系组合
详见 https://www.jenkins.io/doc/book/pipeline/syntax/#when
语法生成器
查官方文档找用法是学习时的最佳路径,但实际编写时,可以用 jenkins 内置的语法生成器来辅助生成代码片段。
比如上述的触发条件,以及jenkins 内置的各种函数,以及插件提供的函数。
用户可以点击任意 job,在左侧导航条找到 `流水线语法`,在那里选择条件,生成片段。如图示例
回放
在调试流水线时,不必每次对 Jenkinsfile 产生变更都提交到代码仓库,
可以先提交一个最简单的,确保能成功执行的到仓库,触发构建后,可以点击回放,输入调试的内容来进行验证