欢迎您, 来到 宁时修博客.^_^

Jenkins自动化 持续集成04--Jenkins pipeline插件

2018/11/09 言则行 Jenkins 1073
Jenkins自动化 持续集成

一、pipeline是什么

    Jenkins Pipeline(或者简称为“Pipeline”)是一套插件,支持在 Jenkins 中实施和集成持续交付流水线。

    持续交付(CD)流水线是将软件从版本控制发布到用户和客户的过程的自动化表达。对软件的每一次改变(在源代码控制中提交)都会在发布过程中经历一个复杂的过程。这个过程包括以可靠和可重复的方式构建软件,以及通过测试和部署的多个阶段来推进构建的软件(称为“构建”)。

    Pipeline 提供了一套可扩展的工具,用于通过 Pipeline domain-specific language(DSL)语法将交付流水线“作为代码”建模。

    Jenkins Pipeline 的定义写在称为 Jenkinsfile 的文本文件中,这个文件可以提交到项目的代码控制仓库。这是“Pipeline-as-code”的基础。 将 CD 流水线作为应用程序的一部分进行版本控制,并像任何其他代码一样进行审查。


    创建 Jenkinsfile 文件并且提交到版本控制有下面几个好处:

        对所有的 branches 和 pull 请求自动创建 Pipeline。

        Pipeline 上的代码审查/迭代(along with the remaining source code)。

        审核追踪 Pipeline

        Pipeline 的单一真实来源,可由项目的多个成员查看和编辑。


    虽然用于定义 Pipeline 的语法无论是在 Web UI 中还是在 Jenkinsfile 中是相同的,但在 Jenkinsfile 中定义 Pipeline 并提交到源代码控制中通常被认为是最佳实践。


二、pipeline基本概念

    Pipeline

    Pipeline 是一个用户定义的 CD 流水线模式。Pipeline 代码定义了通常包含构建、测试和发布步骤的完整的构建过程。

    同时,pipeline 代码块也是声明式 Pipeline 语法的关键特性。


    Node

    node 是一个机器,一个node就是一个jenkins节点,是执行 Step 的具体运行环境,Pipeline 执行中的大部分工作都是在一个或多个声明 Node 步骤的上下文中完成的。

    同时,node 代码块也是脚本式 Pipeline 语法的关键特性。


    Stage

    Stage 块定义了在整个 Pipeline 中执行的概念上不同的任务子集(例如“构建”,“测试”和“部署”阶段),许多插件使用它来可视化或呈现 Jenkins 管道状态/进度。


    Step

    一项任务。从根本上讲,一个步骤告诉 Jenkins 在特定时间点(或过程中的“步骤”)要做什么。例如,使用 sh step:sh 'make' 可以执行 make 这个 shell 命令。 当一个插件扩展了 Pipeline DSL 时,通常意味着该插件已经实现了一个新的步骤。



三、Pipeline 语法概述

    下面的 Pipeline 代码框架说明了声明式与脚本式 Pipeline 语法之间的基本区别。

    上述的阶段(stage)和步骤(step)都是声明式与脚本式 Pipeline 语法的常见元素。


    1、声明式 Pipeline 基础

    在声明式 Pipeline 语法中,pipeline 块定义了贯穿 Pipeline 的所有的工作。

Jenkinsfile (Declarative Pipeline)
pipeline {
    agent any  //在任何可用的代理上执行这个 Pipeline 或其任意 stage
    stages {
        stage('Build') { //定义 "Build" stage
            steps {
                // 执行和 "Build" stage 相关的step
            }
        }
        stage('Test') { // 定义  "Test" stage
            steps {
                // 执行和 "Test" stage 相关的step
            }
        }
        stage('Deploy') { 
            steps {
                // 执行和 "Deploy" stage 相关的step
            }
        }
    }
}



    2、脚本式 Pipeline 基础

        在脚本式 Pipeline 语法中,一个或多个 node 块执行贯穿整个 Pipeline 的核心工作。虽然这不是脚本式 Pipeline 语法的强制性要求,但将管道 work 限制在 node 块内部会做两件事情:

    1)通过将 item 添加到 Jenkins 队列来运行块中包含的 step。只要执行程序在 node 上空闲,这些步骤就会运行。

    2)创建一个工作空间(特定于该特定 Pipeline 的目录),其中可以对从源代码管理检出的文件执行工作。 

    注意:根据不同的 Jenkins 配置,部分 workspaces (工作空间)不会在一段不活动时间之后自动清理。

Jenkinsfile (Scripted Pipeline)
node {  //在任何可用的代理上执行这个 Pipeline 或其任意 stage
    stage('Build') { //定义 "Build" stage
        // 执行和 "Build" stage 相关的 step
    }
    stage('Test') { 
        // 执行和 "Test" stage 相关的step
    }
    stage('Deploy') { 
        // 执行和 "Deploy" stage 相关的step
    }
}

    脚本式 Pipeline 中,stage 块是可选的。但是,在脚本式 Pipeline 中实现 stage 块可以更清晰地显示 Jenkins UI 中每个阶段的 tasks/steps。


四、Pipeline示例

    下面是Jenkinsfile 的例子使用声明式 Pipeline 语法:

Jenkinsfile (Declarative Pipeline)
pipeline { 
    agent any 
    stages {
        stage('Build') { 
            steps { 
                sh 'make' 
            }
        }
        stage('Test'){
            steps {
                sh 'make check'
                junit 'reports/**/*.xml' 
            }
        }
        stage('Deploy') {
            steps {
                sh 'make publish'
            }
        }
    }
}


    与上面对应的脚本式 Pipeline 语法:

Jenkinsfile (Scripted Pipeline)
node { 
    stage('Build') { 
        sh 'make' 
    }
    stage('Test') {
        sh 'make check'
        junit 'reports/**/*.xml' 
    }
    stage('Deploy') {
        sh 'make publish'
    }
}


五、安装插件和实践

    1、安装pipeline插件

    一般jenkins安装时会推荐插件安装,里面包含pipeline,如果没有安装,就这样:

    系统管理--插件管理--可选插件--搜索Pipeline安装插件


    2、实践

    新建任务:

        01.png


    

    编写pipeline脚本:

        4.png


    借助流水线语法,脚本如下:

node {
    stage('build jar') { 
        echo "build jar"
   }
   
    stage('build exchange-config') {
        echo "build exchange-config"
   }

    stage('build operate-web') {
        echo "build operate-web"
   }
	
    stage('deploy operate-web') {
        echo "deploy operate-web"
   }

    stage('backup operate-web') {
        echo "backup operate-web"
   }

}

    我这没有拉取代码,要拉取代码,可以加上以下:

stage('git checkout') { // for display purposes
    checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[url: 'git@192.168.184.123:root/test01.git']]])
}

    当然也可以看文末的拉取方式。


    开始构建:

        29.png

    控制台输出:

            7.png


        我们也可以从Gitlab中读取pipeline脚本(就是将pipeline脚本放在仓库中)。

        首先我们需要将pipeline脚本提交到我们新建的git仓库中。

        jenkins项目中需要进行如下配置:

       00.png

        jenkinsfile文件路径要写对,我的文件就在gitlab项目主目录下,如果jenkinsfile文件在gitlab项目中的  repos/jenkinsfile,那么就scripts path就写 repos/jenkinsfile 。



        构建还是成功的:

        11.png


    之后如果要更改步骤,不再更改jenkins的步骤,直接更改jenkinsfile文件即可。


六、附录:jenkins节点与pipeline

    还没有做主从,只有一台jenkins服务器,如果做了主从,那么写pipeline脚本需要注意写上jenkins节点名称,指定相应jenkins节点去执行pipeline脚本。

    master节点可以不写,其它slave节点需要写,格式为:node ("节点名称")。如下示例:

node("slave-jenkins") {
   stage('build jar') { 
        echo "build jar"
   }
}



七、附录:我以前用过的线上pipeline脚本

    公司已倒闭,写出来留个记录。这是Java项目。

    

node("slave-ut-online-jenkins") {
   stage('build jar') { 
        sh '''
	source /etc/profile
        a=(exchange-cache exchange-common exchange-dao stats-dao operate-service)
         for i in ${a[@]}
            do
                echo "-----------------开始构建$i---------------------"
                cd /jenkins/code/game/xhv2-$i
                if [ `git branch|grep "* master"|wc -l` -ne 1 ]
                    then
                        git checkout master
                fi
                git pull
               /usr/local/maven-3.5.4/bin/mvn clean install -Dmaven.test.skip=true
                
        done
        
        '''
   }
   

    stage('build exchange-config') {
        sh '''
	source /etc/profile
        a=exchange-config
        echo "---------------------------------开始构建$a--------------------------------------"
        cd /jenkins/code/game/$a
        if [ `git branch|grep "* master"|wc -l` -ne 1 ]
            then
                git checkout master
        fi
        git pull
        echo -----------
        /usr/local/maven-3.5.4/bin/mvn clean install -Poperate-web-prod -Dmaven.test.skip=true
        '''
   }


    stage('build operate-web') {
        sh '''
	source /etc/profile
        a=operate-web
        echo "---------------------------------开始构建$a--------------------------------------"
        cd /jenkins/code/game/xhv2-$a
        if [ `git branch|grep "* master"|wc -l` -ne 1 ]
            then
                git checkout master
        fi
        git pull
        echo -----------
        /usr/local/maven-3.5.4/bin/mvn clean package -Dmaven.test.skip=true
        '''
   }
	
    stage('deploy operate-web') {
        sh '''
	a="operate-web"
	deploy_ip=172.16.1.16
        deploy_path="/application/tomcat-game/webroot"
        glnr="'tomcat8-game-operate-web-8071/temp org.apache'"
        bin="/application/tomcat-game/tomcat8-game-operate-web-8071/bin/catalina.sh"
        war_path="/jenkins/code/game/xhv2-$a/target/$a.war"
	echo "---------------------------------开始发布$a--------------------------------------"
	ssh gx@${deploy_ip} "
		$bin stop
		sleep 4
		[ \\$(ps -ef |grep "${glnr}" |grep -v 'grep' |wc -l) -gt 0 ] && \
		ps -ef |grep ${glnr} |grep -v 'grep' |awk '{print \\$2}' | xargs kill -9 || \
		echo "tomcat is stopped !!!!!!!!"
		sleep 1
		cd ${deploy_path}/ && rm -fr operate-web/*
		"
		
        scp $war_path  gx@${deploy_ip}:${deploy_path}/operate-web/
        
        ssh gx@${deploy_ip}  "
            cd ${deploy_path}/operate-web/ && /usr/local/jdk1.8.0_181/bin/jar xf ${a}.war && mv ${a}.war ${deploy_path}/ && cd /home/gx
            sleep 1
            $bin start
        "
        
        '''
   }
   
   stage('backup operate-web') {
        sh '''
	a="operate-web"
	b="game-operate-web"
	bak_path=/jenkins/bak/$b
	bak_name=$a-`date '+%Y-%m-%d'`
	war_path="/jenkins/code/game/xhv2-$a/target/$a.war"
	echo "----------------------------------开始备份$a------------------------------------"
        mkdir -p ${bak_path}
		cp ${war_path} ${bak_path}/${bak_name}
		/bin/sh /jenkins/bak/del_oldfiles.sh $b
        /bin/sh /jenkins/bak/get_name.sh
		du -sh ${bak_path}/*
        '''
   }

}


点赞
说说你的看法

所有评论: (0)

# 加入组织

1、用手机QQ扫左侧二维码

2、搜Q群:1058582137

3、点击 宁时修博客交流群