Tools-Jenkins-pipeline

jenkins使用pipeline

脚本名词解释

pipeline <必须> Pipeline是CD管道的用户定义模型。Pipeline的代码定义了您的整个构建过程,通常包括构建应用程序,测试和交付应用程序的阶段。
agent <必须> 定义pipeline的执行环境,必须存在
stages<阶段> 包含多个子阶段stage(‘子阶段名’)

jenkins 的工作空间目录 /var/jenkins_home/workspace/

node vs agent 区别

agent是声明性的pipelines,node是脚本性的pipelines

实践

pipeline使用gradle

学习到如何使用工具,和配置工具全局变量

  1. 配置工具系统管理->全局工具配置->Gradle->Gradle 安装

    name:gradle4.8

    • 自动安装

    版本 Gradle 4.8

    Apply->Save即可

    注释:如果没有Gradle设置,先去安装Gradle插件,默认推荐设置是安装了的

  2. 编写Jenkinsfile进行测试

    1
    2
    3
    4
    5
    6
    7
    8
    #!/usr/bin/env groovy Jenkinsfile
    node {
    def gradleHome = tool 'gradle4.8' //这里的gradle4.8要和gradle工具的配置里的name要一致
    env.PATH = "${gradleHome}/bin:${env.PATH}"
    stage('build') {
    sh 'gradle -v'
    }
    }

pipeline使用gradle打包java spring boot

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env groovy Jenkinsfile
node {
def gradleHome = tool 'gradle4.8' //这里的gradle4.8要和gradle工具的配置里的name要一致
env.PATH = "${gradleHome}/bin:${env.PATH}"
stage('gradle build') {
if (isUnix()) {
//sh './gradlew clean :eurekaserver:build' //这里会自动下载项目里的gradle版本(4.7)
sh 'gradle clean :eurekaserver:build' //使用jenkns安装的gradle工具(4.8)
} else {
// bat 'gradlew.bat clean :eurekaserver:build'
bat 'gradle clean :eurekaserver:build'
}
}
}

打包jar为镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/env groovy Jenkinsfile
node {
def gradleHome = tool 'gradle4.8' //这里的gradle4.8要和gradle工具的配置里的name要一致
env.PATH = "${gradleHome}/bin:${env.PATH}"
stage('gradle build') {
if (isUnix()) {
//sh './gradlew clean :eurekaserver:build' //这里会自动下载项目里的gradle版本(4.7)
sh 'gradle clean :eurekaserver:build' //使用jenkns安装的gradle工具(4.8)
} else {
// bat 'gradlew.bat clean :eurekaserver:build'
bat 'gradle clean :eurekaserver:build'
}
}
stage('docker build image'){
dir('eurekaserver'){ //dockerfile的跟目录
docker.build("springcould/eurekaserver:${env.BUILD_NUMBER}")
}
}
}

运行镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env groovy Jenkinsfile
node {
def gradleHome = tool 'gradle4.8' //这里的gradle4.8要和gradle工具的配置里的name要一致
env.PATH = "${gradleHome}/bin:${env.PATH}"
stage('gradle build') {
if (isUnix()) {
sh 'gradle clean :eurekaserver:build' //使用jenkns安装的gradle工具(4.8)
} else {
bat 'gradle clean :eurekaserver:build'
}
}
stage('docker build image'){
dir('eurekaserver'){ //dockerfile的跟目录
docker.build("springcould/eurekaserver:${env.BUILD_NUMBER}")
}
}
stage('docker run Application'){
sh "docker run -p 8091:8091 springcould/eurekaserver:${env.BUILD_NUMBER}"
}
}

pipeline 环境变量选择设置

**严重注意**这个需要第二次运行才会生效,第一次设置之后运行,不会出来,第二次拉去运行才会出来
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env groovy Jenkinsfile
pipeline {
agent any
parameters {
choice(name: 'door_choice',
choices: 'one\ntwo\nthree\nfour',
description: 'What door do you choose?')
}
stages {
stage('build') {
steps {
echo "${params.door_choice}"
}
}
}
}

pipeline agent版gradle脚本

not support tool "gradle4.8"单个设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env groovy Jenkinsfile
pipeline {
agent any
parameters {
choice(name: 'door_choice',
choices: 'one\ntwo\nthree\nfour',
description: 'What door do you choose?')
}
stages {
stage('build') {
tools{
gradle "gradle4.8"
}
steps {
echo "${params.door_choice}"
sh 'gradle -v'
}
}
}
}

申明式使用脚本式语言script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/env groovy Jenkinsfile

pipeline {
agent any
parameters {
choice(name: 'project_choice',
choices: 'eurekaserver\neurekaclient\neurekafeign\neurekazuul',
description: '你要编译构建那个项目?')
}
stages {
stage('docker build'){
steps{
dir("${params.project_choice}"){
sh "pwd"
script { //需要用script包裹,就能使用脚本式语言
docker.build("my-image:${env.BUILD_ID}")
}
}
}
}
}
}

环境变量

env.BUILD_ID 当前的编译id,和Jenkins versions 1.597+ 的env.BUILD_NUMBER一样

env.JOB_NAME 当前项目名

env.JENKINS_URL only available if Jenkins URL set in “System Configuration”

git diff HEAD^ eurekaserver/ 和上个版本比较eurekaserver目录,可以不要

常见问题

  1. 提示如下错误

    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
    > git --version # timeout=10
    > git --version # 'git version 1.8.3.1'
    using GIT_ASKPASS to set credentials
    > git ls-remote http://gitlab.admin.exxk.com.cn/exxk/exxk-server.git # timeout=10
    > git rev-parse --resolve-git-dir /var/jenkins_home/caches/git-d065127b6d5e88dbce5baaa6da0dd31a/.git # timeout=10
    Setting origin to http://gitlab.admin.exxk.com.cn/exxk/exxk-server.git
    > git config remote.origin.url http://gitlab.admin.exxk.com.cn/exxk/exxk-server.git # timeout=10
    Fetching & pruning origin...
    Listing remote references...
    > git config --get remote.origin.url # timeout=10
    > git --version # timeout=10
    > git --version # 'git version 1.8.3.1'
    using GIT_ASKPASS to set credentials
    > git ls-remote -h http://gitlab.admin.exxk.com.cn/exxk/exxk-server.git # timeout=10
    Fetching upstream changes from origin
    > git config --get remote.origin.url # timeout=10
    using GIT_ASKPASS to set credentials
    > git fetch --tags --progress --prune origin +refs/heads/*:refs/remotes/origin/* # timeout=10
    ERROR: [星期三 六月 29 07:55:33 UTC 2022] Could not fetch branches from source
    [星期三 六月 29 07:55:33 UTC 2022] Finished branch indexing. Indexing took 0.5 秒
    FATAL: Failed to recompute children of prd-exxk6xljd » prd-exxk-server
    hudson.plugins.git.GitException: Command "git fetch --tags --progress --prune origin +refs/heads/*:refs/remotes/origin/*" returned status code 1:
    stdout:
    stderr: error: there are still refs under 'refs/remotes/origin/release'
    From http://gitlab.admin.exxk.com.cn/exxk/exxk-server
    ! [new branch] release -> origin/release (unable to update local ref)

    at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.launchCommandIn(CliGitAPIImpl.java:2671)
    at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.launchCommandWithCredentials(CliGitAPIImpl.java:2096)
    at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.access$500(CliGitAPIImpl.java:84)
    at org.jenkinsci.plugins.gitclient.CliGitAPIImpl$1.execute(CliGitAPIImpl.java:618)
    at jenkins.plugins.git.AbstractGitSCMSource$8.run(AbstractGitSCMSource.java:602)
    at jenkins.plugins.git.AbstractGitSCMSource$8.run(AbstractGitSCMSource.java:588)
    at jenkins.plugins.git.AbstractGitSCMSource.doRetrieve(AbstractGitSCMSource.java:394)
    at jenkins.plugins.git.AbstractGitSCMSource.doRetrieve(AbstractGitSCMSource.java:350)
    at jenkins.plugins.git.AbstractGitSCMSource.retrieve(AbstractGitSCMSource.java:588)
    at jenkins.scm.api.SCMSource._retrieve(SCMSource.java:373)
    at jenkins.scm.api.SCMSource.fetch(SCMSource.java:283)
    at jenkins.branch.MultiBranchProject.computeChildren(MultiBranchProject.java:641)
    at com.cloudbees.hudson.plugins.folder.computed.ComputedFolder.updateChildren(ComputedFolder.java:278)
    at com.cloudbees.hudson.plugins.folder.computed.FolderComputation.run(FolderComputation.java:166)
    at jenkins.branch.MultiBranchProject$BranchIndexing.run(MultiBranchProject.java:1032)
    at hudson.model.ResourceController.execute(ResourceController.java:101)
    at hudson.model.Executor.run(Executor.java:442)
    Finished: FAILURE

    分析:关键错误error: there are still refs under 'refs/remotes/origin/release' From http://gitlab.admin.exxk.com.cn/exxk/exxk-server ! [new branch] release -> origin/release (unable to update local ref)这句表示本地已经有release分支了,服务器的release删了,然后又重新建了,导致不一样,解决清空本地分支,执行git remote prune origin删除旧的分支和冲突分支,但是这是在jenkins里面删除难度较大,因此采用删除git在jenkins里面的缓存,因此需要找到分支的缓存,可以在日志git rev-parse --resolve-git-dir /var/jenkins_home/caches/git-d065127b6d5e88dbce5baaa6da0dd31a/.git这一行发现缓存的目录

    解决:登录jenkins容器,进入cd /var/jenkins_home/caches/然后删除或重命名git-d065127b6d5e88dbce5baaa6da0dd31agit-d065127b6d5e88dbce5baaa6da0dd31a@tmp即可

    总结:kubesphere的devops流程是,先在jenkins容器里面扫描git里面的jenkins部署脚本,然后缓存,然后启动新的容器根据jekins部署脚本拉取代码,运行编译过程。

  2. 流水线卡在‘Jenkins’ doesn’t have label ‘maven’这个提示

    分析:检查jekins输出了一个info信息Maximum number of concurrently running agent pods (100) reached for Kubernetes Cloud kubernetes, not provisioning: 100 running or pending in namespace kubesphere-devops-system with Kubernetes labels {jenkins=slave}这句话意思是agent pods 已经有100个在运行或pending等待中,然后执行kubectl get pod -A发行maven和nodejs的代理镜像加起来刚刚100个,都处于error状态。

    解决:执行kubectl delete pod maven-xxx -n kubesphere-devops-system进行删除错误的pod。

    总结:注意每个日志,不是错误警告日志,也要注意重复多次的提示信息。

  3. 在2基础上分析为什么有100个error的pod,执行kubectl logs maven-0n5wf -n kubesphere-devops-system提示如下错误

    1
    error: a container name must be specified for pod maven-0n5wf, choose one of: [jnlp maven]

    在执行kubectl logs maven-0n5wf -n kubesphere-devops-system -c jnlp提示如下错误

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
       ```



    4. [ks-jenkins:2.249.1](registry.cn-beijing.aliyuncs.com/kubesphereio/ks-jenkins:2.249.1)启动出现异常,找不到原因时,快速删除缓存重建配置可以解决大多数问题。执行

    ````bash
    #命令详解:ls列举所有文件然后通过管道grep ,-v代表反转,-E代表正则,多个匹配,去掉-v可以检查正则是否正确
    #该命令是删除除了jobs、secret.key、secret.key.not-so-secret、secrets、userContent、users、workspace之外的所有文件
    rm -rf `ls | grep -vE "^jobs$|^secret.key$|^secret.key.not-so-secret$|^secrets$|^userContent$|^users$|^workspace$"`

    rm -rf `ls | grep -vE "^jobs$|^secret.key$|^secret.key.not-so-secret$|^secrets$|^userContent$|^users$|^workspace$|^plugins$"`
    ````

    5. 升级[jenkins镜像](registry.cn-beijing.aliyuncs.com/kubesphereio/ks-jenkins:2.249.1)为`jenkins/jenkins:2.354-centos7-jdk8`,然后清理挂载目录(按第4个问题的命令清理),出现如下错误

    ```bash
    2022-08-25 06:29:48.180+0000 [id=10] WARNING h.i.i.InstallUncaughtExceptionHandler#handleException: Caught unhandled exception with ID 077a9ea8-f2e2-4590-a73a-477279c34ccb

    hudson.security.AccessDeniedException3: anonymous is missing the Overall/Read permission

    at hudson.security.ACL.checkPermission(ACL.java:80)

    解决:

参考

https://github.com/arun-gupta/docker-jenkins-pipeline