说实话,Jenkins 真得很牛逼!只是大部分人不会用而已~(保姆级教程)(上)

简介: 说实话,Jenkins 真得很牛逼!只是大部分人不会用而已~(保姆级教程)(上)


什么是流水线

jenkins 有 2 种流水线分为声明式流水线脚本化流水线,脚本化流水线是 jenkins 旧版本使用的流水线脚本,新版本 Jenkins 推荐使用声明式流水线。文档只介绍声明流水线。

声明式流水线

在声明式流水线语法中,流水线过程定义在 Pipeline{}中,Pipeline 块定义了整个流水线中完成的所有工作,比如

参数说明:
  • agent any:在任何可用的代理上执行流水线或它的任何阶段,也就是执行流水线过程的位置,也可以指定到具体的节点
  • stage:定义流水线的执行过程(相当于一个阶段),比如下文所示的 Build、Test、Deploy, 但是这个名字是根据实际情况进行定义的,并非固定的名字
  • steps:执行某阶段具体的步骤。
//Jenkinsfile (Declarative Pipeline)
pipeline {
  agent any
    stages {
      stage('Build') {
        steps {
          echo 'Build'
        }
      }
      stage('Test') {
        steps {
          echo 'Test'
        }
      }
      stage('Deploy') {
        steps {
          echo 'Deploy'
      }
    }
  }
}
脚本化流水线

在脚本化流水线语法中,会有一个或多个 Node(节点)块在整个流水线中执行核心工作

参数说明:
  • node:在任何可用的代理上执行流水线或它的任何阶段,也可以指定到具体的节点
  • stage:和声明式的含义一致,定义流水线的阶段。Stage 块在脚本化流水线语法中是可选的,然而在脚本化流水线中实现 stage 块,可以清楚地在 Jenkins UI 界面中显示每个 stage 的任务子集。
//Jenkinsfile (Scripted Pipeline)
node {
  stage('Build') {
    echo 'Build'
  }
  stage('Test') {
    echo 'Test'
  }
  stage('Deploy') {
    echo 'Deploy'
  }
}

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

声明式流水线

声明式流水线必须包含在一个 Pipeline 块中,比如是一个 Pipeline 块的格式

pipeline {
  /* insert Declarative Pipeline here */
}

在声明式流水线中有效的基本语句和表达式遵循与 Groovy 的语法同样的规则,但有以下例外

  • 流水线顶层必须是一个 block,即 pipeline{}
  • 分隔符可以不需要分号,但是每条语句都必须在自己的行上
  • 块只能由 Sections、Directives、Steps 或 assignment statements 组成
  • 属性引用语句被当做是无参数的方法调用,比如 input 会被当做 input()。
Sections

声明式流水线中的 Sections 不是一个关键字或指令,而是包含一个或多个 Agent、Stages、 post、Directives 和 Steps 的代码区域块。

1.Agent

Agent 表示整个流水线或特定阶段中的步骤和命令执行的位置,该部分必须在 pipeline 块的顶层被定义,也可以在 stage 中再次定义,但是 stage 级别是可选的。

any

在任何可用的代理上执行流水线,配置语法

pipeline {
  agent any
}
none

表示该 Pipeline 脚本没有全局的 agent 配置。当顶层的 agent 配置为 none 时, 每个 stage 部分都需要包含它自己的 agent。配置语法

pipeline {
  agent none
  stages {
    stage('Stage For Build'){
      agent any
    }
  }
}
label

以节点标签形式选择某个具体的节点执行 Pipeline 命令,例如:agent { label 'my-defined-label' }。节点需要提前配置标签。

pipeline {
  agent none
    stages {
      stage('Stage For Build'){
        agent { label 'role-master' }
        steps {
          echo "role-master"
        }
      }
    }
}
node

和 label 配置类似,只不过是可以添加一些额外的配置,比如 customWorkspace(设置默认工作目录)

pipeline {
  agent none
    stages {
      stage('Stage For Build'){
        agent {
          node {
            label 'role-master'
            customWorkspace "/tmp/zhangzhuo/data"
          }
        }
        steps {
          sh "echo role-master > 1.txt"
        }
      }
    }
}
dockerfile

使用从源码中包含的 Dockerfile 所构建的容器执行流水线或 stage。此时对应的 agent 写法如下

agent {
   dockerfile {
     filename 'Dockerfile.build'  //dockerfile文件名称
     dir 'build'                  //执行构建镜像的工作目录
     label 'role-master'          //执行的node节点,标签选择
     additionalBuildArgs '--build-arg version=1.0.2' //构建参数
   }
}
docker

相当于 dockerfile,可以直接使用 docker 字段指定外部镜像即可,可以省去构建的时间。比如使用 maven 镜像进行打包,同时可以指定 args

agent{
  docker{
    image '192.168.10.15/kubernetes/alpine:latest'   //镜像地址
    label 'role-master' //执行的节点,标签选择
    args '-v /tmp:/tmp'      //启动镜像的参数
  }
}
kubernetes

需要部署 kubernetes 相关的插件,官方文档:

https://github.com/jenkinsci/kubernetes-plugin/

Jenkins 也支持使用 Kubernetes 创建 Slave,也就是常说的动态 Slave。配置示例如下

  • cloud: Configure Clouds 的名称,指定到其中一个 k8s
  • slaveConnectTimeout: 连接超时时间
  • yaml: pod 定义文件,jnlp 容器的配置必须有配置无需改变,其余 containerd 根据自己情况指定
  • workspaceVolume:持久化 jenkins 的工作目录。

  • persistentVolumeClaimWorkspaceVolume:挂载已有 pvc。
workspaceVolume persistentVolumeClaimWorkspaceVolume(claimName: "jenkins-agent", mountPath: "/", readOnly: "false")
  • nfsWorkspaceVolume:挂载 nfs 服务器目录
workspaceVolume nfsWorkspaceVolume(serverAddress: "192.168.10.254", serverPath: "/nfs", readOnly: "false")
  • dynamicPVC:动态申请 pvc,任务执行结束后删除
workspaceVolume dynamicPVC(storageClassName: "nfs-client", requestsSize: "1Gi", accessModes: "ReadWriteMany")
  • emptyDirWorkspaceVolume:临时目录,任务执行结束后会随着 pod 删除被删除,主要功能多个任务 container 共享 jenkins 工作目录。
workspaceVolume emptyDirWorkspaceVolume()
  • hostPathWorkspaceVolume:挂载 node 节点本机目录,注意挂载本机目录注意权限问题,可以先创建设置 777 权限,否则默认 kubelet 创建的目录权限为 755 默认其他用户没有写权限,执行流水线会报错。
workspaceVolume hostPathWorkspaceVolume(hostPath: "/opt/workspace", readOnly: false)
示例
agent {
  kubernetes {
      cloud 'kubernetes'
      slaveConnectTimeout 1200
      workspaceVolume emptyDirWorkspaceVolume()
      yaml '''
kind: Pod
metadata:
  name: jenkins-agent
spec:
  containers:
  - args: [\'$(JENKINS_SECRET)\', \'$(JENKINS_NAME)\']
    image: '192.168.10.15/kubernetes/jnlp:alpine'
    name: jnlp
    imagePullPolicy: IfNotPresent
  - command:
      - "cat"
    image: "192.168.10.15/kubernetes/alpine:latest"
    imagePullPolicy: "IfNotPresent"
    name: "date"
    tty: true
  restartPolicy: Never
'''
  }
}
2.agent 的配置示例

kubernetes 示例

pipeline {
  agent {
    kubernetes {
      cloud 'kubernetes'
      slaveConnectTimeout 1200
      workspaceVolume emptyDirWorkspaceVolume()
      yaml '''
kind: Pod
metadata:
  name: jenkins-agent
spec:
  containers:
  - args: [\'$(JENKINS_SECRET)\', \'$(JENKINS_NAME)\']
    image: '192.168.10.15/kubernetes/jnlp:alpine'
    name: jnlp
    imagePullPolicy: IfNotPresent
  - command:
      - "cat"
    image: "192.168.10.15/kubernetes/alpine:latest"
    imagePullPolicy: "IfNotPresent"
    name: "date"
    tty: true
  - command:
      - "cat"
    image: "192.168.10.15/kubernetes/kubectl:apline"
    imagePullPolicy: "IfNotPresent"
    name: "kubectl"
    tty: true
  restartPolicy: Never
'''
    }
  }
  environment {
    MY_KUBECONFIG = credentials('kubernetes-cluster')
  }
  stages {
    stage('Data') {
      steps {
        container(name: 'date') {
          sh """
            date
          """
        }
      }
    }
    stage('echo') {
      steps {
        container(name: 'date') {
          sh """
            echo 'k8s is pod'
          """
        }
      }
    }
    stage('kubectl') {
      steps {
        container(name: 'kubectl') {
          sh """
            kubectl get pod -A  --kubeconfig $MY_KUBECONFIG
          """
        }
      }
    }
  }
}

docker 的示例

pipeline {
  agent none
  stages {
    stage('Example Build') {
      agent { docker 'maven:3-alpine' }
      steps {
        echo 'Hello, Maven'
        sh 'mvn --version'
      }
    }
    stage('Example Test') {
      agent { docker 'openjdk:8-jre' }
      steps {
        echo 'Hello, JDK'
        sh 'java -version'
      }
    }
  }
}
3.Post

Post 一般用于流水线结束后的进一步处理,比如错误通知等。Post 可以针对流水线不同的结果做出不同的处理,就像开发程序的错误处理,比如 Python 语言的 try catch。

Post 可以定义在 Pipeline 或 stage 中,目前支持以下条件

  • always:无论 Pipeline 或 stage 的完成状态如何,都允许运行该 post 中定义的指令;
  • changed:只有当前 Pipeline 或 stage 的完成状态与它之前的运行不同时,才允许在该 post 部分运行该步骤;
  • fixed:当本次 Pipeline 或 stage 成功,且上一次构建是失败或不稳定时,允许运行该 post 中定义的指令;
  • regression:当本次 Pipeline 或 stage 的状态为失败、不稳定或终止,且上一次构建的 状态为成功时,允许运行该 post 中定义的指令;
  • failure:只有当前 Pipeline 或 stage 的完成状态为失败(failure),才允许在 post 部分运行该步骤,通常这时在 Web 界面中显示为红色
  • success:当前状态为成功(success),执行 post 步骤,通常在 Web 界面中显示为蓝色 或绿色
  • unstable:当前状态为不稳定(unstable),执行 post 步骤,通常由于测试失败或代码 违规等造成,在 Web 界面中显示为黄色
  • aborted:当前状态为终止(aborted),执行该 post 步骤,通常由于流水线被手动终止触发,这时在 Web 界面中显示为灰色;
  • unsuccessful:当前状态不是 success 时,执行该 post 步骤;
  • cleanup:无论 pipeline 或 stage 的完成状态如何,都允许运行该 post 中定义的指令。和 always 的区别在于,cleanup 会在其它执行之后执行。
示例

一般情况下 post 部分放在流水线的底部,比如本实例,无论 stage 的完成状态如何,都会输出一条 I will always say Hello again!信息

//Jenkinsfile (Declarative Pipeline)
pipeline {
  agent any
  stages {
    stage('Example1') {
      steps {
        echo 'Hello World1'
      }
    }
    stage('Example2') {
      steps {
        echo 'Hello World2'
      }
    }
  }
  post {
    always {
      echo 'I will always say Hello again!'
    }
  }
}

也可以将 post 写在 stage,下面示例表示 Example1 执行失败执行 post。

//Jenkinsfile (Declarative Pipeline)
pipeline {
  agent any
  stages {
    stage('Example1') {
      steps {
        sh 'ip a'
      }
      post {
        failure {
          echo 'I will always say Hello again!'
        }
      }
    }
  }
}
4.sepes

Steps 部分在给定的 stage 指令中执行的一个或多个步骤,比如在 steps 定义执行一条 shell 命令

//Jenkinsfile (Declarative Pipeline)
pipeline {
  agent any
  stages {
    stage('Example') {
      steps {
        echo 'Hello World'
      }
    }
  }
}

或者是使用 sh 字段执行多条指令

//Jenkinsfile (Declarative Pipeline)
pipeline {
  agent any
  stages {
    stage('Example') {
      steps {
        sh """
           echo 'Hello World1'
           echo 'Hello World2'
        """
      }
    }
  }
}
Directives

Directives 可用于一些执行 stage 时的条件判断或预处理一些数据,和 Sections 一致,Directives 不是一个关键字或指令,而是包含了 environment、options、parameters、triggers、stage、tools、 input、when 等配置。

1.Environment

Environment 主要用于在流水线中配置的一些环境变量,根据配置的位置决定环境变量的作用域。可以定义在 pipeline 中作为全局变量,也可以配置在 stage 中作为该 stage 的环境变量。该指令支持一个特殊的方法 credentials(),该方法可用于在 Jenkins 环境中通过标识符访问预定义的凭证。对于类型为 Secret Text 的凭证,credentials()可以将该 Secret 中的文本内容赋值给环境变量。对于类型为标准的账号密码型的凭证,指定的环境变量为 username 和 password,并且也会定义两个额外的环境变量,分别为MYVARNAME_USR和MYVARNAME_PSW。

基本变量使用

//示例
pipeline {
  agent any
  environment {   //全局变量,会在所有stage中生效
    NAME= 'zhangzhuo'
  }
  stages {
    stage('env1') {
      environment { //定义在stage中的变量只会在当前stage生效,其他的stage不会生效
        HARBOR = 'https://192.168.10.15'
      }
      steps {
        sh "env"
      }
    }
    stage('env2') {
      steps {
        sh "env"
      }
    }
  }
}

使用变量引用 secret 的凭证

//这里使用k8s的kubeconfig文件示例
pipeline {
  agent any
  environment {
    KUBECONFIG = credentials('kubernetes-cluster')
  }
  stages {
    stage('env') {
      steps {
        sh "env"  //默认情况下输出的变量内容会被加密
      }
    }
  }
}
使用变量引用类型为标准的账号密码型的凭证

这里使用 HARBOR 变量进行演示,默认情况下账号密码型的凭证会自动创建 3 个变量

  • HARBOR_USR:会把凭证中 username 值赋值给这个变量
  • HARBOR_PSW:会把凭证中 password 值赋值给这个变量
  • HARBOR:默认情况下赋值的值为usernamme:password
//这里使用k8s的kubeconfig文件示例
pipeline {
  agent any
  environment {
    HARBOR = credentials('harbor-account')
  }
  stages {
    stage('env') {
      steps {
        sh "env"
      }
    }
  }
}
2.Options

Jenkins 流水线支持很多内置指令,比如 retry 可以对失败的步骤进行重复执行 n 次,可以根据不同的指令实现不同的效果。比较常用的指令如下:

  • buildDiscarder :保留多少个流水线的构建记录
  • disableConcurrentBuilds:禁止流水线并行执行,防止并行流水线同时访问共享资源导致流水线失败。
  • disableResume :如果控制器重启,禁止流水线自动恢复。
  • newContainerPerStage:agent 为 docker 或 dockerfile 时,每个阶段将在同一个节点的新容器中运行,而不是所有的阶段都在同一个容器中运行。
  • quietPeriod:流水线静默期,也就是触发流水线后等待一会在执行。
  • retry:流水线失败后重试次数。
  • timeout:设置流水线的超时时间,超过流水线时间,job 会自动终止。如果不加 unit 参数默认为 1 分。
  • timestamps:为控制台输出时间戳。

定义在 pipeline 中

pipeline {
  agent any
  options {
    timeout(time: 1, unit: 'HOURS')  //超时时间1小时,如果不加unit参数默认为1分
    timestamps()                     //所有输出每行都会打印时间戳
    buildDiscarder(logRotator(numToKeepStr: '3')) //保留三个历史构建版本
    quietPeriod(10)  //注意手动触发的构建不生效
    retry(3)    //流水线失败后重试次数
  }
  stages {
    stage('env1') {
      steps {
        sh "env"
        sleep 2
      }
    }
    stage('env2') {
      steps {
        sh "env"
      }
    }
  }
}

定义在 stage 中

Option 除了写在 Pipeline 顶层,还可以写在 stage 中,但是写在 stage 中的 option 仅支持 retry、 timeout、timestamps,或者是和 stage 相关的声明式选项,比如 skipDefaultCheckout。处于 stage 级别的 options 写法如下

pipeline {
  agent any
  stages {
    stage('env1') {
      options {   //定义在这里这对这个stage生效
        timeout(time: 2, unit: 'SECONDS') //超时时间2秒
        timestamps()                     //所有输出每行都会打印时间戳
        retry(3)    //流水线失败后重试次数
      }
      steps {
        sh "env && sleep 2"
      }
    }
    stage('env2') {
      steps {
        sh "env"
      }
    }
  }
}
3.Parameters

Parameters 提供了一个用户在触发流水线时应该提供的参数列表,这些用户指定参数的值可以通过 params 对象提供给流水线的 step(步骤)。只能定义在 pipeline 顶层。

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
3天前
|
jenkins Java 持续交付
Jenkins离线安装部署教程简记
Jenkins离线安装部署教程简记
15 0
|
2月前
|
jenkins Java 持续交付
Docker搭建持续集成平台Jenkins最简教程
Jenkins 是一个广泛使用的开源持续集成工具,它能够自动化构建、测试和部署软件项目。在本文中,我们将使用 Docker 搭建一个基于 Jenkins 的持续集成平台。
123 2
|
2月前
|
JavaScript Java jenkins
如何利用CentOS7+docker+jenkins+gitee部署springboot+vue前后端项目(保姆教程)
如何利用CentOS7+docker+jenkins+gitee部署springboot+vue前后端项目(保姆教程)
89 0
|
9月前
|
jenkins Java 持续交付
Jenkins的简单使用,小白式教程
Jenkins的简单使用,小白式教程
182 0
|
9月前
|
前端开发 Ubuntu jenkins
前端项目自动化部署——超详细教程(Jenkins、Github Actions)(三)
前端项目自动化部署——超详细教程(Jenkins、Github Actions)(三)
451 0
|
9月前
|
前端开发 jenkins Linux
前端项目自动化部署——超详细教程(Jenkins、Github Actions)(二)
前端项目自动化部署——超详细教程(Jenkins、Github Actions)(二)
627 0
|
9月前
|
前端开发 JavaScript jenkins
前端项目自动化部署——超详细教程(Jenkins、Github Actions)(一)
前端项目自动化部署——超详细教程(Jenkins、Github Actions)
359 0
|
消息中间件 Kubernetes jenkins
说实话,Jenkins 真得很牛逼!只是大部分人不会用而已~(保姆级教程)(下)
说实话,Jenkins 真得很牛逼!只是大部分人不会用而已~(保姆级教程)(下)
|
Java jenkins 持续交付
Jenkins 安装配置教程(下)
Jenkins 安装配置教程(下)
Jenkins 安装配置教程(下)
|
5月前
|
jenkins Java 持续交付
【项目集成工具】Jenkins
【项目集成工具】Jenkins