【DevOps实践】3. Jenkins流水线搭建golang项目持续集成环境

1. 摘要

Jenkins是一个自动化服务器,目前发展超过15年,比较成熟的CI工具(也可以CD)能够实现自动化集成发布。
Jenkins构件任务一般有2种,一种是“构建一个自由风格的软件项目”和“流水线”项目。本文讲解的是使用pipeline流水线搭建一个GO工程的持续集成任务的完整方法。

2. 实践内容

2.1 pipeline流水线简介

本质上,jenkins是一个自动化引擎,它支持许多自动模式。流水线向Jenkins添加了一组强大的工具,支持用例、简单的持续集成到全面的持续交付流水线。 通过对一系列的发布任务建立标准的模板,用户可以利用更多流水线的特性,比如:

代码化: 流水线是在代码中实现的,通常会存放到源代码控制,使团队具有编辑、审查和更新他们项目的交付流水线的能力。

耐用性:流水线可以从Jenkins的master节点重启后继续运行。

可暂停的:流水线可以由人功输入或批准继续执行流水线。

解决复杂发布: 支持复杂的交付流程。例如循环、并行执行。

可扩展性: 支持扩展DSL和其他插件集成。

构建一个可扩展是Jenkins的核心价值,流水线可以通过ShareLibrary的方式来扩展。

2.2 Jenkins环境准备

2.2.1 配置Jenkins的SSH key

由于jenkins需要从gitlab上拉取代码,通过ssh方式。所以需要在jenkins机器上安装git,并且将jenkins机器上生成的ssh密钥的公钥(id_rsa.pub中的内容)添加到gitlab的ssh keys中。

配置username和Email,生成ssh密钥

git config --global user.name "duncan.wang"
git config --global user.email "duncan.wang@artarva.com"
ssh-keygen -t rsa  -C "duncan.wang@artarva.com"

拷贝公钥内容填到gitlab服务器。

2.2.2 配置GitLab connections

(1)配置GitLab connections连接到gitlab拉取代码使用,配置证书,使用gitlab api token。
token从gitlab中获取,在个人设置中有Access Token一栏,创建一个token。

(2)在jenkins的系统管理/凭据管理(manageCredentials)/全局凭证/添加凭证,如下:
把gitlab创建的Feed token填写到API token的位置,描述增加点说明,例如"GITLAB的授权信息",ID不用设置,会被Jenkins系统自动更新出来。

(3)在Jenkins的系统管理处配置gitlab授权配置
授权凭证选择刚才配置的GitLab API token即可。可以点击“Test Connection”,返回显示为"Success"表示连接成功。

Test Connection,显示success则表示配置成功。

(4)配置Jenkins所在服务器拉取代码的服务器私钥访问凭证
该凭证用于在下面章节的流水线配置拉取代码时以私钥访问凭证形式访问目标环境。此处的私钥“Private Key”为“2.2.1 配置Jenkins的SSH key”产生的rsa_privatekey。

2.2.3 配置管道任务梳理

丢弃旧的构建配置为只保留7天,10个构建版本。


2.3 创建流水线任务

(1)输入命名“preproduct-training-ip-demo”,选择流水线风格。


(2)配置Gitlab连接
选择 2.2.2 配置GitLab connections 配置的“artarva”连接。


(3)设置流水线脚本

#!/usr/bin/env groovy

def git_address = "git@101.132.137.193:trainingipmanagement/training-ip-demo.git"
def git_auth = "10a4d4f3-1977-486c-945f-31cfcd8c04db"
def git_branch = "dev"


pipeline {
    agent { node { label "master"}}

    stages {
        stage('1.拉取代码'){
            steps {
             //checkout([$class: 'GitSCM', branches: [[name: '${Branch}']], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_address}"]]])
                 git  branch: "${git_branch}", credentialsId: "${git_auth}", url: "${git_address}"
                     // }
            }
        }


        stage('3.编译程序'){
            steps {
                sh """  
                    export GOPATH=/opt/GOPATH
                    export PATH=$PATH:\$GOPATH/bin
                    go build -o training-ip-demo main.go
            cp training-ip-demo /home/training-ip-management/training-ip-demo       
                """   
            }      
        }  
        
        stage('4.部署程序'){
            steps {
                script{
                    PROCESS_ID = sh(script: "ps aux|grep training-ip|grep -v grep|grep -v jenkins|awk \'{print \$2}\'", returnStdout: true).trim()
                    echo "${PROCESS_ID}"

                    if (PROCESS_ID != "") {
                        sh """
                             echo "Kill process: ${PROCESS_ID}"
                             sudo kill -9 ${PROCESS_ID}
                            """
                    }
                }

                sh """
                JENKINS_NODE_COOKIE=dontKillMe nohup /home/training-ip-management/training-ip-demo/training-ip-demo & 
                """
            }  
        }
    }

    post {
        always{
            script{
                println("流水线结束后,经常做的事情")
            }
        }
            
        success{
            script{
                println("流水线成功后,要做的事情")
            }
            
        }
        failure{
            script{
                println("流水线失败后,要做的事情")
            }
        }
            
        aborted{
            script{
                println("流水线取消后,要做的事情")
            }
            
        }
    }
}

(4) 立即构建
点击“立即构建”,根据输出结果排查问题后即可完成流水线工作,包含
拉取Gitlab版本,编辑代码,部署程序这3个主要步骤。
本样例暂时不包含2.代码静态检查的步骤,后面其他文章再涉及。

截图.png

2.4 典型问题解答

2.4.1 流水线配置的程序后台部署运行正常后即被关闭

问题现象:
在普通的shell环境中,nohup,并且& 某个程序后,会抛到后台执行,在退出当前shell环境后,程序依然可以执行。但是在Jenkins的pipeline中,通过nohup,且使用&之后,step结束后,执行的程序还是会退出,导致程序起不来。

在pipeline中需要使用修改 JENKINS_NODE_COOKIE 的值来解决问题,这样后续结束的时候,后面的sh程序就不会被kill掉了。
例如代码:

        stage('4.部署程序'){
            steps {
                script{
                    PROCESS_ID = sh(script: "ps aux|grep training-ip|grep -v grep|grep -v jenkins|awk \'{print \$2}\'", returnStdout: true).trim()
                    echo "${PROCESS_ID}"

                    if (PROCESS_ID != "") {
                        sh """
                             echo "Kill process: ${PROCESS_ID}"
                             sudo kill -9 ${PROCESS_ID}
                            """
                    }
                }

                sh """
                JENKINS_NODE_COOKIE=dontKillMe nohup /home/training-ip-management/training-ip-demo/training-ip-demo & 
                """
            }  
        }

2.4.2 GO编译命令不认识

问题现象:
Jenkins有如下输出,表示go 命令找不到。

[Pipeline] { (3.编译程序)[](https://jenkins.artarva.com/job/preproduct-training-ip-demo/5/console#) [Pipeline] sh[](https://jenkins.artarva.com/job/preproduct-training-ip-demo/5/console#) + export GOPATH=/opt/GOPATH
+ GOPATH=/opt/GOPATH
+ export PATH=/usr/local/bin:/usr/local/java/jdk1.8.0_212//bin:/usr/local/java/jdk1.8.0_212//jre/bin:/usr/local/mycat/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/opt/GOPATH/bin
+ PATH=/usr/local/bin:/usr/local/java/jdk1.8.0_212//bin:/usr/local/java/jdk1.8.0_212//jre/bin:/usr/local/mycat/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/opt/GOPATH/bin
+ go build -o training-ip-demo main.go
/var/lib/jenkins/workspace/preproduct-training-ip-demo@tmp/durable-86459043/script.sh: line 4: go: command not found</pre>

运行的对应流水线脚本为:

        stage('3.编译程序'){
            steps {
                sh """  
                    export GOPATH=/opt/GOPATH
                    export PATH=$PATH:\$GOPATH/bin
                    go build -o training-ip-demo main.go
            sudo cp training-ip-demo /home/training-ip-management/training-ip-demo       
                """   
            }      
        } 

问题分析:
JENKINS下,默认采用Jenkins账号运行。该账号下的PATH并没有包含GO的环境,上面脚本的路径也写错了。改为如下即可成功运行。
运行成功的对应流水线脚本为:

        stage('3.编译程序'){
            steps {
                sh """  
                    export GOROOT=/opt/module/go
                    export PATH=$PATH:\$GOROOT/bin
                    go build -o training-ip-demo main.go
            sudo cp training-ip-demo /home/training-ip-management/training-ip-demo       
                """   
            }      
        } 

关于Jenkins pipeline单引号、双引号和转义字符的说明参考 https://blog.csdn.net/nklinsirui/article/details/100539935 这篇文章。

3.参考

(1)Jenkins持续集成Go项目
https://www.pianshen.com/article/8603599995/

(2)Jenkins流水线(pipeline)实战之:golang项目
https://blog.csdn.net/qq_36270681/article/details/105449608
【说明】
[1]安装插件,按照次更新了镜像
jenkins Publish over SSH 的配置与使用
https://www.cnblogs.com/yechen2019/p/11529755.html
[2] 流水线失败,不用。
[3] GIT相关命令
https://www.jenkins.io/doc/pipeline/steps/git/
[4] SHELL相关命令
https://www.jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#sh-shell-script
[5] jenkins全局变量
https://wiki.jenkins.io/display/JENKINS/Building+a+software+project#Buildingasoftwareproject-JenkinsSetEnvironmentVariables
https://jenkins.artarva.com/env-vars.html/
[6]官方groovy语法
http://docs.groovy-lang.org/latest/html/documentation/core-operators.html#_conditional_operators

(3)使用Docker+Jenkins实现Go语言项目的持续集成
https://juejin.cn/post/6844904152829542413
【说明】自由风格构件成功GO项目,不是流水线

(4)使用Docker+Jenkins实现Go语言项目的持续集成
https://juejin.cn/post/6844904152829542413
【说明】自由风格构件成功GO项目,不是流水线

(5)搭建jenkins+gitlab持续集成环境
https://jingyan.baidu.com/article/5552ef47fbb9b3518ffbc983.html
【说明】构建项目部分未使用。

(6)Jenkins集成Gitlab配置提交流水线
https://blog.csdn.net/valada/article/details/104272152

(7)基于GitLab CI搭建Golang自动构建环境
https://segmentfault.com/a/1190000019525332
【说明】将直接在GitLab上部署自动化构件环境的。

(8)Jenkins中使用GitLab的配置
https://www.cnblogs.com/gongxr/p/9257434.html

(9)JENKINS插件查询的地方
https://plugins.jenkins.io/
https://blog.csdn.net/valada/article/details/104272154

(10)Jenkins中pipeline后台进程起不来的问题
https://shanhy.blog.csdn.net/article/details/79637311
【说明】有效,采用JENKINS_NODE_COOKIE=dontKillMe解决。

(11)Jenkins pipeline中优雅的执行shell/python/groovy脚本
https://www.jianshu.com/p/2cdc8efedf2f

(12)Jenkins pipeline单引号、双引号和转义字符
https://blog.csdn.net/nklinsirui/article/details/100539935

(13)Jenkins实践
http://www.idevops.site/jenkins/

(14)版本控制系统集成
http://www.idevops.site/jenkins/pipelineintegrated/chapter03/

(15)Groovy 语法教程
https://www.w3cschool.cn/groovy/
【说明】
<1> DEF 是在 Groovy 用来定义标识符的关键字。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容