Skip to content

Jenkins

Jenkins 是什么

Jenkins 是一个独立的开源自动化服务器,可以用来自动化与构建、测试、交付或部署软件相关的各种任务。

Jenkins 可以通过本地系统包、Docker 安装,甚至可以在任何安装了 Java 运行环境(JRE,Java Runtime Environment)的机器上独立运行。

安装 Jenkins

Docker

sh
$ docker run -d -p 8080:8080 --name jenkins jenkins/jenkins:lts-jdk11

安装后的设置向导

解锁 Jenkins

第一次访问一个新的 Jenkins 实例时,需要使用自动生成的密码解锁它。

  1. 浏览到 http://localhost:8080(或安装时为 Jenkins 配置的任何端口),并等待解锁 Jenkins 页面出现。

image (图片来源:Jenkins 官网)

  1. 从 Jenkins 控制台日志输出中,复制自动生成的字母数字密码(在两组星号之间)。

    • Docker
    sh
    $ docker logs jenkins
    ···
    2022-07-05 02:59:23.345+0000 [id=29]    INFO    jenkins.install.SetupWizard#init: 
    
    *************************************************************
    *************************************************************
    *************************************************************
    
    Jenkins initial setup is required. An admin user has been created and a password generated.
    Please use the following password to proceed to installation:
    
    a7f5186a72eb43cfb88a83602ae944ad
    
    This may also be found at: /var/jenkins_home/secrets/initialAdminPassword
    
    *************************************************************
    *************************************************************
    *************************************************************
    ···
  2. 解锁 Jenkins 页面上,将此密码粘贴到管理员密码字段中,然后单击继续

TIP

Jenkins 控制台日志显示可以获取密码的位置(在 Jenkins 主目录中)。必须在新 Jenkins 安装中的安装向导中输入此密码才能访问 Jenkins 的主 UI。如果您在设置向导中跳过了后续的用户创建步骤,则此密码还可用作默认 admininstrator 帐户的密码(使用用户名“admin”)。

用插件定制 Jenkins

解锁 Jenkins 后,会出现自定义 Jenkins 页面。

  • 安装推荐的插件 — 安装推荐的插件集,这些插件基于最常见的用例。

  • 选择插件来安装 — 选择并安装最合适的插件集。

创建第一个管理员用户

最后,在使用插件自定义 Jenkins 之后,Jenkins 会要求创建第一个管理员用户。

  1. 创建第一个管理员用户页面出现时,在各自的字段中指定管理员用户的详细信息,然后单击保存完成

  2. Jenkins 准备好了出现时,单击开始使用 Jenkins

  3. 如果需要,使用您刚刚创建的用户的凭证登录到 Jenkins,您就可以开始使用 Jenkins 了!

使用 Jenkins

第一个流水线

  1. 如果有要求的话,确保你已登录进 Jenkins。

  2. 从 Jenkins 主页(即 Jenkins 经典 UI 的工作台),点击左上的新建Item

  3. 输入一个任务名称字段,填写你新建的流水线项目的名称。

WARNING

Jenkins 使用这个项目名称在磁盘上创建目录。建议不要在项目名称中使用空格,因为这样做可能会触发在脚本中不能正确处理目录路径中的空格的 bug。

  1. 向下滚动并点击流水线,然后点击页面底部的确定打开流水线配置页。

  2. 点击页面顶部的流水线选项卡让页面向下滚动到流水线部分。

  3. 流水线部分, 确保定义字段显示Pipeline script选项。

  4. 将你的流水线代码输入到脚本文本区域。

    jenkinsfile
    pipeline {
        agent any // 1
    
        stages {
            stage('hello') {
                steps {
                    echo 'Hello, Jenkins!' // 2
                }
            }
        }
    }
    1. agent 指示 Jenkins 为整个流水线分配一个执行器(在 Jenkins 环境中的任何可用代理/节点上)和工作区。

    2. echo 写一个简单的字符串到控制台输出。

  5. 点击保存打开流水线项目视图页面。

  6. 在该页面, 点击左侧的立即构建运行流水线。

  7. 在左侧的 Build History 下面,点击 #1 来访问这个特定流水线运行的详细信息。

  8. 点击 Console Output 来查看流水线运行的全部输出。下面的输出显示你的流水线已成功运行。

    sh
    Started by user admin
    [Pipeline] Start of Pipeline
    [Pipeline] node
    Running on Jenkins in /var/jenkins_home/workspace/hello-world
    [Pipeline] {
    [Pipeline] stage
    [Pipeline] { (hello)
    [Pipeline] echo
    Hello, Jenkins!
    [Pipeline] }
    [Pipeline] // stage
    [Pipeline] }
    [Pipeline] // node
    [Pipeline] End of Pipeline
    Finished: SUCCESS

流水线

什么是 Jenkins 流水线

Jenkins 流水线 (或简单的带有大写 "P" 的 "Pipeline") 是一套插件,它支持实现和集成 continuous delivery pipelines 到Jenkins。

流水线提供了一组可扩展的工具,通过 Pipeline domain-specific language (DSL) syntax 将从简单到复杂的交付管道建模为“代码”。

Jenkins 流水线的定义被写入一个文本文件(称为 Jenkinsfile),该文件可以提交给项目的源代码控制存储库。这是“管道即代码”的基础;将 CD(continuous delivery) 流水线作为应用程序的一部分进行版本控制和审查,就像其他代码一样。

创建一个 Jenkinsfile 并将其提交给源代码控制提供了许多直接的好处:

  • 自动为所有分支和 pull 请求创建一个流水线构建流程。

  • 对流水线的代码审查/迭代(包括剩余的源代码)。

  • 对流水线进行审计跟踪。

  • 该流水线的真正的源代码, 可以被项目的多个成员查看和编辑。

尽管在 web UI 中或在 Jenkinsfile 中定义流水线的语法是相同的,但通常认为在 Jenkinsfile 中定义流水线并将其检入到源代码控制中是最佳实践。

声明式和脚本式的流水线语法

Jenkinsfile 能使用两种语法进行编写 - 声明式和脚本式。

声明式和脚本式的流水线从根本上是不同的。声明式流水线的是 Jenkins 流水线更近的特性:

  • 相比脚本式的流水线语法,它提供更丰富的语法特性,

  • 是为了使编写和读取流水线代码更容易而设计的。

然而,写入 Jenkinsfile 的许多单独的语法组件(或“步骤”)对于声明式管道和脚本式管道都是通用的。

流水线的概念

下面的概念是 Jenkins 流水线很关键的一方面,它与流水线语法紧密相连。

Pipeline

流水线是用户定义的一个 CD 流水线模型。流水线的代码定义了整个的构建过程,他通常包括构建、测试和交付应用程序的阶段。

另外,pipeline 块是声明式流水线语法的关键部分

Node

节点是一台机器,它是 Jenkins 环境的一部分,能够执行流水线。

此外,node 块是脚本式流水线语法的关键部分

Stage

stage 定义了通过整个流水线执行的任务的一个概念上不同的子集(比如 "Build", "Test" 和 "Deploy" 阶段),许多插件使用它来可视化或呈现 Jenkins 流水线的状态/进度。

Step

一个单一的任务。从根本上说,step 告诉 Jenkins 在特定时间点(或流程中的“步骤”)要做什么。例如,执行 shell 命令 make 时,需要使用 sh 步骤:sh 'make'。当一个插件扩展流水线 DSL 时,通常意味着插件实现了一个新步骤。

流水线语法概述

声明式流水线基础

在声明式流水线语法中,pipeline 块定义了整个流水线中完成的所有的工作。

jenkinsfile
// Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any // 1
    stages {
        stage('Build') { // 2
            steps {
                // 3
            }
        }
        stage('Test') { // 4
            steps {
                // 5
            }
        }
        stage('Deploy') { // 6
            steps {
                // 7
            }
        }
    }
}
  1. 在任何可用的代理上,执行流水线或它的任何阶段。

  2. 定义 "Build" 阶段。

  3. 执行与 "Build" 阶段相关的步骤。

  4. 定义 "Test" 阶段。

  5. 执行与 "Test" 阶段相关的步骤。

  6. 定义 "Deploy" 阶段。

  7. 执行与 "Deploy" 阶段相关的步骤。

脚本式流水线基础

在脚本化流水线语法中, 一个或多个 node 块负责整个流水线中的核心工作。虽然这不是脚本化流水线语法的强制性要求, 但将流水线的工作限制在 node 块内会产生两种效果:

  1. 通过向 Jenkins 队列添加一个项来调度块中包含的步骤运行。只要节点上的执行器空闲,这些步骤就会运行。

  2. 创建一个工作区(一个特定于该流水线的目录),可以在其中对从源代码控制中签出的文件进行处理。

jenkinsfile
// Jenkinsfile (Scripted Pipeline)

node { // 1 
    stage('Build') { // 2
        // 3
    }
    stage('Test') { // 4
        // 5
    }
    stage('Deploy') { // 6
        // 7
    }
}
  1. 在任何可用的代理上,执行流水线或它的任何阶段。

  2. 定义 "Build" 阶段。 stage 块在脚本化流水线语法中是可选的。然而,在脚本化流水线中实现 stage 块,可以清楚的显示 Jenkins UI 中的每个 stage 的任务子集。

  3. 执行与 "Build" 阶段相关的步骤。

  4. 定义 "Test" 阶段。

  5. 执行与 "Test" 阶段相关的步骤。

  6. 定义 "Deploy" 阶段。

  7. 执行与 "Deploy" 阶段相关的步骤。

使用 Jenkinsfile

复杂的流水线很难在流水线配置页面的脚本文本区域进行编写和维护。

为简化操作,流水线的 Jenkinsfile 可以在文本编辑器或集成开发环境(IDE)中进行编写并提交到源码管理系统(可选择性地与需要 Jenkins 构建的应用程序代码放在一起)。然后 Jenkins 从源代码管理系统中检出 Jenkinsfile 文件作为流水线项目构建过程的一部分并接着执行你的流水线。

在源代码管理系统中定义流水线

要使用来自源代码管理系统的 Jenkinsfile 文件配置流水线项目:

  1. 按照上面的步骤定义你的流水线直到第 5 步(在流水线配置页面访问流水线部分)。

  2. 定义字段选择 Pipeline script from SCM 选项。

  3. SCM 字段,选择包含 Jenkinsfile 文件的仓库的源代码管理系统的类型。

  4. 填充对应仓库的源代码管理系统的字段。

    Tip: 如果你不确定给定字段应填写什么值,点击它右侧的 ? 图标以获取更多信息。

  5. 脚本路径字段,指定你的 Jenkinsfile 文件的位置(和名称)。这个位置是 Jenkins 检出/克隆包括 Jenkinsfile 文件的仓库的位置,它应该与仓库的文件结构匹配。该字段的默认值采取名称为 JenkinsfileJenkinsfile 文件并位于仓库的根路径。

    jenkinsfile
    pipeline {
        agent any
    
        stages {
            stage('hello') {
                steps {
                    echo 'Hello, Jenkins!'
                }
            }
        }
    }
  6. 点击保存打开流水线项目视图页面。

  7. 在该页面, 点击左侧的立即构建运行流水线。

  8. 在左侧的 Build History 下面,点击 #1 来访问这个特定流水线运行的详细信息。

  9. 点击 Console Output 来查看流水线运行的全部输出。下面的输出显示你的流水线已成功运行。

    sh
    Started by user admin
    Obtained Jenkinsfile from git https://github.com/panxingcheng/jenkinsfile.git
    [Pipeline] Start of Pipeline
    [Pipeline] node
    Running on Jenkins in /var/jenkins_home/workspace/hello-world
    [Pipeline] {
    [Pipeline] stage
    [Pipeline] { (Declarative: Checkout SCM)
    [Pipeline] checkout
    Selected Git installation does not exist. Using Default
    The recommended git tool is: NONE
    No credentials specified
    Cloning the remote Git repository
    Cloning repository https://github.com/panxingcheng/jenkinsfile.git
    > git init /var/jenkins_home/workspace/hello-world # timeout=10
    Fetching upstream changes from https://github.com/panxingcheng/jenkinsfile.git
    > git --version # timeout=10
    > git --version # 'git version 2.30.2'
    > git fetch --tags --force --progress -- https://github.com/panxingcheng/jenkinsfile.git +refs/heads/*:refs/remotes/origin/* # timeout=10
    > git config remote.origin.url https://github.com/panxingcheng/jenkinsfile.git # timeout=10
    > git config --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/* # timeout=10
    Avoid second fetch
    > git rev-parse refs/remotes/origin/main^{commit} # timeout=10
    Checking out Revision 86873a2d22812873528cb317b2425c8f761f12ef (refs/remotes/origin/main)
    > git config core.sparsecheckout # timeout=10
    > git checkout -f 86873a2d22812873528cb317b2425c8f761f12ef # timeout=10
    Commit message: "Create Jenkinsfile"
    First time build. Skipping changelog.
    [Pipeline] }
    [Pipeline] // stage
    [Pipeline] withEnv
    [Pipeline] {
    [Pipeline] stage
    [Pipeline] { (hello)
    [Pipeline] echo
    Hello, Jenkins!
    [Pipeline] }
    [Pipeline] // stage
    [Pipeline] }
    [Pipeline] // withEnv
    [Pipeline] }
    [Pipeline] // node
    [Pipeline] End of Pipeline
    Finished: SUCCESS

在流水线中使用 Docker

从流水线版本 2.5 或以上开始, 流水线内置了与 Jenkinsfile 中的 Docker 进行交互的的支持。

TIP

  • 要在 Jenkins 容器使用 Docker,请参见Jenkins 容器使用宿主机的 Docker

  • 需要安装 docker-workflow 插件,不然报这个错误: org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed: WorkflowScript: 3: Invalid agent type "docker" specified. Must be one of [any, label, none]

自定义执行环境

jenkinsfile
pipeline {
    agent {
        docker {
            image 'maven:3.8.6-eclipse-temurin-17-alpine'
        }
    }
    stages {
        stage('Test') {
            steps {
                sh 'mvn --version'
            }
        }
    }
}

为容器缓存数据

jenkinsfile
pipeline {
    agent {
        docker {
            image 'maven:3.8.6-eclipse-temurin-17-alpine'
            args '-v $HOME/.m2/:/root/.m2/'
        }
    }
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
    }
}

使用多个容器

jenkinsfile
pipeline {
    agent none
    stages {
        stage('Build') {
            agent {
                docker {
                    image 'maven:3.8.6-eclipse-temurin-17-alpine'
                    args '-v $HOME/.m2/:/root/.m2/'
                }
            }
            steps {
                sh 'mvn clean package'
            }
        }
        stage('Test') {
            agent {
                docker {
                    image 'maven:3.8.6-eclipse-temurin-17-alpine'
                }
            }
            steps {
                sh 'mvn --version'
            }
        }
    }
}

Released under the MIT License.