jenkins语法

ads

作者ZHDYA,曾运营 “云原生个锤子” 达3000+人,专注免费分享一些DEVOPS/运维/自动化/K8S生态方面的实战技巧,我们一起前行学习!

最近更新主要围绕:Kubernetes、持久化存储、Helm、CICD、Ingress-nginx、监控告警、应用可观察性等相关文章。

Jenkins Pipeline语法一、什么是Jenkins Pipeline二、Declarative Pipeline(声明式)流水线2.1、特点2.2、声明式核心概念:2.2.1、pipeline2.2.2、agent2.2.3、stages2.2.4、stage2.2.5、steps2.2.6、post(可选)2.2.7、parameters(可选)2.2.8、triggers(可选)2.2.9、input(可选)2.2.10、when(可选)三、Scripted Pipeline(脚本式)流水线四、Declarative pipeline和Scripted pipeline的比较五、优化交付流水线性能5.1、并行执行5.2、缓存依赖项5.3、删除不必要的阶段六、总结

Jenkins Pipeline语法

作为一种流行的持续集成和交付工具,Jenkins有多种方式来实现交付流水线。其中,Jenkins Pipeline是一种比较流行的方式,它提供了一个DSL(Domain Specific Language 的缩写,中文翻译为:领域特定语言)来描述交付流水线。

官方:Pipeline Syntax (jenkins.io)

一、什么是Jenkins Pipeline

Jenkins Pipeline是一种基于Groovy编写的DSL,它可以描述交付流水线。Pipeline支持串行和并行的执行,可以将多个任务组合成一个流水线。Pipeline也支持将上下文传递给不同的阶段,使得阶段之间的数据共享变得更加容易。

Pipeline提供了三种编写Pipeline的方式:

Declarative Pipeline:是基于YAML编写的声明式语言,它可以更容易地描述交付流水线。

Scripted Pipeline:是基于Groovy编写的脚本语言,它是一种灵活的方式来描述交付流水线。

Jenkinsfile:是一种将Pipeline脚本保存为Jenkins源代码管理系统中的文件的方式。

二、Declarative Pipeline(声明式)流水线

2.1、特点

  • 最外层必须由pipline{ //do something }来进行包裹

  • 不需要分号作为分隔符,每个语句必须在一行内

  • 不能直接使用groovy语句(例如循环判断等),需要被script {}包裹

下面是一个简单的Pipeline脚本示例:

pipeline{   // 最外层必须由pipeline包裹
   agent any // agent表示再哪个节点执行
   stages{
       stage("build"){
           steps{ // 具体执行步骤
               echo "Build..."
          }
      }
       stage("test"){
           steps{
               echo "Test..."
          }
      }
       stage("depoly"){
           steps{
               echo "Deployment..."
          }
      }
  }
   post{ // 最后执行
       success{ // 测试成功时执行(需要安装 Email Extension 插件)
           emailext body: 'Build succeeded!', subject: 'Build Success', to: 'xx@example.com'
      }
       failure{ // 失败时会执行
           emailext body: 'Build failed!', subject: 'Build Failure', to: 'xx@example.com'
      }
  }
}

在这个示例中,我们使用了三个阶段:buildtestdeploy

每个阶段都是一个stage块。在每个阶段中,我们可以使用Jenkins提供的一些API来执行任务,例如sh命令来执行shell脚本或者Jenkins提供的其他插件。

2.2、声明式核心概念:

  1. pipeline:声明其内容为一个声明式的pipeline脚本;

  2. agent:执行节点(job运行的slave或者master节点);

  3. stages:阶段集合,包裹所有的阶段(例如:打包,部署等各个阶段);

  4. stage:阶段,被stages包裹,一个stages可以有多个stage;

  5. steps:步骤,为每个阶段的最小执行单元,被stage包裹;

  6. post:执行构建后的操作,根据构建结果来执行对应的操作;

2.2.1、pipeline
作用域:应用于全局最外层,表明该脚本为声明式pipeline
是否必须:必须
参数:无
2.2.2、agent
作用域:可用在全局与stage内
是否必须:是,
参数:any, none, label, node, docker, dockerfile

参考示例:
//运行在任意的可用节点上
agent any

//全局不指定运行节点,由各自stage来决定
agent none

//运行在指定标签的机器上,具体标签名称由agent配置决定
agent { label 'master' }

//node参数可以扩展节点信息
agent {
    node {
        label 'master'
        customWorkspace 'xxx'
  }
}

//使用指定运行的容器
pipeline{
  agent none
  stages{
      stage('build Test'){
             agent {docker 'maven:3-alpine'}
             steps{
                  echo "Build Test"
                  }    
              }
      stage('Example Test'){
             agent {docker 'openjdk:8-jre'}
             steps{
                 echo "Exmaple Test"
              }
            }
        }
}
2.2.3、stages
作用域:全局或者stage阶段内,每个作用域内只能使用一次
是否必须:全局必须
参数:无

参考示例:
pipeline{
   agent any
   stages{
       stage("first stage"){
           stages{  //嵌套在stage里
               stage("inside"){
                   steps{
                       echo "inside"
                  }
              }
               stage("inside_two"){
                   steps{
                       echo "inside_two"
                  }
              }
          }
      }
       stage("stage2"){
           steps{
               echo "outside"
          }
      }
  }
}
2.2.4、stage
作用域:被stages包裹,作用在自己的stage包裹范围内
是否必须:必须
参数:需要一个string参数,表示此阶段的工作内容
备注:stage内部可以嵌套stages,内部可单独制定运行的agent
2.2.5、steps
作用域:被stage包裹,作用在stage内部
是否必须:必须
参数:无
2.2.6、post(可选)
作用域:作用在pipeline结束或者stage结束后
条件:always、changed、failure、success、unstable、aborted
2.2.7、parameters(可选)
  • 构建时用户需要提供的参数

  • 这些参数可以通过params提供给流水线的steps使用,有 字符串 类型和 boolean 类型string:字符串类型,parameters { string(name: ‘DEPLOY_ENV’, defaultValue: ‘staging’, description: ‘’) }booleanParam:布尔参数,parameters { booleanParam(name: ‘DEBUG_BUILD’, defaultValue: true, description: ‘’) }text:文本参数,包含多行 parameters { text(name: ‘DEPLOY_TEXT’, defaultValue: ‘OnenTwonThreen’, description: ‘’) }choice:选择类型的参数,parameters { choice(name: ‘CHOICES’, choices: [‘one’, ‘two’, ‘three’], description: ‘’) }password:password参数,parameters { password(name: ‘PASSWORD’, defaultValue: ‘SECRET’, description: ‘A secret password’) }

示例:

pipeline{
   agent any
   parameters {
       string(name: 'P1', defaultValue: 'it is p1', description: 'it is p1')
       booleanParam(name: 'P2', defaultValue: true, description: 'it is p2')
  }
   stages{
       stage("stage1"){
           steps{
               echo "$P1"
               echo "$P2"
          }
      }
  }
}
2.2.8、triggers(可选)

自动化触发运行pipeline的方法

示例:每两分钟触发一次job

pipeline{
agent any
triggers{cron("*/2 * * * *")}
stages{
stage("Build Test"){
steps{
echo "hello world"
}
}
}
}
2.2.9、input(可选)

指令允许 暂时中断 pipeline执行,等待用户输入,根据用户输入进行下一步动作

pipeline {
agent any
stages {
stage('Example') {
input {
message "Should we continue?"
ok "Yes, Do it."
submitter "alice,bob"
parameters {
string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
}
}
steps {
echo "Hello, ${PERSON}, nice to meet you."
}
}
}
}
2.2.10、when(可选)

根据when指令的判断结果来决定是否执行后面的阶段一个when指令至少包含一个条件,当有多个条件时,所有的子条件必须返回true,这个stage才会运行

branch:当正在构建的分支与模式给定的分支匹配时,执行这个阶段, 例如: when { branch ‘master’ }。注意,这只适用于多分支流水线。environment:当指定的环境变量是给定的值时,执行这个步骤, 例如: when { environment name: ‘DEPLOY_TO’, value: ‘production’ }expression:当指定的Groovy表达式评估为true时,执行这个阶段, 例如: when { expression { return params.DEBUG_BUILD } }not:当嵌套条件是错误时,执行这个阶段,必须包含一个条件,例如: when { not { branch ‘master’ } }allOf:当所有的嵌套条件都正确时,执行这个阶段,必须包含至少一个条件,例如: when { allOf { branch ‘master’; environment name: ‘DEPLOY_TO’, value: ‘production’ } }anyOf:当至少有一个嵌套条件为真时,执行这个阶段,必须包含至少一个条件,例如: when { anyOf { branch ‘master’; branch ‘staging’ } }

单条件判断:

pipeline{
agent any
parameters{
string(name:"deploy_env",defaultValue:"test",description:"")
}
stages{
stage("Build Test"){
when{
environment name:"deploy_env",value:"prod"
}
steps{
echo "hello wrold"
}
}
}
}

build结果:

第一次build时,deploy_env的值是 test,stage “Build Test” 被 skipped第二次build时,参数deploy_env设置为 prod,执行 stage “Build Test”

多条件判断:

pipeline{
agent any
parameters{
string(name:"deploy_env",defaultValue:"test",description:"")
string(name:"branch",defaultValue:"test",description:"分支")
}
stages{
stage("Build Test"){
when{
environment name:"branch",value:"master"
environment name:"deploy_env",value:"prod"
}
steps{
echo "Hello world"
}
}
}
}

需满足 branch:master,deploy_env:prod 才会执行流水线。

三、Scripted Pipeline(脚本式)流水线

脚本管道和声明管道一样,是建立在底层管道子系统之上的。与Declarative不同,Scripted Pipeline实际上是一个使用Groovy构建的通用DSL。

Groovy语言提供的大多数功能都可供Scripted Pipeline的方式使用,这意味着它可以是一个非常有扩展性和灵活性的工具,可以用来编写连续交付管道。

stage('Build&Tag&Push&Deploy'){
//把选择的项目信息转为数组
def selectedProjects = "${project_name}".split(',')

for(int i=0;i<selectedProjects.size();i++){
//取出每个项目的名称
def currentProjectName = selectedProjects[i];
//定义镜像名称
def imageName = "${currentProjectName}:${tag}"
//定义newTag
def newTag = sh(returnStdout: true,script: 'echo `date +"%Y%m%d%H%M%S"_``git describe --tags --always`').trim()
//编译,构建本地镜像
sh "sed -i 's#ACTIVEPROFILE#${springProfilesActive}#g' Dockerfile"
sh "mvn clean package -Dmaven.test.skip=true dockerfile:build"
container('docker') {
//给镜像打标签
sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${currentProjectName}:${newTag}"
//登录Harbor,并上传镜像
withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')])
{
//登录
sh "docker login -u ${username} -p ${password} ${harbor_url}"
//上传镜像
sh "docker push ${harbor_url}/${harbor_project_name}/${currentProjectName}:${newTag}"
}

//删除本地镜像
sh "docker rmi -f ${imageName}"
sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${currentProjectName}:${newTag}"
}
def deploy_image_name = "${harbor_url}/${harbor_project_name}/${currentProjectName}:${newTag}"

//基于Helm的方式部署到K8S
container('helm3') {
withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
sh """
helm repo add --username=${username} --password=${password} aliharborrepo http://harbor-test.xxxx.com/chartrepo/sparkx
"""
}
withCredentials([file(credentialsId: 'b8fca5a2-8c91-4456-99aa-071723aae7fe', variable: 'KUBECONFIG')]) {
sh """
mkdir -p /root/.kube/ && echo $KUBECONFIG >/root/.kube/config
echo "Helm应用配置信息确认..."
helm upgrade --install --dry-run --debug ${currentProjectName} --namespace devops aliharborrepo/javaAliTest
--set replicaCount=${replicas}
--set image.repository=${deploy_image_name}
--set service.type=ClusterIP
--set springActive=${springProfilesActive}
--set ingress.enabled=${isIngress}
echo "应用部署..."
helm upgrade --install ${currentProjectName} --namespace devops aliharborrepo/javaAliTest
--set replicaCount=${replicas}
--set image.repository=${deploy_image_name}
--set service.type=ClusterIP
--set springActive=${springProfilesActive}
--set ingress.enabled=${isIngress}
"""
}
}
}
}

四、Declarative pipeline和Scripted pipeline的比较

共同点:

两者都是pipeline代码的持久实现,都能够使用pipeline内置的插件或者插件提供的steps,两者都可以利用共享库扩展。

区别:

两者不同之处在于语法和灵活性。

Declarative pipeline:对用户来说,语法更严格,有固定的组织结构,容易生成代码段,使其成为用户更理想的选择。

Scripted pipeline:更加灵活,因为Groovy本身只能对结构和语法进行限制,对于更复杂的pipeline来说,用户可以根据自己的业务进行灵活的实现和扩展。

五、优化交付流水线性能

随着交付流水线的复杂度越来越高,需要优化交付流水线的性能成为了一个时刻需要关注的问题。

下面是一些常见的优化策略:

5.1、并行执行

使用并行执行可以大大缩短交付流水线的执行时间。Pipeline可以很容易地支持并行执行。

例如,我们可以将测试阶段并行执行:

stage('Test') {
parallel (
"test1" : { sh 'mvn test -Dtest=Test1' },
"test2" : { sh 'mvn test -Dtest=Test2' },
"test3" : { sh 'mvn test -Dtest=Test3' }
)
}

在这个示例中,我们使用了 parallel块 来并行执行。

在parallel块内,我们定义了三个分支来执行测试。分支的名称是任意的,它们将被用作日志输出。每个分支都有自己的命令来执行测试。

5.2、缓存依赖项

使用缓存可以避免在每个阶段中重新下载依赖项。

例如,如果一个项目使用Maven,我们可以在build阶段前缓存Maven仓库:

pipeline {
agent any
stages {
stage('Build') {
steps {
script {
def mvnHome = tool 'Maven-3.8.2'
env.M2_HOME = mvnHome
sh "${mvnHome}/bin/mvn -B -Dmaven.repo.local=$HOME/.m2/repository clean package"
}
}
}
}
post {
success {
cleanWs()
}
}
}

在这个示例中,我们使用了Maven插件的tool方法来定义Maven的版本。然后,我们将M2_HOME设置为我们定义的Maven的路径。

最后,我们在Maven命令中使用-Dmaven.repo.local选项来指定Maven仓库的位置。

5.3、删除不必要的阶段

一些阶段可能不必要并且会大大降低交付流水线的性能。

例如,我们可能只需要在提交代码时执行 buildtest 阶段,而不是在每次构建时执行这些阶段。

示例:

pipeline {
agent any
stages {
stage('Build') {
when {
changeset "src/**"
}
steps {
sh 'mvn clean install'
}
}
stage('Test') {
when {
changeset "src/**"
}
steps {
sh 'mvn test'
}
}
stage('Deploy') {
when {
changeset "src/**"
}
steps {
sh './deploy.sh'
}
}
}
post {
success {
cleanWs()
}
}
}

在这个示例中,我们在build、test和deploy阶段之前添加了when块。当检测到代码库中的更改时,这些阶段才会被执行。

六、总结

Scripted Pipeline 和 Declarative Pipeline 两种流水线定义的主要区别在于语法和灵活性上。

Declarative Pipeline 语法要求更严,需使用 Jenkins 预定义的DSL 结构,使用简单;

Scripted Pipeline 受限很少,限制主要在 Groovy 的结构和语法;

大家可以根据个人或企业的情况选择两种方式,比如如果公司没有 Groovy 技术栈,可以考虑直接使用 Declarative Pipeline, 学习曲线低,可以快速上手;

如果需要对公司的业务场景灵活配置或者对 Groovy 熟悉,那么 Scripted Pipeline 是一个不错的选择;

最后编辑于:2024/1/10 拔丝英语网

admin-avatar

英语作文代写、国外视频下载

高质量学习资料分享

admin@buzzrecipe.com