1. 安装渠成
1.1 快速安装
2. 渠成介绍
2.1 产品简介
2.2 架构说明
2.3 主要特性
3. 安装应用
3.1 安装应用
4. 平台使用
4.1 账号管理
4.2 仪表盘
4.3. 应用市场
4.3.1 应用列表
4.3.2 应用安装
4.4. 服务管理
4.4.1 服务详情和服务操作
4.4.2 服务备份与回滚
4.5 服务导航
4.6 应用升级
4.7. 后台管理
4.7.1 平台升级
4.7.2 数据库管理
4.7.3 平台备份与恢复
4.7.4 LDAP服务
4.7.5 域名解析
4.7.6 域名管理
4.7.7 负载均衡
5. 命令行工具
5.1 安装与升级
5.2 版本升级文档
5.3 通过命令行升级平台
5.4 平台管理
5.5 应用管理
5.6 全局数据库管理
5.7 平台应用端口映射
5.8 其他功能
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 服务
7. 问题排查
7.1 问题反馈
7.2 安装问题

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 是否会触发

判断条件可以是:

  1. 匹配某个分支
  2. tag 触发
  3. pull request 触发
  4. 环境变量或参数的值匹配

以及其它更多条件,也可以把这些条件以 与或 的关系组合

详见 https://www.jenkins.io/doc/book/pipeline/syntax/#when

语法生成器

查官方文档找用法是学习时的最佳路径,但实际编写时,可以用 jenkins 内置的语法生成器来辅助生成代码片段。

比如上述的触发条件,以及jenkins 内置的各种函数,以及插件提供的函数。

用户可以点击任意 job,在左侧导航条找到 `流水线语法`,在那里选择条件,生成片段。如图示例 image

回放

在调试流水线时,不必每次对 Jenkinsfile 产生变更都提交到代码仓库,

可以先提交一个最简单的,确保能成功执行的到仓库,触发构建后,可以点击回放,输入调试的内容来进行验证

发表评论
评论通过审核后显示。