jenkins 脚本编写_使用Jenkins 2编写以代码形式编写管道和实现DevOps的简介

jenkins 脚本编写

DevOps的关键思想之一是“ 基础结构即代码”(具有用代码表示交付/部署管道的基础结构),就像流过它的产品一样。

Jenkins工作流工具是用于创建许多持续交付/部署管道的主要应用程序之一。 这通常是通过为各种管道任务定义一系列单独的作业来完成的。 每个作业都通过Web表单进行配置-填写文本框,从下拉列表中选择条目,等等。然后将一系列作业串在一起,每个作业触发下一个,进入管道。

尽管得到了广泛使用,但是这种创建和连接詹金斯工作以形成管道的方法具有挑战性。 它不符合“ 基础设施即代码”的定义。 作业配置仅作为XML文件存储在Jenkins配置区域中。 这意味着文件不容易阅读或直接修改。 Jenkins应用程序本身提供了用户的主视图以及对它们的访问。

我们通常将Jenkins 2命名为支持流水线代码功能以及其他功能的较新版本。)在本文中,我们将学习如何在Jenkins 2中创建流水线作为代码。这将使用两种不同样式的管道语法(脚本式和声明式)来完成。 我们还将介绍如何在Jenkins外部存储管道代码,但仍然需要Jenkins在更改时运行它,以实现实现DevOps的目标之一。

让我们从基础开始。 Jenkins及其插件通过其自己的编程步骤(Jenkins领域专用语言(DSL))使构建基块可用于您的管道任务。

DSL步骤

当詹金斯开始向流水线代码模型发展时,一些最早的更改是以插件的形式出现的— 工作流插件。 这包括创建一组初始DSL步骤,以允许在Jenkins中编写简单的作业,并通过扩展对简单的管道进行编码。

如今,许多不同的插件提供了Jenkins中可用的不同DSL步骤。 例如,我们通过Git插件提供了一个git步骤,以从源代码控制系统中检索源代码。 清单1显示了其用法的示例:


   
   
node ('worker_node1') {
     stage('Source') {
         // Get some code from our Git repository
         git 'http://github.com/brentlaster/roarv2'
      }
}

清单1:使用Git步骤的示例管道代码行。

实际上,为了与Jenkins 2兼容,当前的插件有望提供用于管道的DSL步骤。 管道包含DSL步骤,以执行传统上通过Web表单执行的操作。 但是,要构成完整的管道,还需要其他支撑件和结构。 Jenkins 2允许两种样式的结构和语法来构建管道。 这些被称为脚本化声明性

脚本管道

现在,在Jenkins 2中创建管道的原始方法称为脚本化 。 在最高级别, 脚本化管道被包装在一个节点块中。 这里的节点是指包含Jenkins 代理程序片段并且可以运行作业(以前称为从属实例)的系统。 该节点通过使用标签映射到系统。 标签只是在Jenkins中配置一个或多个节点(通过全局“ 管理节点”部分完成)时添加的标识符。 一个示例如图1所示。

Figure 1. Node configuration with labels

图1:带有标签的节点配置

节点Groovy编程语言中的一种称为闭包的构造(由开括号和闭括号表示)。 实际上,脚本化管道可以包括并利用任何有效的Groovy代码。 作为示例,清单2显示了执行以下操作的脚本管道代码:

  • 检索源代码(通过git pipe步骤);
  • 获取全局定义的Gradle安装的值(通过tool管道步骤),并将其放入Groovy变量中; 和
  • 调用外壳执行它(通过sh管道步骤):
    
         
         
    // Scripted Pipeline
    node ('worker_node1') {
      // get code from our Git repository
      git 'http://github.com/brentlaster/roarv2'
       // get Gradle HOME value
      def gradleHome = tool 'gradle4'
       // run Gradle to execute compile and unit testing
      sh "'${gradleHome}/bin/gradle' clean compileJava test"
    }

清单2:使用该工具和sh步骤的脚本语法

这里gradleHome是一个Groovy变量,用于支持DSL步骤。 可以通过Jenkins定义这样的管道,方法是创建一个新的Pipeline项目,并在新项目页面底部的Pipeline Editor部分中键入代码,如图2所示:

Figure 2: Defining a new Pipeline project

图2:定义一个新的管道项目

尽管此简单的节点块在技术上是有效的语法,但Jenkins管道通常具有更高级的粒度阶段。 阶段是将管道划分为逻辑功能单元的一种方式。 它还可以将DSL步骤和Groovy代码组合在一起以实现目标功能。 清单3显示了我们的脚本化管道,其中包含构建阶段的阶段定义和源管理阶段的阶段定义:


   
   
// Scripted Pipeline with stages
node ('worker_node1') {
  stage('Source') { // Get code
    // get code from our Git repository
    git 'http://github.com/brentlaster/roarv2'
  }
  stage('Compile') { // Compile and do unit testing
    // get Gradle HOME value
    def gradleHome = tool 'gradle4'
    // run Gradle to execute compile and unit testing
    sh "'${gradleHome}/bin/gradle' clean compileJava test"
  }
}

清单3:带有阶段的脚本语法

在新的默认Jenkins输出屏幕( 舞台视图)中,管道中的每个阶段都具有自己的输出区域。 如图3所示,“阶段视图”输出以矩阵形式组织,每一行代表作业的运行,每一列都映射到管道中定义的阶段:

Figure 3: Defined stages and Stage View output

图3:定义的阶段和阶段视图输出

此矩阵中的每个单元格(行和列的交集)还显示计时信息,并使用颜色指示成功或失败。 表1显示了每种颜色的关键:

表1:舞台执行的颜色代码

Color

含义
White 阶段尚未运行
Blue stripes 处理中
Green 阶段成功
Red 阶段成功,但下游阶段失败
Red stripes 阶段失败

另外,通过将鼠标悬停在该单元上,弹出窗口将提供有关该阶段执行的更多信息,并带有指向日志的链接,如图4所示:

Figure 4: Drilling down into the logs in stage output

图4:钻取阶段输出中的日志

尽管脚本化管道提供了很大的灵活性,并且使程序员感到舒适和熟悉,但是对于某些用户而言,它们确实有其缺点。 特别是:

  • 感觉就像您需要了解Groovy才能创建和修改它们。
  • 对于传统的詹金斯用户来说,学习如何使用它们可能具有挑战性。
  • 它们提供Java样式的回溯以显示错误。
  • 没有内置的生成后处理。

如果您习惯于执行诸如通过Freestyle作业中的后构建处理发送电子邮件通知或归档结果之类的任务,则上面列表中的最后一项可能是一件大事。 如果您的脚本管道代码失败并引发异常,则可能永远无法到达管道末端; 但是,您可以在主要的脚本管道代码周围使用Java样式的try-catch块来处理此问题,如图5所示:

Figure 5: try-catch block to emulate post-build notifications

图5:try-catch块模拟构建后的通知

在这里,我们有一个称为Notify最后阶段。 无论管道的早期部分成功还是失败,都将始终执行此阶段。 这是因为try-catch结构将捕获由故障引起的任何异常,并允许控制随后继续。 (Jenkins 2也有一个catchError块,它是try-catch构造的简化的受限版本。)

这种解决方法增加了一种印象,即您需要了解一些编程才能在以前使用Freestyle免费获得的脚本管道中执行操作。 为了简化来自传统Jenkins的开发人员的工作,并从Java / Groovy-ism中脱颖而出,CloudBees和Jenkins社区创建了第二种语法风格来编写管道-声明式。

声明式管道

顾名思义,声明式语法更多地是在管道中声明您想要的内容,而不是编码要执行此操作的逻辑。 它仍然使用DSL步骤作为基础,但在步骤周围包括定义明确的结构。 该结构包括许多指令和部分,用于指定管道中所需的项目。 清单4中显示了一个示例性声明式管道:


   
   
pipeline {
  agent { label 'worker_node1' }
  stages {
    stage('Source') { // Get code
      steps {
        // get code from our Git repository
        git 'https://github.com/brentlaster/roarv2'
      }
    }
    stage('Compile') { // Compile and do unit testing
      tools {
        gradle 'gradle4'
      }
      steps {
        // run Gradle to execute compile and unit testing
        sh 'gradle clean compileJava test'
      }
    }
  }
}

清单4:声明性管道示例

您在这里可能会注意到的第一件事是,我们在代码周围有一个agent块,而不是一个node块。 您可以将代理程序和节点视为同一件事,即指定要在其上运行的系统。 (但是,代理程序还包括其他创建系统的方法,例如通过Dockerfiles。)

除此之外,我们在管道中还有其他指令块,例如工具一,在其中声明要使用Gradle的安装(而不是像脚本语法那样将其分配给变量)。 在声明性语法中,不能使用Groovy代码(例如赋值或循环)。 您仅限于结构化的部分/块和DSL步骤。

此外,在声明性管道中,必须将一个步骤中的DSL步骤包含在步骤指令中。 这是因为除了阶段中的步骤之外,您还可以声明其他内容。

图6显示了Jenkins 2:启动和运行手册中的图表,其中包含声明性管道中的所有部分。 读取此图表的方式是,需要带有实线边框的项目,而带有虚线边框的项目是可选的:

Figure 6: Diagram of Declarative Pipeline sections

图6:声明性管道部分的示意图

您可能可以从它们的名称中了解不同部分的功能。 例如, 环境设置环境变量,而工具声明我们要使用的工具应用程序。 我们不会在这里详细介绍每一个细节,但是这本书有整整一章关于声明性管道。

请注意,这里有一个帖子部分。 这可以模拟Freestyle作业中的后生成处理功能,并且不需要像在脚本管道中使用的try-catch构造那样的语法。 还要注意, post块也可以在阶段结束时发生。

这种明确定义的结构为在Jenkins中使用声明性管道提供了多个优势。 它们包括:

  • 从Freestyle到代码管道的转换更容易,因为您在声明所需内容(类似于在传统Jenkins中填写表单的方式);
  • 更严格,更清晰的语法/要求检查; 和
  • 与新的Blue Ocean图形界面更紧密地集成(管道图中结构良好的部分更易于单个图形对象使用)。

您可能想知道声明性管道的缺点是什么。 如果您需要超出声明性语法所允许的范围,则必须采用其他方法。 例如,如果您想为变量分配一个值并在管道中使用它,则不能使用声明性语法。 有些插件还可能需要某种东西才能在管道中使用它们。 因此,它们与声明性语法不直接兼容。

在那种情况下你会怎么做? 您可以在阶段中围绕少量非声明性代码添加脚本块。 声明性管道中脚本块中的代码可以是任何有效的脚本语法。

对于更大量的非声明性代码,推荐的方法是将其放入外部库(在Jenkins 2中称为共享管道库 )。 还有一些其他方法,这些方法受到的制裁较少-意味着将来可能不会支持它们。 (如果您有兴趣了解更多信息,那么“ Jenkins 2:启动并运行”一书详细介绍了共享库和其他替代方法。)

希望这可以使您很好地了解Jenkins 2中的脚本化管道和声明性管道之间的区别。在这里要考虑的最后一个方面是,对于Jenkins 2,您不需要将管道代码存储在Jenkins应用程序本身中。 您可以将其创建为(或复制到)具有特殊名称Jenkinsfile的外部文本文件中。 然后可以将该文件与源代码一起存储在所需分支的同一存储库中。

詹金斯档案

尽管Jenkins应用程序是开发和运行管道的主要环境,但是管道代码本身也可以放置在名为Jenkinsfile的外部文件中。 这样,我们便可以将管道代码视为其他任何文本文件,这意味着可以将其存储在源代码管理中并在源代码管理中进行跟踪,并进行常规的过程(例如代码审查)。

此外,流水线代码可以与产品源一起存储并与之一起使用,从而使我们可以将流水线作为基础结构即代码来实现。

图7显示了存储在源代码控制存储库中的Jenkins文件:

Figure 7: Jenkinsfile in source control

图7:源代码管理中的Jenkinsfile

源代码管理中Jenkinsfile的内容如图8所示:

Figure 8: An example Jenkinsfile

图8:示例Jenkinsfile

您可能会认为这是我们较早版本的管道的精确副本,但是有一些细微的差异。 首先,我们在顶部添加了groovy标记。 但是,更重要的是,请注意从源代码控制系统获取代码的步骤。 代替我们先前使用的git步骤,我们有一个scm checkout步骤。 这是您可以在Jenkinsfile中使用的快捷方式。 由于Jenkinsfile与它将在其上运行的代码位于相同的存储库(和分支)中,因此它已经假定这是应从中获取源代码的位置。 这意味着我们不需要明确地告诉它该信息。

使用Jenkinsfile的优点是您的管道定义与通过管道的产品源一起使用。 然后,您可以在Jenkins中创建一个Multibranch Pipeline类型的项目,并通过作业配置的“ 分支源”部分将其指向带有Jenkinsfile的源存储库。 图9显示了两个步骤:

Figure 9: Creating and configuring a Multibranch Pipeline
Figure 9: Creating and configuring a Multibranch Pipeline

图9:创建和配置多分支管道

然后,Jenkins将扫描存储库中的每个分支,并检查该分支是否具有Jenkinsfile。 如果是这样,它将在Multibranch Pipeline项目中自动创建并配置一个子项目,以运行该分支的管道。 图10显示了运行扫描并寻找Jenkinsfiles以在多分支管道中创建作业的示例:

Figure 10: Jenkins checking for Jenkinsfiles to automatically setup jobs in a Multibranch Pipeline

图10:Jenkins检查Jenkinsfiles以在多分支管道中自动设置作业

图11显示了针对Jenkins文件和源存储库执行后的多分支管道中的作业:

Figure 11: Automatically created Multibranch Pipeline jobs based on Jenkinsfiles in source code branches

图11:基于源代码分支中的Jenkinsfiles自动创建的多分支管道作业

使用Jenkinsfiles,我们可以实现将基础架构(或至少是管道定义)视为代码的DevOps目标。 如果需要更改管道,则可以像在其他文件中一样在源代码控制中拉,编辑和推送Jenkins文件。 我们还可以在管道脚本上执行诸如代码审查之类的事情。

使用Jenkinsfiles有一个潜在的弊端:在外部文件中而不是在Jenkins应用程序环境中工作时,提前发现问题可能更具挑战性。 解决此问题的一种方法是首先在Jenkins应用程序中将代码开发为管道项目。 然后,您可以随后将其转换为Jenkinsfile。 此外,还有一个声明性管道短绒应用程序,您可以针对Jenkins之外的Jenkinsfiles运行它,以及早发现问题。

结论

希望本文对脚本化和声明性管道的区别和使用以及如何将它们作为Jenkinsfiles包含在源中提供了很好的了解。 如果您想在Jenkins 2中找到有关这些主题或相关主题的更多信息,可以在网上搜索或查阅《 Jenkins 2:启动并运行》一书,以获取有关使用此技术为DevOps赋权的更多示例和说明。在您的组织中。

翻译自: https://opensource.com/article/18/8/devops-jenkins-2

jenkins 脚本编写

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值