Jenkinsfile 使用说明(1)

文章目录

    • 1. Jenkins 是什么
    • 2. 流水线
      • 2.1 流水线是什么
      • 2.2 流水线的分类
      • 2.2 为什么使用流水线
    • 3. 声明式流水线——jenkinsfile 的语法
      • 3.1 声明式流水线基础语法
      • 3.2 典型的声明式流水线例子
      • 3.3 流水线基础语法详解
        • 3.3.1 agent (require)
        • 3.3.2 stages (require)
        • 3.3.3 stage (require && alest one)
        • 3.3.4 steps (require)
        • 3.3.5 environment
        • 3.3.6 parameters
        • 3.3.7 post
        • 3.3.8 tools
        • 3.3.9 值得学习的关键字大集合
    • 4. 碎碎念
    • 5. 参考资料

1. Jenkins 是什么

Jenkins 是一款由 Java 编写的开源的持续集成工具。

注:目前一些自动化编译,自动化测试都允许在 Jenkins 上运行。

2. 流水线

2.1 流水线是什么

Jenkins 2.0 的到来, Pipeline(流水线)进入了视野, jenkins 2.0 的核心特性,也是最适合持续交付的 feature。

注:简单的来说,就是把 Jenkins 1.0 版本中,Project 中的相关配置信息,如 SVN/Git 的配置,Parameter 的配置等都变成 Code,即 Pipeline as Code。

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

Jenkins 允许你将配置文件和执行步骤以代码的形式保持,这样就可以做到像管理源码一样管理 Jenkins 任务。

注:Jenkins Pipeline (流水线)是一套插件,将持续交付的实现和实施集成到 Jenkins 中。其提供了一套可扩展的工具,用于将「简单到复杂」的交付流程实现为「持续交付即代码」。

​ Jenkins Pipeline (流水线) 的定义通常被写入到一个文本文件——Jenkinsfile 中,该文件可以被放入项目的源代码控制库中。

2.2 流水线的分类

Jenkins 流水线分为脚本式的和声明式的

  • 脚本式流水线比较灵活,可以嵌入一些 Groovy 语言编程,功能比较强大,但是对于新手而言上手较难。
    • pipeline 块是 声明式流水线的基础。
  • 声明式流水线更具有结构化,减少对 Groovy 语言的依赖,对新用户比较友好。
    • node 块是 脚本化流水线的基础

2.2 为什么使用流水线

本质上,Jenkins 是一个自动化引擎,它支持许多自动模式。流水线向 Jenkins 中添加了一组强大的工具,支持用例简单的持续集成到全面的 CD 流水线。用户可以利用很多流水线的特性:

  • 代码:Pipeline 以代码的形式实现,通常被检入源代码控制,使团队能够编辑、审查和迭代其 CD 流程
  • 可持续性:Jenkins 重启或者中断后都不会影响 Pipeline Job
  • 停顿:Pipeline 可以选择停止并等待人工输入或批准,然后在继续 Pipeline 运行
  • 多功能:Pipeline 支持现实世界的复杂 CD 要求,包括 fork/join 子进程,循环和并行执行工作的能力
  • 可扩展:Pipeline 插件支持其 DSL 的自定义扩展以及其他插件集成的多个选项

简而言之,就是使用 jenkins 的流水线比研发自己手动执行

  • 编译
  • 制作镜像
  • 推送镜像到 hub

的流程有很多优势。

3. 声明式流水线——jenkinsfile 的语法

3.1 声明式流水线基础语法

  • pipeline:声明其内容为一个声明式的 Pipeline 脚本
  • agent:执行节点(job 运行的 slave 或者 master 节点)
  • stages:阶段集合,包括所有的阶段(例如:打包、部署等各个阶段)
  • stage:阶段,被 stages 包括,一个 stages 可以有多个 stage
  • steps: 步骤,为每个阶段的最小执行单位,被 stage 包括
  • post:执行构建后的操作,根据构建结果来执行对应的操作

3.2 典型的声明式流水线例子

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

Jenkinsfile (Declarative Pipeline)
pipeline {
    agent any /*1*/
    stages {
        stage('Build') { /*2*/
            steps {
                // /*3*/
            }
        }
        stage('Test') { /*4*/
            steps {
                // /*5*/
            }
        }
        stage('Deploy') { /*6*/
            steps {
                // /*7*/
            }
        }
    }
}

上述定义的 1-7 的解释如下:

  • 1 -> 在任何可以用的代理上,执行流水线或它的任何阶段。
  • 2 -> 定义「Build」阶段
  • 3 -> 定义与 「Build」阶段相关的步骤
  • 4 -> 定义 「Test」阶段
  • 5 -> 定义与 「Test」阶段相关的步骤
  • 6 -> 定义 「Deploy」阶段
  • 7 -> 定义与 「Deploy」阶段相关的步骤

注:部分 jenkins 的集群不支持 agent any 的写法。

Jenkinsfile 使用说明(1)_第1张图片

3.3 流水线基础语法详解

所有有效的声明式流水线必须包含在一个 pipeline块中,比如:

pipeline {
	/* insert Declarative Pipeline here */
}

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

  • 流水线顶层必须是一个 block,特别地:pipeline{}
  • 没有分号作为语句分隔符,每条语句必须在自己的行上
  • 块只能由 Sections、Directives、Steps 和赋值语句组成
  • 属性引用语句被视为无参数方法调用,因此,例如,输入被视为 input()

注:当前存在一个未解决的问题,该问题限制了 pipeline {} 内代码块的大小,但此限制不适用与脚本化 pipeline

3.3.1 agent (require)

agent 声明整个 pipeline 脚本或某个 stage 脚本在 jenkins 中的运行环境。

  • 写在 pipeline 最外层则是声明整个 pipeline 的运行环境
  • 写在 stage 里则是 stage 的运行环境

agent 的类型参数

  • any:在任意可用代理上运行 pipeline

  • none:当在全局声明 agent 为 none 时,那么每一个 stage 都需声明自己的 agent

  • label:按在 jenkins 环境中设定的 label 标签名声明 agent,如 label 所代表的节点。

    agent {
      label 'my-node1'
    }
    

    注:label 的 value 可以使用逻辑符号组合

  • node:node 声明运行节点,与 label 功能类似,但是 node 可以附加选项参数,如 label、customWorkspace 等

    agent {
      node {
          label 'my-node1'
      }
    }
    

    注:以上的 node 写法与 label 的写法相同

  • docker: 用于基于 docker 的 pipeline 流水线,在预配置的节点或指定 label 的节点上创建 docker 容器。除此之外,还可以接收 docker run 的参数,以及 docker registry 等参数。

    agent {
      docker {
          image 'maven:3.8.1-adoptopenjdk-11'
          label 'my-defined-label'
          args  '-v /tmp:/tmp'
          registryUrl 'https://myregistry.com/'
          registryCredentialsId 'myPredefinedCredentialsInJenkins'
      }
    }
    
  • dockerfile:从一个 Dockerfile 创建 docker 容器来运行 pipeline 流水线。默认会从构建的根目录寻找 Dockerfile。

    • 如果项目的 Dockerfile 存放在子目录,则需要通过 dir 参数声明。

    • 如果 Dockerfile 名字是其他自定义名则需要通过 filename 参数说明。

      注:还可以通过 additionBuildArgs 来设置 docker build 参数。使用 registryUrl 来设置 docker 仓库,使用 registryCredentialsId 从 jenkins 获取 docker 仓库的账号密码。

    agent {
        // Equivalent to "docker build -f Dockerfile.build --build-arg version=1.0.2 ./build/
        dockerfile {
            filename 'Dockerfile.build'
            dir 'build'
            label 'my-defined-label'
            additionalBuildArgs  '--build-arg version=1.0.2'
            args '-v /tmp:/tmp'
            registryUrl 'https://myregistry.com/'
            registryCredentialsId 'myPredefinedCredentialsInJenkins'
        }
    }
    
  • kubernetes:在 Kubernetes 集群中的一个 Pod 内执行 pipeline 流水线,pod 模板将定义在 kubernetes {} 模块中。如果需要在 Pod 中安装 Kaniko 则可在 yaml 参数中声明。

    注:使用 Kaniko 是无需 docker demo 即可构建 docker 镜像的方式

    agent {
        kubernetes {
            label podlabel
            yaml """
    kind: Pod
    metadata:
      name: jenkins-agent
    spec:
      containers:
      - name: kaniko
        image: gcr.io/kaniko-project/executor:debug
        imagePullPolicy: Always
        command:
        - /busybox/cat
        tty: true
        volumeMounts:
          - name: aws-secret
            mountPath: /root/.aws/
          - name: docker-registry-config
            mountPath: /kaniko/.docker
      restartPolicy: Never
      volumes:
        - name: aws-secret
          secret:
            secretName: aws-secret
        - name: docker-registry-config
          configMap:
            name: docker-registry-config
    """
       }
    
3.3.2 stages (require)

pipeline 阶段集声明部分,至少包含一个或多个 stage

3.3.3 stage (require && alest one)

构建阶段模块。定义构建阶段要做的事情,每个 pipeline 流水线至少包含一个 stage。一个 stage 里有且只有一个 steps。

pipeline {
    agent any
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'
            }
        }
    }
}
3.3.4 steps (require)

Steps 包含一个或多个可执行指令。

3.3.5 environment

environment 命令用于声明一系列的键值对作为整个 pipeline 或某个 stage 指令执行的环境变量,取决于它定义在 pipeline 的最外层或 stage 里。该指令还支持通过 credentials() 获取预设的账户密码。

其中支持的 credential 类型包括:

  • Secret Text:该环境变量的值将会被设置为 Secret Text 的内容。
  • Secret File:该环境变量的值将会被设置为临时创建文件路径。
  • Username and Password:该环境变量的值将会被设置为 username:password ,并且还会自动创建两个环境变量:MYVARNAME_USR 和 MYVARNAME_PSW。
  • SSH with Private Key:该环境变量的值将会被设置为临时创建的 ssh key 文件路径,并且还会自动创建两个环境变量:MYVARNAME_USR 和 MYVARNAME_PSW。
pipeline {
    agent any
    stages {
        stage('Example Username/Password') {
            environment {
                SERVICE_CREDS = credentials('my-predefined-username-password')
            }
            steps {
                sh 'echo "Service user is $SERVICE_CREDS_USR"'
                sh 'echo "Service password is $SERVICE_CREDS_PSW"'
                sh 'curl -u $SERVICE_CREDS https://myservice.example.com'
            }
        }
        stage('Example SSH Username with private key') {
            environment {
                SSH_CREDS = credentials('my-predefined-ssh-creds')
            }
            steps {
                sh 'echo "SSH private key is located at $SSH_CREDS"'
                sh 'echo "SSH user is $SSH_CREDS_USR"'
                sh 'echo "SSH passphrase is $SSH_CREDS_PSW"'
            }
        }
    }
}
3.3.6 parameters

parameters 声明当构建触发时用户要输入的所有参数,steps 指令将通过 params 对象获取这些参数。

参数类型包括:

  • string
  • text
  • boolean
  • choice
  • password

举个例子:

pipeline {
    agent any
    parameters {
        string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')

        text(name: 'BIOGRAPHY', defaultValue: '', description: 'Enter some information about the person')

        booleanParam(name: 'TOGGLE', defaultValue: true, description: 'Toggle this value')

        choice(name: 'CHOICE', choices: ['One', 'Two', 'Three'], description: 'Pick something')

        password(name: 'PASSWORD', defaultValue: 'SECRET', description: 'Enter a password')
    }
    stages {
        stage('Example') {
            steps {
                echo "Hello ${params.PERSON}"

                echo "Biography: ${params.BIOGRAPHY}"

                echo "Toggle: ${params.TOGGLE}"

                echo "Choice: ${params.CHOICE}"

                echo "Password: ${params.PASSWORD}"
            }
        }
    }
}
3.3.7 post

定义附加 steps 在整个 pipeline 流水线或某个 stage 执行完之后运行。post 可以定义在 pipeline 的最外层或某个 stage 里,如果定义在最外层则表示这个 pipeline 执行完之后运行,如果在 stage 里则表示该 stage 执行完后运行。

  • always:不管 pipeline 或 stage 的执行结果状态,总会执行的 steps
  • changed:只有在 pipeline 或 stage 的执行结果状态与前一次执行相比发生改变时执行
  • fixed:当前 pipeline 或 stage 执行成功且它的前一次执行结果是 failure 或 unstable 时执行
  • regression:当前 pipeline 或 stage 执行结果是 failure,unstable 或 aborted 且它的前一次执行成功时执行。
  • aborted:当前 pipeline 或 stage 执行结果是 aborted 时执行
  • failure:当前 pipeline 或 stage 执行结果是失败时执行
  • success:当前 pipeline 或 stage 执行结果是成功时执行
  • unstable:当前 pipeline 或 stage 执行结果是 unstable 时执行(ps (⊙_⊙) 什么是 unstable?)
  • unsuccessful:当前 pipeline 或 stage 执行结果不是成功时执行
  • cleanup:在其他所有的 post 场景脚本都处理完之后执行,不管当前 pipeline 或 stage 执行结果是什么

继续举个例子:

pipeline {
    agent any
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'
            }
        }
    }
    post { 
        always { 
            echo 'I will always say Hello again!'
        }
    }
}
3.3.8 tools

声明需要自动按照构建所需的工具,并设置到 PATH 环境变量里。当 agent none 时,tools 声明会自动忽略。

支持安装的工具有:jdk、maven、gradle

例子:

pipeline {
    agent any
    tools {
        maven 'apache-maven-3.0.1' 
    }
    stages {
        stage('Example') {
            steps {
                sh 'mvn --version'
            }
        }
    }
}
3.3.9 值得学习的关键字大集合
  • input:stage 参数输入指令。在进入 agent 模块和 when 条件判断之前,stage 将会被暂停并弹出输入对话框,直到用户输入可用的参数后 stage 才会继续执行。所有输入的参数在余下的 stage 指令当中都可以通过环境变量获取。

  • pipeline:流水线选项参数,pipeline 流水线提供了一系列的选项参数。其中也有些由插件提供,例如 timestamps。全局 options 声明在最外面,而写在 stage 里的则只在该 stage 有效且 stage options 只支持:skipDefaultCheckouttimeoutretrytimestamps

  • when:命令通过设定的条件判断决定 pipeline 流水线的当前stage是否执行, when 命令至少包含一个条件判断。如果when包含多个条件判断,那么当且仅当所有条件判断都为true时,当前 stage才 会被执行。

    注:正常情况下 when 判断时在 agent,input,options 命令之后才执行的,但是可以通过 beforeAgent,beforeInput,beforeOptions 参数来设置提前执行。

4. 碎碎念

今天平安夜,希望大家都能平平安安的:

  • 最好的状态是一点点向自己喜欢的东西靠近,保持热爱奔赴山海,忠于自己热爱生活,知足上进。
  • 要在最快乐的年纪活的精彩且迷人。
  • 务必请你,一而再,再而三,三而不竭,千次万次,毫不犹豫地,救自己于这世间水火。

最近真的是持续性萎靡不振,不想努力,那就允许自己放松一阵子吧。

5. 参考资料

  • jenkins 入门
  • Jenkins(软件)
  • 流水线
  • Jenkins pipline on kubernetes
  • Jenkins pipeline 基础语法与示例
  • Kaniko-以一种更安全可靠的方式在 Kubernetes 平台上构建容器镜像|IDCF

你可能感兴趣的:(jenkins,运维)